Your client can ping the gateway's address while every resource behind it stays unreachable. That pair of observations describes a host that is talking to you and a router that is not routing, which is a different role on the same machine. Forwarding is the switch between them.

The two roles are independent, and so are the two address families.

Answering Its Own Address Proves Nothing

When a packet is addressed to the gateway itself, the local stack consumes it and no forwarding decision happens. That is why a successful ping to the tunnel address or a management interface tells you the daemon is alive and the tunnel is up, while saying nothing about traffic destined for a network behind the box. The kernel only consults its forwarding path for packets that are not addressed to it.

Read the requirement as a role, not a setting: this host must move packets between two interfaces. A laptop that only needs to reach a remote network never takes that role, and a site-to-site endpoint always does. Reading the requirement that way explains why a working client configuration fails when moved to a gateway.

The same sentence applies to the firewall in front of the forwarding decision, which has its own policy about what may be forwarded.

Check Each Address Family Separately

IPv4 forwarding is one switch, and IPv6 forwarding is a different one with its own per-interface behaviour. Enabling the first says nothing about the second, and a dual-stack client can reach half a network while the rest stays dark. Two clients of different families can therefore disagree about the same gateway. Ask which family the failing client used before editing either setting. Confirm both before concluding the routing design is wrong.

sysctl net.ipv4.ip_forward
sysctl -a --pattern 'net.ipv6.conf.(all|default).forwarding'
nft list ruleset | head -n 40

On many distributions the value you read at runtime was placed there by a service or a configuration file, so a change made with a one-shot command can vanish at reboot. Find the file that owns the setting before you edit the runtime value.

Forwarding Is One of Four Requirements

A working forwarded flow needs four things at once: the client must know the destination is behind the tunnel, the gateway must have a route onward, replies must have a path back, and the firewall must permit the traffic. Source translation belongs to that design as an option rather than a rule, because a private routed network with symmetric paths does not need it and an asymmetric one usually does. Each of the four fails independently, which is why repairing one rarely moves the symptom. Write all four down before you change any of them.

Cloud platforms add a fifth consideration. Some enforce source and destination checks on instances, which drops forwarded packets regardless of what the guest's kernel is configured to do. The platform's own networking documentation is the authority there, not the sysctl output inside the VM.

Test From the Client, Not the Gateway

A test run in the gateway's own shell traverses none of the forwarding path you just enabled. Generate the traffic from the client that has the problem, and confirm it reaches something behind the gateway rather than the gateway itself. That is the only test that exercises the role you changed.

Keep listener rules and forwarding rules distinct in your head and in the change record. Opening the VPN port admits clients to the service; it grants them nothing on the network behind it, and the two look identical in a firewall listing that has grown for years.

If packets arrive and the service then rejects the user, you have moved past networking. Continue with application authorization instead of widening the forwarding policy again.

ተዛመድቲ ጽሑፋት