Safari Hanging on Page Reloads? OPNsense, QUIC.
I was having an odd issue with some sites hanging on reload, after they had been open for some time, only in safari, not chrome or Firefox ever.
I opened Safari's web inspector for one site doing it. Noticed requests to unpkg.com (a CDN for JavaScript libraries) were hanging. That gave me something to trace.
Fired up tcpdump:
sudo tcpdump -i any host unpkg.com -nn -v
And there it was. Safari was sending QUIC packets (HTTP/3 over UDP port 443) to the server and getting zero response back. It just kept retrying for about 12 seconds before giving up and opening a fresh connection. The new connection worked instantly.
Here's what the capture looked like—Safari hammering away on a dead connection:
23:33:05.881085 192.168.0.130.55087 > 104.18.0.22.443: quic, protected
23:33:05.923585 192.168.0.130.55087 > 104.18.0.22.443: quic, protected
...keeps sending with no response...
23:33:17.897185 192.168.0.130.55087 > 104.18.0.22.443: quic, protected
12 seconds of packets going nowhere. Then Safari finally opens a new connection on a different port, handshake completes in milliseconds, and data flows fine.
The Problem: Stale QUIC Connections
QUIC uses UDP, and Safari tries to reuse connections. The problem is Safari doesn't send keepalives on idle QUIC connections. So if the connection sits idle for a bit, the NAT state on your firewall expires, but Safari doesn't know. It keeps trying to use a connection that no longer exists in your firewall's state table.
This is actually a known issue—Apple's own developer forums have reports about it. Safari uses a max_idle_timeout of 0 and doesn't send keepalives, so it relies entirely on the server's timeout value. If your firewall drops the state before that, you're stuck waiting.
The Fix: OPNsense UDP State Timeout
I run OPNsense as my router/firewall. Turns out the default "normal" firewall optimization has pretty aggressive UDP timeouts:
- udp.first: 60s
- udp.single: 30s ← this was the culprit
- udp.multiple: 60s
30 seconds. That's it. If a QUIC connection sits idle for 30 seconds, OPNsense drops the state. Safari has no idea and keeps trying to use it.
The fix is simple:
- Go to Firewall → Settings → Advanced
- Find Firewall Optimization
- Change it from normal to conservative
- Save and apply
This bumps the UDP timeouts to:
- udp.first: 300s
- udp.single: 150s
- udp.multiple: 900s
You can verify with:
pfctl -st | grep udp
One more thing—existing states keep the old timeout, so you need to flush them:
pfctl -F states
Or in the GUI: Firewall → Diagnostics → States → Reset States
Then restart Safari and you're good.
Takeaway
If you're running OPNsense (or pfSense, same deal) and Safari is randomly hanging on page loads, especially after tabs have been idle for a bit, check your UDP state timeouts. The "conservative" firewall optimization setting fixes it.
Could Apple fix this by having Safari send QUIC keepalives? Probably. This has been reported on the Apple Developer Forums multiple times, with threads going back years. The behavior is documented—Safari sets max_idle_timeout to 0 and doesn't proactively send keepalives, leaving it entirely up to the server and network path to maintain the connection.
Chrome and Firefox handle this differently, which is why you don't see the same issue there. But Apple hasn't changed Safari's behavior.
Ready to scan your domain?
Check your security configuration in seconds with our free scanner.
Start Free Scan