The client gets an address, the server answers pings, and every page still times out. Most people start editing the client profile at this point, which is usually wasted effort: once the tunnel is up, the server has to behave like a router. Three conditions have to hold at once before a packet leaves and a reply comes back, and the symptom is identical whichever one is missing.

Why a working tunnel still has no route out

The kernel must forward packets between interfaces, which is off by default on most Linux distributions. The traffic must be translated to an address the outside world can answer, unless every upstream router already knows the route back to the tunnel subnet. The firewall's forward path must permit the traffic in both directions, including the replies.

Each of those can be fixed independently, which is the trap. Turning on forwarding without a translation rule leaves packets leaving with a private source and no return path. Adding translation without a forward rule leaves the kernel dropping the packet one step later.

So test the three layers rather than the client, and change one at a time so the result means something.

Forwarding is a kernel switch you have to persist

Check the current value before changing it, then set it and confirm the change took effect.

sysctl net.ipv4.ip_forward
sysctl -w net.ipv4.ip_forward=1
sysctl net.ipv4.ip_forward

The first command reports the current value, the second sets it at runtime, and the third proves the write worked. The runtime value disappears at the next reboot, which is why a working session can break after maintenance with no configuration change.

Make it permanent in a file under /etc/sysctl.d/, then apply that file rather than rebooting to find out. On FreeBSD the equivalent is net.inet.ip.forwarding, with gateway_enable=YES in rc.conf for persistence. An appliance that reports forwarding disabled explains a whole class of "packets arrive and nothing comes back" reports. Check the setting after every upgrade as well, since a rebuilt kernel or a replaced appliance image can reset it without telling anyone.

Choose masquerade or one fixed translation address

With a dynamic outside address, masquerading is the simplest correct form. Name the tunnel subnet as the source and the outside interface as the exit.

iptables -t nat -A POSTROUTING -s 10.9.0.0/24 -o eth0 -j MASQUERADE

With a static public address, source translation to that exact address is more predictable and easier to audit.

iptables -t nat -A POSTROUTING -s 10.9.0.0/24 -j SNAT --to-source 198.51.100.10

The second form carries a maintenance trap: a hard-coded address that later changes keeps the tunnel working while internet access silently stops. Either use masquerade or update the rule whenever the provider moves you. The interface matters too, because a router sharing its own upstream tunnel has to translate out that tunnel rather than the physical WAN.

The filter table is the third gate

Forwarding and translation can both be correct while the packet still dies in the filter table. ufw is a frequent offender: its forward policy ships as DROP, and the rest of the setup can look perfectly correct while that one setting kills the traffic. Raising it is a deliberate security decision rather than a checkbox.

iptables -A FORWARD -i tun0 -o eth0 -j ACCEPT
iptables -A FORWARD -i eth0 -o tun0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

The first rule allows new traffic from the tunnel toward the outside, and the second allows only replies back. Narrow both to the tunnel subnet and the destination you intend, because a blanket accept on the tunnel interface turns the VPN into an open egress point for anyone who can authenticate.

A bridged tunnel needs a different answer. The address belongs to the bridge, not to the physical port, so enslaving the interface removes the address it used to hold and the host looks unreachable until the bridge itself receives one, which dhclient br0 can supply. That failure looks like a VPN problem and is a layer-two problem. Check the bridge's own address before you touch the firewall, because a filter change cannot fix a host that no longer has an address to send from.

Where to look when a page never loads

Ping the server's tunnel address to prove the tunnel exists. Then run a traceroute from the client to a public address and read where it stops: at the server, the packet arrives but is not forwarded or translated; beyond the server, the problem is upstream and out of your hands.

ping -c 3 10.9.0.1
traceroute -n 198.51.100.10

The first command proves the tunnel carries traffic to the server itself, and the second shows how far a packet gets toward the outside. A trace that ends at the tunnel address points at forwarding or translation on the server, while a trace that stops one hop later points at the provider or the upstream router's return path.

On the server, watch the outside interface while a client loads a page. Traffic leaving with a private source address means translation is missing, and no reply at all means the forward path or the upstream return route is dropping it.

If remote clients must also reach hosts on the server's LAN, remember that the LAN needs a return route to the tunnel subnet. That is routing rather than translation, and it is the step most often forgotten after the internet path finally works.

Skyldar greinar