Skip to content

danielitus/chrome-err-connection-reset-fix

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 

Repository files navigation

Chrome ERR_CONNECTION_RESET — ISP Middlebox vs Post-Quantum TLS

A detailed root cause analysis and fix for ERR_CONNECTION_RESET errors in Google Chrome caused by ISP deep packet inspection (DPI) middleboxes that cannot handle large TLS 1.3 ClientHello messages and TCP segments generated by Chrome's post-quantum cryptography (ML-KEM/Kyber) implementation.

Symptoms

  • Chrome shows ERR_CONNECTION_RESET on certain websites (especially those behind Cloudflare CDN)
  • curl to the same URLs works perfectly fine
  • Other browsers (Firefox, Safari) may also work
  • The issue is network-specific — the same Chrome instance works on a different network (e.g., mobile hotspot)
  • Incognito mode may temporarily work but fails after a few page loads as cookies accumulate

Affected Environment

  • Google Chrome 124+ (post-quantum key exchange enabled by default since Chrome 124, ML-KEM since Chrome 131)
  • ISPs with upstream DPI middleboxes that inspect or filter TCP segments during TLS sessions
  • Known affected ISPs: CenturyLink/Lumen, and potentially others using similar DPI equipment
  • Network topology: OPNsense/pfSense firewall behind an ISP modem in bridge mode — the firewall passes traffic cleanly, but the ISP's upstream infrastructure does not

Root Cause

The TLS ClientHello Size Problem

Starting with Chrome 124, Google enabled hybrid post-quantum key exchange using X25519Kyber768. In Chrome 131+, this was switched to X25519MLKEM768 (NIST FIPS 203).

This adds approximately 1,100 bytes of post-quantum key material to the TLS ClientHello key_share extension, inflating the ClientHello from ~300 bytes to ~1,500+ bytes. At this size, the ClientHello is fragmented across multiple TCP segments.

Many ISP middleboxes performing deep packet inspection (DPI) expect the ClientHello to fit within a single TCP segment. When it spans multiple segments, these middleboxes either:

  • Send a TCP RST (connection reset)
  • Silently drop the connection
  • Fail to reassemble the handshake correctly

The Large Segment Problem

Even after reducing the ClientHello size (by disabling ML-KEM), Chrome's encrypted HTTP requests can also trigger the same middlebox behavior. Chrome sends significantly more data than curl:

  • 8+ cookies per request (tracking cookies, consent cookies, session cookies)
  • Dozens of HTTP headers (sec-ch-ua, sec-fetch-*, etc.)
  • Total encrypted payload: 1,400–1,500+ bytes

When these encrypted payloads hit the TCP Maximum Segment Size (MSS) boundary (~1,460 bytes with standard 1,500 MTU), the ISP middlebox RSTs the connection.

curl works because:

  • Its ClientHello is ~300 bytes (no post-quantum extensions)
  • Its HTTP requests are minimal (no cookies, fewer headers)
  • All segments stay well under the middlebox's threshold

Why OPNsense/pfSense Isn't the Problem

If your firewall is running in a typical routing configuration behind a bridged ISP modem:

  • Firewall logs show all connections to the affected IPs as passed
  • IDS/IPS (Suricata) is either disabled or not triggering on these connections
  • No TLS inspection or transparent proxy is configured

The RST originates from upstream ISP infrastructure, not the local firewall.

Diagnosis

1. Chrome Net-Export Log Analysis

Capture a net-export log from chrome://net-export/ and analyze the TLS handshake:

SSL_CONNECT_JOB_SSL_CONNECT: {"ech_config_list": "", "ech_enabled": true}

SOCKET_BYTES_SENT: {"byte_count": 1726}  ← Oversized ClientHello

SOCKET_READ_ERROR: {"net_error": -101, "os_error": 54}  ← ECONNRESET
SSL_HANDSHAKE_ERROR: {"error_lib": 35, "error_reason": 101,
  "file": "net/socket/socket_bio_adapter.cc", "line": 157,
  "net_error": -101, "ssl_error": 1}

Key indicators:

  • net_error: -101 = ERR_CONNECTION_RESET
  • os_error: 54 = macOS ECONNRESET
  • TCP connects successfully, RST occurs after ClientHello is sent
  • ech_enabled: true and large byte_count in SOCKET_BYTES_SENT

2. Packet Capture Comparison

# Capture Chrome's TLS handshake
sudo tcpdump -i en0 -c 20 'net <server_ip_range> and tcp port 443' -n

# Compare with curl's ClientHello size
curl -v --resolve www.example.com:443:<server_ip> https://www.example.com 2>&1 | grep -A2 "Client hello"

Chrome's ClientHello: ~1,536 bytes (split across 1,448 + 88 byte segments)
curl's ClientHello: ~321 bytes (single segment)

3. Network Isolation Test

# Test on mobile hotspot (bypasses ISP middlebox)
# If Chrome works on hotspot → ISP middlebox is the culprit

# Temporarily reduce MTU to force smaller segments
sudo ifconfig en0 mtu 1400
# If Chrome works with lower MTU → confirms large segment issue
sudo ifconfig en0 mtu 1500  # revert after testing

4. Verify Post-Quantum Key Exchange in ClientHello

In the tcpdump hex output, look for the ML-KEM key share codepoint:

0x11EC  →  ML-KEM768+X25519 (Chrome 131+)
0x6399  →  X25519Kyber768 (Chrome 124-130)

If present in the key_share extension, the ClientHello is inflated with post-quantum key material.

