Skip to content

IPv6 with a proxy fails with Python3.9 #3615

@xNinjaKittyx

Description

@xNinjaKittyx

Subject

Take the following mitmproxy docker compose in a IPv6 environment

services:
    mitmproxy:
        image: mitmproxy/mitmproxy
        command: mitmdump --set ssl_insecure --set allow_hosts="::/0" --set proxyauth="user:pass" --
        ports:
            - "8080:8080"
        networks:
            - mitmproxy_network

networks:
  mitmproxy_network:
    enable_ipv6: true

I take the following test script

import urllib3
import requests

print(urllib3.__version__)
print(requests.__version__)

r = requests.get(
    "https://[some:ipv6:ipaddress:1::10]:1234/uri/path/redacted",  # with some ipv6 address
    auth=("admin", "password"),
    proxies={
        "http": "http://user:pass@[fdac:a8f0:d40b:1::2]:8080",  # Using an IPv6 Proxy address.
        "https": "http://user:pass@[fdac:a8f0:d40b:1::2]:8080"  # Can grab this via docker inspect
    },
    verify=False
)

print(r.status_code)
print(r.text)

This fails with

Traceback (most recent call last):
... (truncated)
requests.exceptions.ProxyError: HTTPSConnectionPool(host='some:ipv6:ipaddress:1::10', port=1234): Max retries exceeded with url: /uri/path/redacted (Caused by ProxyError('Unable to connect to proxy', OSError('Tunnel connection failed: 400 Bad Request')))

Looking through the code, I found that https://github.com/urllib3/urllib3/blob/main/src/urllib3/connection.py#L235 will have different proxy behavior with < 3.11.4

However, this code path with IPv6 eventually calls this CONNECT command incorrectly.

(Pdb) connect
b'CONNECT some:ipv6:ipaddress:1::10:1234 HTTP/1.0\r\n'

In Python 3.13, this is correctly called, since it has the IPv6 handler in the python builtin library
https://github.com/python/cpython/blob/3.9/Lib/http/client.py#L912

(Pdb) connect
b'CONNECT [some:ipv6:ipaddress:1::10]:1234 HTTP/1.1\r\n'

Other notes

curl -x http://user:pass@[fdac:a8f0:d40b:1::2]:8080 -6 -k -u  admin:password https://[myipv6address]:1234/uri/path/redacted

I have not personally tested with 3.10 or < 3.11.4, but I would assume they would have similar issues.

Environment

print("OS", platform.platform())
OS Linux-5.4.17-2136.343.5.1.el8uek.x86_64-x86_64-with-glibc2.36
print("Python", platform.python_version())
Python 3.9.22
print(ssl.OPENSSL_VERSION)
OpenSSL 3.0.16 11 Feb 2025
print("urllib3", urllib3.version)
urllib3 2.4.0

Steps to Reproduce

What I did

  • Run the mitmproxy compose file
  • You'll need an ipv6 enabled web server... (I'll try to see if I can make a single compose file to do everything)
  • Run a python3.9 docker image interactively sudo docker run --network ${USER}_mitmproxy_network --entrypoint /bin/bash -it python:3.9
    • you could mount a dir or something here to make it easier. Otherwise, I installed vim and installed pip install requests==2.32.3
    • Then ran the script

Expected Behavior

I would expect it to not fail during the TUNNEL connection phase.

Actual Behavior

Raises an exception for ProxyError

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions