Skip to content

SSL Certificate Mismatch for files.pythonhosted.org over IPv6 (Fastly CDN issue) #7163

@photonclock

Description

@photonclock

My Platform

Experiencing SSL certificate verification errors when accessing files.pythonhosted.org via pip (e.g., pip install --upgrade pip). The server serves a certificate for default.ssl.fastly.net instead of *.pythonhosted.org over IPv6, causing errors like:

SSLCertVerificationError: “default.ssl.fastly.net” certificate name does not match input.

This occurs on macOS 15.6 (Mac Mini M4, Python 3.12.9 in virtual environment). IPv4 connections work correctly with the proper certificate.

Tailscale's DNS override (using 100.100.100.100) exacerbated the issue by preferring IPv6, but disabling it (tailscale set --accept-dns=false) resolved it locally—indicating a Fastly IPv6 edge server misconfiguration.

Similar issues reported on Reddit around August 1, 2025.

Environment

  • OS: macOS 15.6 (Mac Mini M4)
  • Python: 3.12.9 (via pyenv, virtual environment)
  • pip: 24.3.1
  • Network: Starlink with IPv6 enabled, Tailscale VPN (DNS: 100.100.100.100)
  • Date: August 2, 2025

Steps to Reproduce:

Run curl -6 -v https://files.pythonhosted.org/packages/b7/3f/945ef7ab14dc4f9d7f40288d2df998d1837ee0888ec3659c813487572faa/pip-25.2-py3-none-any.whl

Fails with: SSL: no alternative certificate subject name matches target host name 'files.pythonhosted.org'.
Certificate: CN=default.ssl.fastly.net (valid May 1, 2025 - June 2, 2026).

Run curl -4 -v (same URL): Succeeds with CN=*.pythonhosted.org (valid Feb 4, 2025 - Mar 8, 2026).

Diagnostics:

DNS resolution (via dig):

IPv4: 167.82.52.223
IPv6: 2a04:4e42:d000::223

openssl s_client -connect files.pythonhosted.org:443 -showcerts: Shows default.ssl.fastly.net over IPv6.
Network: Starlink with IPv6 enabled; DNS: 100.100.100.100 (via Tailscale).
Date: August 2, 2025.

Workaround:
pip --prefer-ipv4 or tailscale set --accept-dns=false

Please investigate the Fastly IPv6 certificate configuration for files.pythonhosted.org.

Attached: Full curl and openssl outputs

curl -6 -v https://files.pythonhosted.org/packages/b7/3f/945ef7ab14dc4f9d7f40288d2df998d1837ee0888ec3659c813487572faa/pip-25.2-py3-none-any.whl

  • Host files.pythonhosted.org:443 was resolved.
  • IPv6: 2a04:4e42:d000::223
  • IPv4: (none)
  • Trying [2a04:4e42:d000::223]:443...
  • Connected to files.pythonhosted.org (2a04:4e42:d000::223) port 443
  • ALPN: curl offers h2,http/1.1
  • (304) (OUT), TLS handshake, Client hello (1):
  • CAfile: /etc/ssl/cert.pem
  • CApath: none
  • (304) (IN), TLS handshake, Server hello (2):
  • (304) (IN), TLS handshake, Unknown (8):
  • (304) (IN), TLS handshake, Certificate (11):
  • (304) (IN), TLS handshake, CERT verify (15):
  • (304) (IN), TLS handshake, Finished (20):
  • (304) (OUT), TLS handshake, Finished (20):
  • SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256 / [blank] / UNDEF
  • ALPN: server accepted h2
  • Server certificate:
  • subject: C=US; ST=California; L=San Francisco; O=Fastly, Inc.; CN=default.ssl.fastly.net
  • start date: May 1 16:26:08 2025 GMT
  • expire date: Jun 2 16:26:07 2026 GMT
  • subjectAltName does not match host name files.pythonhosted.org
  • SSL: no alternative certificate subject name matches target host name 'files.pythonhosted.org'
  • Closing connection
    curl: (60) SSL: no alternative certificate subject name matches target host name 'files.pythonhosted.org'
    More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

