Skip to content

Instantly share code, notes, and snippets.

@sdesalas
Last active June 23, 2026 15:50
Show Gist options
  • Select an option

  • Save sdesalas/09f8121b1e96cba65da24f02a1434241 to your computer and use it in GitHub Desktop.

Select an option

Save sdesalas/09f8121b1e96cba65da24f02a1434241 to your computer and use it in GitHub Desktop.
Deep Packet Inspection on TLS traffic causing ERROR_CONNECTION_RESET in Chrome browser (OSX)

TLS Connection Reset Fix — macOS

Root Cause

Modern browsers (Chrome 124+, Firefox 128+) now include a post-quantum key exchange (ML-KEM) in every HTTPS handshake. This inflates the TLS ClientHello to ~1700–1800 bytes, which no longer fits in a single TCP segment. Some home routers have a DPI (Deep Packet Inspection) engine that only handles single-segment ClientHellos — when the handshake spills into a second segment, the router injects a TCP RST and kills the connection before the server ever responds.

Safari is unaffected because Apple has not yet added ML-KEM to WebKit.

Fix — Reduce MTU on WiFi interface

Lowering the Mac's MTU forces smaller TCP segments, keeping each one within the router's inspection limit.

Check current MTU:

ifconfig en0 | grep mtu

One-time (resets on reboot):

sudo ifconfig en0 mtu 1400

Undo:

sudo ifconfig en0 mtu 1500

Persistent — LaunchDaemon (applied at every boot):

Save the following as ~/mtu-fix-launchdaemon.sh and run chmod +x ~/mtu-fix-launchdaemon.sh && sudo ~/mtu-fix-launchdaemon.sh:

#!/bin/bash
set -e

PLIST=/Library/LaunchDaemons/com.local.mtu-fix.plist

if [ -f "$PLIST" ]; then
  echo "LaunchDaemon already exists at $PLIST"
  echo "Run the uninstall script first if you want to reinstall."
  exit 1
fi

sudo tee "$PLIST" > /dev/null <<'EOF'
<?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>Label</key>
    <string>com.local.mtu-fix</string>
    <key>ProgramArguments</key>
    <array>
        <string>/sbin/ifconfig</string>
        <string>en0</string>
        <string>mtu</string>
        <string>1400</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>
EOF

sudo launchctl load "$PLIST"

echo "Installed and loaded. Current MTU:"
ifconfig en0 | grep mtu

To uninstall, save the following as ~/mtu-fix-launchdaemon-uninstall.sh and run chmod +x ~/mtu-fix-launchdaemon-uninstall.sh && sudo ~/mtu-fix-launchdaemon-uninstall.sh:

#!/bin/bash
set -e

PLIST=/Library/LaunchDaemons/com.local.mtu-fix.plist

if [ ! -f "$PLIST" ]; then
  echo "LaunchDaemon not found at $PLIST — nothing to remove."
  exit 0
fi

sudo launchctl unload "$PLIST"
sudo rm "$PLIST"

echo "Removed. Restoring MTU to 1500..."
sudo ifconfig en0 mtu 1500

echo "Done. Current MTU:"
ifconfig en0 | grep mtu

Troubleshooting — LaunchDaemon fails silently on newer macOS

launchctl load is deprecated

On macOS 13+, launchctl load may return an I/O error. Use bootstrap/bootout instead:

# Load
sudo launchctl bootstrap system /Library/LaunchDaemons/com.local.mtu-fix.plist

# Unload
sudo launchctl bootout system/com.local.mtu-fix

# Check status
launchctl print system/com.local.mtu-fix

Daemon runs but MTU doesn't change (exit code 1)

Calling ifconfig directly from a plist can fail if the interface isn't fully ready when the daemon fires at boot. Fix: use a shell script wrapper that waits for the interface before applying the MTU.

Create /usr/local/bin/mtu-fix.sh:

#!/bin/bash
while ! /sbin/ifconfig en0 &>/dev/null; do sleep 1; done
/sbin/ifconfig en0 mtu 1400
sudo chmod +x /usr/local/bin/mtu-fix.sh

Update the plist ProgramArguments to call the script:

<array>
    <string>/bin/bash</string>
    <string>/usr/local/bin/mtu-fix.sh</string>
</array>

Then reload:

sudo launchctl bootout system/com.local.mtu-fix
sudo launchctl bootstrap system /Library/LaunchDaemons/com.local.mtu-fix.plist
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment