Forwarding a port to a host that sits behind the router's own VPN client fails in a way that looks like a firewall problem, because the request clearly arrives. The service logs a connection, the client waits, and nothing comes back. Destination translation did its job; the return packet is the part that went missing. One selective source-NAT rule on the router fixes it, and the interesting part is deciding how narrow that rule can be.

Why the reply takes a different road

A port forward rewrites where a packet is going, never where it came from. The internet client's address stays in the source field all the way across the tunnel, so the remote service sees a stranger and answers the only way it knows: through its own default gateway. That gateway is the VPN concentrator on the far side, which has no route back to an arbitrary public address.

Watch a capture on the tunnel interface and the asymmetry is obvious: request packets outbound, nothing inbound. The forward chain allowed the flow and the tunnel carried it, so the drop happens after the remote host has already chosen a return path.

A source rule narrow enough to trust

Make the router the source the remote host replies to. In this layout the WAN address is 203.0.113.24, the LAN is 192.168.88.0/24, the router's tunnel address is 172.20.5.1, and the service answers on 172.20.5.40:8443. The rule below matches the packet after destination translation, which is why it names the translated address rather than the public one. Nothing in it depends on the client's address, and that is exactly the point.

iptables -t nat -A POSTROUTING -o tun0 -p tcp -d 172.20.5.40 --dport 8443 -j SNAT --to-source 172.20.5.1

Every match in that line exists to keep the rewrite local to one service on one tunnel. Drop the interface or the port and you are rewriting more traffic than the problem requires, which is how a targeted fix turns into a mystery for the next person.

When a blanket masquerade is the honest choice

If the router forwards many services into the same VPN subnet, a per-service rule becomes a list nobody maintains. Masquerading everything that leaves the tunnel interface is simpler and predictable, at the cost of hiding the original client from every host on the far side. Choose it when logs over there are not used for attribution; keep the narrow rule when they are.

The two options also fail differently. A missing narrow rule breaks one service; a broad masquerade that matches too much can quietly rewrite traffic that was already working, including the router's own outbound connections.

Check the counters before you publish

Rules that never match look identical to rules that work until you count packets. Read the table back with byte counters before any client connects, then connect from a network that is not the LAN and read it again. Two readings are what turn a guess into a fact. Publish the forward only after the second one moves.

iptables -t nat -L POSTROUTING -v -n --line-numbers

A zero counter on the source rule after a real connection means the match is wrong, usually because the destination or port does not match the post-translation packet. If the counter climbs but the client still times out, the return path is fixed and something else is dropping the reply, so look at the forward policy on the far side next. Hairpin access from inside the LAN is a separate problem and needs its own rule, not a wider version of this one.

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