curl -4 -v https://files.pythonhosted.org/packages/b7/3f/945ef7ab14dc4f9d7f40288d2df998d1837ee0888ec3659c813487572faa/pip-25.2-py3-none-any.whl

  • Host files.pythonhosted.org:443 was resolved.
  • IPv6: (none)
  • IPv4: 167.82.52.223
  • Trying 167.82.52.223:443...
  • Connected to files.pythonhosted.org (167.82.52.223) port 443
  • ALPN: curl offers h2,http/1.1
  • (304) (OUT), TLS handshake, Client hello (1):
  • CAfile: /etc/ssl/cert.pem
  • CApath: none
  • (304) (IN), TLS handshake, Server hello (2):
  • (304) (IN), TLS handshake, Unknown (8):
  • (304) (IN), TLS handshake, Certificate (11):
  • (304) (IN), TLS handshake, CERT verify (15):
  • (304) (IN), TLS handshake, Finished (20):
  • (304) (OUT), TLS handshake, Finished (20):
  • SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256 / [blank] / UNDEF
  • ALPN: server accepted h2
  • Server certificate:
  • subject: CN=*.pythonhosted.org
  • start date: Feb 4 21:00:11 2025 GMT
  • expire date: Mar 8 21:00:10 2026 GMT
  • subjectAltName: host "files.pythonhosted.org" matched cert's "*.pythonhosted.org"
  • issuer: C=BE; O=GlobalSign nv-sa; CN=GlobalSign Atlas R3 DV TLS CA 2025 Q1
  • SSL certificate verify ok.
  • using HTTP/2
  • [HTTP/2] [1] OPENED stream for https://files.pythonhosted.org/packages/b7/3f/945ef7ab14dc4f9d7f40288d2df998d1837ee0888ec3659c813487572faa/pip-25.2-py3-none-any.whl
  • [HTTP/2] [1] [:method: GET]
  • [HTTP/2] [1] [:scheme: https]
  • [HTTP/2] [1] [:authority: files.pythonhosted.org]
  • [HTTP/2] [1] [:path: /packages/b7/3f/945ef7ab14dc4f9d7f40288d2df998d1837ee0888ec3659c813487572faa/pip-25.2-py3-none-any.whl]
  • [HTTP/2] [1] [user-agent: curl/8.7.1]
  • [HTTP/2] [1] [accept: /]

GET /packages/b7/3f/945ef7ab14dc4f9d7f40288d2df998d1837ee0888ec3659c813487572faa/pip-25.2-py3-none-any.whl HTTP/2
Host: files.pythonhosted.org
User-Agent: curl/8.7.1
Accept: /

  • Request completely sent off
    < HTTP/2 200
    < x-amz-id-2: kCO5imCAt9WP48C25jKNclxMdKUwOVAmr8KANwpdcdt+7o8g7LpNeCm54kOXdQmv6eesuuP2XLY=
    < x-amz-request-id: PTJW5PEF8CHCPWJ7
    < last-modified: Wed, 30 Jul 2025 21:50:15 GMT
    < etag: "52af72c263169cc46cc32bed310a5eab"
    < x-amz-server-side-encryption: AES256
    < x-amz-version-id: RQ4jL0jt4v.zdHm4xrJ2jA1dvnZjWusI
    < content-type: binary/octet-stream
    < server: AmazonS3
    < fastly-restarts: 1
    < cache-control: max-age=365000000, immutable, public
    < accept-ranges: bytes
    < date: Sat, 02 Aug 2025 19:26:07 GMT
    < age: 250551
    < x-served-by: cache-iad-kiad7000045-IAD, cache-dfw-ktki8620022-DFW
    < x-cache: HIT, HIT
    < x-cache-hits: 28, 1
    < x-timer: S1754162767.275928,VS0,VE7
    < strict-transport-security: max-age=31536000; includeSubDomains; preload
    < x-frame-options: deny
    < x-xss-protection: 1; mode=block
    < x-content-type-options: nosniff
    < x-robots-header: noindex
    < access-control-allow-methods: GET, OPTIONS
    < access-control-allow-headers: Range
    < access-control-allow-origin: *
    < x-pypi-file-python-version: py3
    < x-pypi-file-version: 25.2
    < x-pypi-file-package-type: bdist_wheel
    < x-pypi-file-project: pip
    < content-length: 1752557
    <
    Warning: Binary output can mess up your terminal. Use "--output -" to tell
    Warning: curl to output it to your terminal anyway, or consider "--output
    Warning: " to save to a file.
  • Failure writing output to destination, passed 683 returned 4294967295
  • process_pending_input: nghttp2_session_mem_recv() returned -902:The user callback function failed
  • Connection #0 to host files.pythonhosted.org left intact

Fastly Debug


DNS Resolution

$ dig pypi.org A
$ dig pypi.org AAAA
$ dig files.pythonhosted.org A
$ dig files.pythonhosted.org AAAA

Traceroutes / IPv4

$ traceroute pypi.org
$ traceroute files.pythonhosted.org

Traceroutes / IPv6 (If available)

$ traceroute6 pypi.org
$ traceroute6 files.pythonhosted.org

HTTPS Requests / IPv4

$ curl -vvv -I --ipv4 https://pypi.org/pypi/pip/json
$ curl -vvv -I --ipv4 https://files.pythonhosted.org/packages/ae/e8/2340d46ecadb1692a1e455f13f75e596d4eab3d11a57446f08259dee8f02/pip-10.0.1.tar.gz

HTTPS Requests / IPv6 (If available)

$ curl -vvv -I --ipv6 https://pypi.org/pypi/pip/json
$ curl -vvv -I --ipv6 https://files.pythonhosted.org/packages/ae/e8/2340d46ecadb1692a1e455f13f75e596d4eab3d11a57446f08259dee8f02/pip-10.0.1.tar.gz

TLS Debug / IPv4

$ echo -n | openssl s_client -4 -connect pypi.org:443
$ echo -n | openssl s_client -4 -connect files.pythonhosted.org:443

TLS Debug / IPv6 (If available)

$ echo -n | openssl s_client -6 -connect pypi.org:443
$ echo -n | openssl s_client -6 -connect files.pythonhosted.org:443

Code of Conduct

  • I agree to follow the PSF Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    networkIssues related to our CDN, users having problems connecting to PyPI

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions