SSH connects, works for a minute or so, then freezes at roughly the same interval every time. The common explanation is an idle timeout, so people lower the MTU and set client keepalives. A WireGuard link I worked on had already been through all of it: a smaller tunnel MTU, client-alive settings, a configured tunnel keepalive. The drops continued unchanged. The cause turned out to be an asymmetric LAN route, and the pattern is worth recognising because it defeats every timer-based fix.

A keepalive proves your host is still willing to send. It cannot make a stateful device see a reply that never crosses it.

The myth: keepalives fix a silent drop

SSH keepalives exist for one job: keeping an idle session from being reaped by something that counts silence. They do that well. They do not address a stateful device that saw the first packet in one direction and then never saw the reply, because nothing the client sends changes which interface the reply uses.

An MTU change is the other popular fix, and it has the same failure mode. Reducing the MTU helps fragmentation and path-MTU problems, and it does nothing to a route. If your timers and MTU are already sensible and the drop is still at a repeatable interval, the interval is telling you about a timeout somewhere, not about packet size. Write the interval down and compare it with the state timeouts on every device in the path.

The tell is regularity combined with a session that stays usable inside that interval. Idle timeouts hit when nothing happens; this hits while you are typing.

What the extra gateway actually does

Put the laptop and the VPN gateway on the same LAN, with a separate LAN firewall as the default gateway. The laptop sends VPN-bound traffic to the firewall, the firewall forwards it to the gateway, and the gateway's replies go straight back across the LAN to the laptop. That second leg never passes the firewall, so its state table holds half a connection.

The addresses below mirror that arrangement:

Laptop:             192.168.50.20
LAN firewall:       192.168.50.1
WireGuard gateway:  192.168.50.10
Remote VPN subnet:  10.77.0.0/24

Redirects and state handling then turn a working handshake into a connection that dies later rather than immediately. The delay is the state entry aging out or a stricter check failing, which is why the interval looks so mechanical.

None of this appears in the client configuration, which is why the search for it usually starts in the wrong file.

Pick one deliberate path

For the layout above, routing the remote subnet directly at the VPN gateway removes the half-connection:

sudo ip route add 10.77.0.0/24 via 192.168.50.10
ip route get 10.77.0.42

Those are example addresses. The next hop has to be reachable on your LAN, the prefix has to be the intended remote network, and the second command shows you the result before you rely on it. If the gateway is not on your subnet, this route is not the fix you want.

If the firewall is meant to police traffic between those systems, routing around it is the wrong design. Make both directions traverse the boundary instead, and configure the routes on each side so the return path matches. The goal is a single deliberate path, not less state checking.

Netgate's notes on asymmetric routing describe the same interface-level asymmetry and the state problems it creates, so read them before you loosen state handling globally. Timed disconnects resembling this case are not evidence on their own. Treat the article as a description of one failure mode, then prove your own network matches it before changing global state policy.

Test it from both ends

Read the laptop's route toward the destination and the destination's route back toward the laptop; they are two separate decisions and only one of them is probably wrong. A ping that succeeds from the gateway itself can hide the problem entirely, because it originates on the machine whose path is already correct. You need both directions as seen by the two ends of the actual session.

After the fix, reopen SSH and hold the session open well past the interval that used to fail. Then make the route persistent in the approved network configuration, because a one-off command is not a reboot plan and the problem will return at the next restart with a new mystery attached.

When asymmetry is fine

Asymmetric routing is normal in many networks and is not broken by definition. It becomes a problem when state tracking, translation or policy depends on seeing a path it does not see, and each of those has a different remedy. Check what the middle device actually requires before redesigning around it.

The durable answer names the two paths, the device that needs to see both, and the route that makes it so. If you cannot name the device, you have not found the cause yet.

འབྲེལ་བའི་རྩོམ་ཡིག