Inbound connections to a host that also runs a VPN client fail in a very specific way: the handshake arrives, the daemon answers, and the client receives nothing back. Nothing is blocking the port. The answer left through the tunnel, because the tunnel owns the default route and the kernel routes replies by destination rather than by memory of where the request came from. The daemon is fine and the port is open.

The reply is routed, not remembered

A VPN client that installs a default route adds an entry that outranks the LAN gateway, either by metric or by splitting the space into two more specific halves. Outbound packets now choose the tunnel interface. The kernel never asks where the packet being answered originally arrived. That single omission explains every symptom that follows.

The forward direction is routed by destination, and so is the reverse direction. The reply is addressed to a public client, which the tunnel will happily carry. The far end receives a packet whose source it does not own, discards it, and the original client waits until it times out.

Strict reverse-path filtering can drop the inbound packet before the daemon ever reads it. Check that counter first, because a filtering drop and a routing mistake look identical from the outside.

ip route show default
sysctl net.ipv4.conf.all.rp_filter net.ipv4.conf.eth0.rp_filter
nft list ruleset | grep -A3 'hook forward'

The first command shows which default currently wins. The second reports whether strict filtering applies globally or per interface, and the third shows any forward-chain rule that might be involved.

Three ways to keep the return path

Excluding the service destination from the tunnel is the narrowest option. A host route pointed at the LAN gateway, plus a daemon bound to the physical address instead of every address, keeps that one flow outside the tunnel. The change is local and easy to reverse.

Policy routing is the general answer. A rule keyed on the source address or on a firewall mark selects a table whose default points at the WAN gateway, while the host's own connections continue to use the tunnel. Keep the priority explicit so the rule cannot be shadowed later.

ip rule add from 203.0.113.25/32 table 100 priority 100
ip route add default via 192.0.2.1 dev eth0 table 100
ip route get 198.51.100.7 from 203.0.113.25

The first two commands build the alternate path for replies sourced from the public address. The third asks the kernel which path that exact source and destination would take, which is how you confirm the rule has any effect.

Source translation is the third option and the only one that survives a router already performing NAT in front of the service. The reply has to return to that router, and masquerading to the WAN interface achieves it while hiding the client from the service logs. Replacing the default route by hand after connecting is a diagnostic, because the client rewrites the table on the next reconnect.

When the box also routes for a LAN

The same failure appears one hop further out when the host routes for devices behind it. An inbound connection is forwarded to an internal device whose only return path is the tunnel, and the reply reaches the external client from the provider's address. The internal device is working correctly the whole time.

Connection tracking then sees a reply for a flow it never recorded and drops it. Destination translation delivers the inbound connection to the device, and source translation makes the reply appear to originate from the router itself.

A policy route that keeps the forwarded port on the WAN while the router's own traffic uses the tunnel is the tidier equivalent. Without source translation the reply is addressed to the external client, and the internal device has no route for that address at all.

Three probes that separate the causes

Run three probes: a connection into the box from the internet, a connection out of it to a public host, and a name lookup. When the first two disagree, the reply path is at fault. When names fail both ways, the resolver is a different fault that merely shares the tunnel.

Fix the routing question first, then look at names. Mixing the two is how a working server gets blamed for a broken resolver.

Record which interface the exception names and keep the configuration under version control. A rule written against an interface that gets renamed after an upgrade passes today and fails after the next reboot.

সম্পৰ্কিত প্ৰবন্ধ