- https://http-ip.tools.pingproxies.com. Responds to any HTTP request with your IP address.
- tcp-echo.tools.pingproxies.com:40000. Accepts TCP connections and returns any bytes received.
- udp-echo.tools.pingproxies.com:50000. Accepts UDP datagrams and returns any bytes received.
- udp-ip.tools.pingproxies.com:50001. Accepts UDP datagrams and returns your IP address.
We try to showcase different libraries and methods for proxying. If an example uses a different library to the one you are using, check the other examples.
- Python examples rely on implicit behaviours of modules to execute different proxying methods.
- Rust examples are more explicit and show exactly how the mechanisms of proxying work.
SOCKS5
SOCKS proxies allow you to tunnel both TCP and UDP traffic, making them a very good choice for things like gaming or VOIP (Voice over IP).SOCKS5 TCP
SOCKS5 TCP
- Python
- Rust
main.py
requests
allows us to quickly establish a SOCKS5 connection and send a HTTP request over it.SOCKS5 UDP
SOCKS5 UDP
For our UDP examples, we use the PingProxies UDP test server. This server, open and free to everyone, returns the IP addresss of any connection formed with it.For SOCKS UDP proxying we rely on
- Python
- Rust
main.py
PySocks
, which provides an API like that of the socket
module, except the data sent on the socket gets proxied.PySocks
has a bug and performs UDP proxying slightly wrong - a result of them misunderstanding the RFC. If you change the False
to True
, this will cause proxying to fail even though it should work fine. We have a PR to PySocks
submitted and waiting to be merged.HTTP
HTTP proxies can either tunnel TPC traffic, or HTTP request. They do this by using the CONNECT method for establishing TCP tunnels or acting as a man in the middle, directly forwarding any non-CONNECT requests it receives.HTTP/1.1
HTTP/1.1
HTTP/1.1 CONNECT
HTTP/1.1 CONNECT
The CONNECT method is very simple. Simply send your target destination and proxy credentials to the proxy server in a request using the CONNECT method. The proxy server will establish a tunnel to that target server, send you a 200 OK telling you the proxy tunnel has been established, then blindly funnel bytes between you and your target.
- Python
- Rust
main.py
requests
lets us quickly establish a proxy connection and send a HTTP request over it. Any proxy request to a HTTPS target will use a CONNECT to establish the proxy tunnel.HTTP/1.1 MITM
HTTP/1.1 MITM
MITM proxying is even simpler than the CONNECT method. Simply send your request directly to the server and it will forward it for you. Unfortunately, the simplicity of MITM proxying is offset by security risks as you can no longer perform TLS to the Target to encrypt your data and hide it from anyone listening and even the proxy server itself.
- Python
- Rust
main.py
requests
lets us quickly establish a proxy connection and send a HTTP request over it. Any proxy request to a HTTP target will use MITM-style proxy requests.HTTP/2
HTTP/2
HTTP/2 offers many advantages over HTTP/1.1. You can read about (or watch) these advantages in our blog here. To summarise however, HTTP/2 lets you send multiple requests over the same connection, concurrently. Alllowing greater throughput with lower overhead.You can’t just speak HTTP/2 with a server, as not all servers support it. Fortunately, there exist three methods turning a TCP connection into a HTTP/2 connection:
As with HTTP/1.1, any requests to a HTTP target will be sent MITM-style. The connection is re-used, just as it is in the HTTP/2 CONNECT example.
- Prior Knowledge. Just asssume it speaks HTTP/2.
- HTTP/1.1 Ugprade. Speak HTTP/1 to the server and ask it to do HTTP/2.
- ALPN. When doing the TLS handshake, ask the server what protocols it supports.
HTTP/2 CONNECT
HTTP/2 CONNECT
CONNECTs with HTTP/2 work just the same as in HTTP/1.1, except you can send multiple of them over the same connection at the same time. In this example, we use ALPN to upgrade our connection to HTTP/2 and send a HTTP/2 CONNECT.
- Python
main.py
httpx
is a more modern and feature-rich HTTP library. Unlike requests
, it supports versions other than HTTP/1.1 and will use ALPN to upgrade requests (including those to a proxy) where possible.HTTP/2 MITM
HTTP/2 MITM
- Python
main.py
HTTP/3
HTTP/3
The CONNECT method, even when used with HTTP/3 proxies which operate over UDP and QUIC, still establishes a TCP connection to the target. If you wish to establish UDP proxy connection using HTTP/3 “connection” to the target, you need to use the as-yet unsupported (by everyone, everywhere) CONNECT-UDP method. Alternatively, using SOCKS5 UDP.This means that there is currently no way to use HTTP/3 to establish a tunnel over which you can send HTTP/3 traffic. MITM-style porxying does allow you to send HTTP/3 requests to your end target however.
This example shows how you can use the
This shows how to proxy MITM style requests. In this case, we receive your HTTP/3 request, establish a HTTP/3 connection to your target server, execute the TLS handshake and then forward your request. This lets you proxy HTTP/3 to the end target, but in return we are able to see everything in your Requests and Responses.
HTTP/3 CONNECT
HTTP/3 CONNECT
- Rust
main.rs
h3
crate to execute a CONNECT request and proxy TCP trafific. If you wish to proxy traffic other than TCP, you’ll need to use the CONNECT-UDP or CONNECT-IP methods.HTTP/3 is still relatively new and unsupported. HTTP/3 proxying even more so.HTTP/3 MITM
HTTP/3 MITM
- Rust
main.rs
HTTP/3 over SOCKS5 UDP - Controlling Your Fingerprint
The example above shows how to proxy TCP traffic over a HTTP/3 connection. The examplebelow shows how to proxy HTTP/3 using a UDP proxy. Most proxy providers who talk about “HTTP/3 proxying” mean this second option. When proxying HTTP/3 using a HTTP/3 MITM proxy, the proxy server is responsible for performing the TLS handshake with the target. As such, you end up with a TLS fingerprint (JA3/JA4) that might not be ideal for your use-case. Until the CONNECT-UDP method becomes widespread, the best option is proxy your HTTP/3 traffic using SOCKS5 UDP proxies.- Rust
main.rs