Symptoms follow one shape: a host works, then it connects to a VPN as a client, and now LAN clients reach it while its answers vanish. A capture on the host shows the replies leaving through the tunnel device instead of the LAN interface. Nothing about the tunnel is broken, and the fix is a route, not a reconnect. Work the four checks below in order and stop at the first one that fails.

A reply is a new packet, not a reversal

It helps to drop the idea that an answer travels back along the path a request took. Routing is decided per packet, per direction, on the sending host. A request that arrived from 10.64.0.23 inside the tunnel creates no return path; when the host answers, that reply is matched against the table as a fresh packet and leaves by whatever route wins.

That is why a full-tunnel client on a machine that also serves a LAN produces such a confusing failure. The client installs a default route, or the two half-default routes some clients prefer, and the reply to a LAN client now matches the tunnel. It goes to the provider, which has no reason to forward it, and the LAN client sees a timeout despite a host that is up and answering locally. The capture makes it obvious, and the routing table explains it.

Keep two subnets in your head while reading the rest. One is the VPN address pool the remote clients come from, in this example 10.64.0.0/24. The other is the LAN that must keep working, 172.16.24.0/24 with its router at 172.16.24.1. The bug is that traffic between them is being decided by the default route.

Prove it from the capture and the lookup

Before changing anything, confirm which device the reply will use. A lookup is faster than a capture and answers the exact question the kernel will answer when the packet is built.

ip route get 10.64.0.23 from 172.16.24.10
tcpdump -ni any -c 6 icmp

Read the reply in two parts. If it names dev tun0, the host will encapsulate the answer and hand it to the provider, and the LAN client will never see it. If it names dev eth0 but the client still times out, the route is already right and the packet is being dropped later, which is a different problem with a different fix.

The capture in the same step settles the doubt a ping cannot. An echo reply arriving at the LAN client proves that some path works, not which interface carried it, so run the capture on the host itself and watch where the frames leave. A printer on the same subnet keeps answering, because its on-link route is more specific than the tunnel default. A forwarded port fails exactly like any other flow, since the table chooses the interface and the connection does not.

Install the narrowest route that outranks the tunnel

Prefix length decides, not metric, so a route for the client pool through the LAN router wins over any default the VPN client installs. No metric surgery is needed, and the default can stay exactly where the client put it.

ip route replace 10.64.0.0/24 via 172.16.24.1 dev eth0
ip route get 10.64.0.23 from 172.16.24.10

Use replace rather than add, because a client that reconnects will have installed its own entry and a second add fails with an existing-route error that reads like a permission problem. On a Windows host the equivalent is route add 10.64.0.0 mask 255.255.255.0 172.16.24.1 -p, where -p keeps the entry across reboots, since the client may rebuild the table when the tunnel comes back up. On a current Windows host the supported equivalent is New-NetRoute -DestinationPrefix 10.64.0.0/24 -NextHop 172.16.24.1 -InterfaceAlias Ethernet -PolicyStore PersistentStore, with the older route command retained as a legacy form.

One detail decides whether this is correct or merely plausible: the next hop has to be the router that actually owns the path back to the clients. Pointing the route at an address that is itself reached through the tunnel creates a loop that shows up as intermittent loss rather than a clean failure. Confirm the next hop is on the LAN subnet before you commit the line.

Keep the answer after a reconnect

A route added by hand survives until the next reconnect at best. If the client pool is dynamic, pin it in the server configuration so the prefix you routed stays the prefix clients receive; otherwise the entry points at an empty range and the symptom returns weeks later with no obvious cause. Writing the route into the client's own up-script is the other reliable option, because it runs after the client has rewritten the table.

A stateful firewall can still defeat a correct route. If the capture now shows the reply leaving eth0 and the client still times out, check whether the host is dropping the packet before it is sent: strict reverse-path filtering, net.ipv4.conf.all.rp_filter set to 1, discards packets whose source would not be routed back out the interface they arrived on, which is exactly the asymmetric case you just created and then fixed. Conntrack state tells the same story for forwarded ports.

The last check is the one people skip: repeat the lookup after the tunnel has been down and up again. Four values should match what you wrote down, the destination, the next hop, the device and the chosen source. If any of them moved, the client rewrote the table and the fix belongs in its hooks rather than in a shell history.

Artihkkalat mat laktásit