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.
Lowering the Mac's MTU forces smaller TCP segments, keeping each one within the router's inspection limit.
Check current MTU:
ifconfig en0 | grep mtuOne-time (resets on reboot):
sudo ifconfig en0 mtu 1400Undo:
sudo ifconfig en0 mtu 1500Persistent — 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 mtuTo 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 mtuOn 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-fixCalling 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 1400sudo chmod +x /usr/local/bin/mtu-fix.shUpdate 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