Put a capture on both sides of a VPN gateway and one flow can show four different addresses. Source NAT rewrites where a packet claims to come from; destination NAT rewrites where it is going. Masquerade is not a third direction, it is a source-NAT rule that takes its address from the outgoing interface instead of a fixed value. Name which of the three you actually need and most "the VPN is broken" tickets collapse into a question about the return path.

What each rule rewrites

Source NAT, usually written SNAT, changes the source address of a flow as it leaves a router or gateway. The receiving service replies to the translated address, and the translating box reverses the change using state it kept for that connection. On Linux that state lives in conntrack, which is why conntrack -L prints the original and reply tuples side by side.

Destination NAT, DNAT, changes the destination instead. A packet addressed to a public address on UDP 51820 can be rewritten to an internal WireGuard server at 10.8.0.2:51820. That is how a home router or a cloud load balancer publishes a VPN listener, and it says nothing about what the tunnel may carry afterwards.

Masquerade belongs to the SNAT family. The rule names no address; it uses whatever address the outgoing interface holds when the packet leaves. Linux gives it its own target, and it is the usual pick on a WAN interface that gets its address from DHCP or PPPoE.

Where the mapping lives decides the failure

Record the tuple at every boundary: before the tunnel, inside it, and on the public interface. A capture inside the tunnel legitimately differs from one outside it, and anyone comparing the two without knowing where translation happens will chase the wrong host.

Return traffic must pass through the device that holds the mapping. If a reply takes another route, a second uplink, a policy route, or a provider that has never heard of your private range, the stateful reverse translation never happens and the client sees one-way traffic. Adding more source NAT rarely fixes a missing return route; it can hide the symptom on one flow while breaking address-based policy everywhere else.

The other common mistake is expecting a tunnel to create routability. A private client whose packets go out to the internet needs a valid egress arrangement: a default route, a forwarding gateway and, usually, source translation to a public address. Encryption on its own does not make a private address reachable.

Masquerade or explicit SNAT

Compare the two by what they promise. Masquerade picks the egress address, explicit SNAT pins it. On a gateway with a stable public address, pinning gives logs and partner allow-lists one predictable value. On a dynamic WAN link, a pinned SNAT address becomes wrong the moment the lease changes, which is exactly the case masquerade was built for.

Scope matters as much as the choice. A masquerade rule matching every packet that leaves the gateway, with no source or destination limit, also translates traffic you meant to keep intact, including traffic to other private networks. Limit the rule to the client range, the intended destination and the interface.

Policy-based IPsec is where this bites hardest. strongSwan's forwarding how-to walks through enabling IP forwarding and adding a source-NAT rule for clients, and the same documentation covers excluding traffic that must keep its original address. Translate a source before the security policy matches it and the tunnel can come up while the traffic still drops, because the packet no longer looks like the selector that was negotiated.

Decide too what the far end should see. After translation a service sees the gateway, not the individual client. That simplifies return routing and at the same time flattens logs and defeats per-client allow-lists. If preserving client addresses matters, plan a routed return path instead of hiding them to make a test pass.

Reading the rules on a Linux gateway

A remote-access gateway with clients on 10.8.0.0/24 and a WAN interface named eth0 needs forwarding enabled and a filter policy that permits the flow before any NAT rule can help. The iptables version keeps both directions in the nat table:

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 51820 \
  -j DNAT --to-destination 10.8.0.2:51820

The nftables form uses the same two hooks with a named interface and an explicit chain:

nft add rule ip nat postrouting ip saddr 10.8.0.0/24 oifname "eth0" masquerade
nft add rule ip nat prerouting iifname "eth0" udp dport 51820 dnat to 10.8.0.2:51820

Both snippets assume the filter chain already accepts the forwarded flow. NAT is not a permit rule, and a correctly translated packet can still be dropped one table later. Confirm the live mapping with conntrack -L, confirm what is loaded with nft list ruleset or iptables-save -t nat, then capture on both interfaces to see the address actually change.

Failure modes that look like a bad rule

Hairpin traffic is the classic. An internal client that reaches an internal server through the server's public address needs the DNAT on the way in and a source translation on the way back out, otherwise the server replies straight to the client and the reply is rejected. The fix is a second, narrower rule for that internal-to-public case, not a wider masquerade rule for everything.

Double translation is the quiet one. A client already behind carrier-grade NAT arrives at your gateway with an address you cannot route back, so you translate again. It works, but logs now carry two hops of private addressing and any investigation needs both mappings. Policy-based IPsec adds a third twist: translate before the policy match and you get an SA that is up with no traffic passing, which reads like a firewall bug rather than a NAT one.

Then there is the test that passes and the deployment that fails. Running the NAT command by hand proves the mechanism, not the configuration. A rule added at runtime disappears on reboot or on the next interface event, and a masquerade rule tied to an interface that renumbers can silently change the address the far end sees. Put the rule in the owning firewall's configuration and re-test after a reconnect.

Checklist before you save the rule

Name the direction first: source, destination, or both. Then identify who must hold the state, the gateway, the upstream router or the IPsec peer, and confirm the reply path returns through it. Limit the rule to the client range, destination and interface you actually intend, and decide in advance whether the far end should see the gateway or the original client address.

Test from a client, not from the gateway. A browser on the gateway itself can bypass the client translation rule entirely, so a working page there proves nothing about the tunnel. Send one client-originated request, watch the counters and the conntrack table, and repeat it after a tunnel reconnect and a WAN address change if either is possible where you work.

Nuŋlɔɖi siwo ku ɖe eŋu