For clients to reach anything beyond the WireGuard server (the internet, or the server’s LAN),
the server must forward and masquerade their traffic. WireGuard runs these as PostUp/PostDown
commands in the server’s [Interface].
iptables (most common)
Replace eth0 with the server’s outbound interface (ip route show default):
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
%i is the WireGuard interface (wg0). The FORWARD rule permits forwarding; MASQUERADE
rewrites the source IP to the server’s so replies come back.
With IPv6 too
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i %i -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -D FORWARD -i %i -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
nftables variant (modern distros)
PostUp = nft add table inet wg; nft add chain inet wg post '{ type nat hook postrouting priority 100 ; }'; nft add rule inet wg post oifname "eth0" masquerade; nft add chain inet wg fwd '{ type filter hook forward priority 0 ; }'; nft add rule inet wg fwd iifname "%i" accept
PostDown = nft delete table inet wg
The PostDown simply drops the whole inet wg table, cleaning up every rule at once.
Don’t forget IP forwarding
NAT does nothing without forwarding enabled — see the IP-forwarding recipe
(net.ipv4.ip_forward = 1).
Verify
sudo iptables -t nat -L POSTROUTING -n -v # see the MASQUERADE rule + packet counts
# from a client:
curl ifconfig.me # should show the server's IP (full tunnel)
Wrong interface = no traffic. The single most common mistake is leaving eth0 when the WAN NIC
is ens3, enp1s0, etc. Check with ip route show default and use that name in the rules.