/trio_http_proxy

Simple HTTP CONNECT proxy implemented with trio

Primary LanguagePythonMozilla Public License 2.0MPL-2.0

trio_http_proxy.py

Simple HTTP CONNECT proxy implemented with Trio.

Tested with Python 3.12 and Trio 0.25.0 (but other versions probably work too).

Why

  • An HTTP CONNECT proxy is one of the simplest async I/O things you can build that does something real. Namely, you can load HTTPS sites (including streaming YouTube and Netflix) through it.

  • If you're trying to access content that's restricted by an IP-based geofence, you could run this from a machine inside the geofence to get access!

    Note: Please consult the relevant terms and conditions first to make sure you wouldn't be breaking the rules. 😇

    Also note: Many popular streaming services blacklist IPs of major cloud hosting providers to thwart unauthorized geofence hopping. So you'd need to run this from some other hosting provider.

  • I was sold on Trio before I saw @njsmith live code happy eyeballs in 40 lines of Python. 🙀

    If you haven't yet read his post, Notes on structured concurrency, or: Go statement considered harmful definitely check it out.

Instructions

  1. Install Trio and h11 if you haven't already.

    uv venv .venv  # create a virtualenv (recommended)
    uv pip install -r requirements-lock.txt  # install dependencies
    
  2. In one shell session, run this script to start the proxy on port 8080:

    ./trio_http_proxy.py
    * Starting HTTP proxy on port 8080...
    

    (You can set the PORT env var to use a different port if you prefer.)

  3. In another session, make an HTTPS request through the proxy, e.g.

    curl -x http://127.0.0.1:8080 https://canhazip.com
    

    You should get the response you were expecting from the destination server, and should see output from the proxy in the first shell session about the forwarded data, e.g.

    [conn1] Reading...
    [conn1] Got CONNECT request for canhazip.com, connecting...
    [conn1 <> canhazip.com] Connected to canhazip.com, sending 200 response...
    [conn1 <> canhazip.com] Sent "200 Connection established" to client, tunnel established.
    [conn1 -> canhazip.com] Forwarded 196 bytes
    [conn1 <- canhazip.com] Forwarded 2954 bytes
    ...
    
  4. You can even configure your OS or browser to use the proxy, and then try visiting some HTTPS websites as you would normally. It works! 💪

    HTTP sites won't work because the proxy only handles HTTP CONNECT requests. But HTTP is weak sauce anyways. 🤓

    A YouTube video streaming through the proxy:

    screenshot of a YouTube video streaming through the proxy

    Changing system proxy settings on macOS:

    screenshot of changing system proxy settings on macOS
  5. When you're done, just hit Ctrl+C to kill the server. Don't forget to restore any proxy settings you changed to how they were set before.

For a one-liner test that only requires one shell session, run:

./trio_http_proxy.py & sleep 1; curl -x http://127.0.0.1:8080 https://canhazip.com ; kill %1