Solution

MSS Clamping on OPNsense (Recommended Fix)

The correct fix is MSS clamping on the WAN interface, which forces all TCP connections to negotiate a smaller Maximum Segment Size. This ensures no individual TCP segment exceeds the threshold that triggers the ISP middlebox.

  1. Navigate to Firewall → Settings → Normalization
  2. Click + Add
  3. Configure:
    • Interface: WAN
    • Direction: Any
    • Protocol: TCP
    • Max MSS: 1400
    • Description: MSS clamping - ISP middlebox large segment fix
  4. SaveApply Changes

This works because:

  • MSS clamping modifies the TCP SYN/SYN-ACK to advertise a smaller MSS
  • All subsequent data segments respect this smaller size
  • Both the TLS handshake and encrypted HTTP data stay within bounds
  • No Chrome-side changes are required
  • All browsers and applications benefit automatically

MSS Clamping on pfSense

  1. Navigate to Firewall → Scrub
  2. Add a scrub rule:
    • Interface: WAN
    • Protocol: TCP
    • Max MSS: 1400
  3. SaveApply

Alternative: Chrome-Side Workarounds (Not Recommended)

These are temporary workarounds that only fix Chrome and don't address the underlying network issue:

Disable Post-Quantum Key Exchange via Enterprise Policy

macOS (configuration profile):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>PayloadContent</key>
    <array>
        <dict>
            <key>PayloadType</key>
            <string>com.google.Chrome</string>
            <key>PayloadVersion</key>
            <integer>1</integer>
            <key>PayloadIdentifier</key>
            <string>com.custom.chrome.tlsfix.settings</string>
            <key>PayloadUUID</key>
            <string>A1B2C3D4-E5F6-7890-ABCD-EF1234567890</string>
            <key>PostQuantumKeyAgreementEnabled</key>
            <false/>
            <key>EncryptedClientHelloEnabled</key>
            <false/>
        </dict>
    </array>
    <key>PayloadDescription</key>
    <string>Disables Chrome PQ key exchange and ECH</string>
    <key>PayloadDisplayName</key>
    <string>Chrome TLS Compatibility Fix</string>
    <key>PayloadIdentifier</key>
    <string>com.custom.chrome.tlsfix</string>
    <key>PayloadOrganization</key>
    <string>Local Admin</string>
    <key>PayloadType</key>
    <string>Configuration</string>
    <key>PayloadUUID</key>
    <string>F1E2D3C4-B5A6-7890-FEDC-BA0987654321</string>
    <key>PayloadVersion</key>
    <integer>1</integer>
</dict>
</plist>

Windows (Registry):

HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome
PostQuantumKeyAgreementEnabled = 0 (DWORD)
EncryptedClientHelloEnabled = 0 (DWORD)

Linux:

sudo mkdir -p /etc/opt/chrome/policies/managed/
echo '{"PostQuantumKeyAgreementEnabled": false, "EncryptedClientHelloEnabled": false}' | \
  sudo tee /etc/opt/chrome/policies/managed/disable-pqc.json

⚠️ Note: Google has stated that PostQuantumKeyAgreementEnabled is a temporary policy. Chrome-side workarounds only reduce the ClientHello size — they don't fix the large encrypted HTTP request problem (cookies/headers), which can also trigger the middlebox RST. MSS clamping is the only complete fix.

Chrome Flags (Deprecated)

These flags have been removed in recent Chrome versions:

  • chrome://flags/#encrypted-client-hello — removed around Chrome 130+
  • chrome://flags/#post-quantum-key-agreement — removed in Chrome 138+
  • chrome://flags/#enable-tls13-kyber — removed in Chrome 131+
  • chrome://flags/#use-ml-kem — removed in Chrome 138+

Technical Details

TLS ClientHello Structure Comparison

Field curl (~321 bytes) Chrome 144 (~1,536 bytes)
TLS version TLS 1.3 TLS 1.3
Cipher suites ~5 ~15
Key share X25519 (32 bytes) X25519MLKEM768 (~1,100 bytes)
ECH Not present GREASE ECH (~200 bytes)
Extensions ~8 ~20+ (including sec-ch-ua, ALPS)

TCP Segment Behavior

With standard MTU 1500 and MSS 1460:

Chrome ClientHello (1,536 bytes):
  Segment 1: [TCP header][TLS record header][ClientHello bytes 1-1,448]  ← 1,448 bytes
  Segment 2: [TCP header][ClientHello bytes 1,449-1,536]                 ← 88 bytes
  → ISP middlebox sees fragmented ClientHello → RST

With MSS clamped to 1400:
  Segment 1: [TCP header][TLS record header][ClientHello bytes 1-1,348]  ← 1,348 bytes
  Segment 2: [TCP header][ClientHello bytes 1,349-1,536]                 ← 188 bytes
  → Segments within middlebox tolerance → PASS

More importantly, MSS clamping also keeps all subsequent encrypted segments under the threshold, preventing RSTs on large HTTP requests with cookies.

Related Resources

Contributing

If you've encountered this issue with a different ISP or network equipment, please open an issue with:

  1. Your ISP name
  2. The modem/gateway model (if known)
  3. Whether MSS clamping resolved the issue
  4. The MSS value that worked for you

License

MIT

About

Fix for Chrome ERR_CONNECTION_RESET caused by ISP middleboxes rejecting large TLS 1.3 ClientHello with post-quantum ML-KEM key exchange. Solution: MSS clamping on OPNsense/pfSense.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors