Why Use MASQUERADE/SNAT Instead of NAPT/PAT – Analysis

nat;

Story

I have a VPN wireguard virtual interface wg0 (can be anything else) and a physical interface eth0. I want to route packets from the VPN to my LAN, or from an interface to another interface.

Almost all the blogs, articles, tutorials advice using MASQUERADE or Source NAT only: iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Moreover, IP masquerade is simply a SNAT (Source NAT), it doesn't change the source port.

Question

  • Am I wrong thinking I should use a NAPT/PAT instead?
  • For completeness, how can I add a NAPT/PAT rule with iptables and/or nftables?

Thoughts

There might be (source port) conflicts between packets generated by the host and forwarded from wg0 (or any other virtual/physical interfaces). IMHO NAPT must be used to avoid these conflicts.

RFC 2663, Network Address Port Translation (NAPT)

Best Answer

If the destination can route its traffic to the source, no NAT or PAT is required.

As an example, no NAT/PAT is required if the VPN clients in 10.8.0.0/24 want to talk with your LAN devices in 192.168.1.0/24, as long as the involved devices can route to the other network (through their gateway).

When the source is in a rfc1918 (private IP) network and the destination is a public IP, because rfc1918 networks are not routable over Internet, a NAT is required to replace the private IP by the public IP. This is source address translation. This job can be done by a SNAT, not a PAT.

Furthermore, you are wrong assuming SNAT/MASQUERADE does not change source ports.

The --to-source option is used to specify which source the packet should use. This option, at its simplest, takes one IP address which we want to use for the source IP address in the IP header. If we want to balance between several IP addresses, we can use a range of IP addresses, separated by a hyphen. The --to--source IP numbers could then, for instance, be something like in the above example: 194.236.50.155-194.236.50.160. The source IP for each stream that we open would then be allocated randomly from these, and a single stream would always use the same IP address for all packets within that stream. We can also specify a range of ports to be used by SNAT. All the source ports would then be confined to the ports specified. The port bit of the rule would then look like in the example above, :1024-32000. This is only valid if -p tcp or -p udp was specified somewhere in the match of the rule in question. iptables will always try to avoid making any port alterations if possible, but if two hosts try to use the same ports, iptables will map one of them to another port. If no port range is specified, then if they're needed, all source ports below 512 will be mapped to other ports below 512. Those between source ports 512 and 1023 will be mapped to ports below 1024. All other ports will be mapped to 1024 or above. As previously stated, iptables will always try to maintain the source ports used by the actual workstation making the connection. Note that this has nothing to do with destination ports, so if a client tries to make contact with an HTTP server outside the firewall, it will not be mapped to the FTP control port.

https://www.frozentux.net/iptables-tutorial/iptables-tutorial.html#SNATTARGET

Note that if you device want to reach a remote server on a given destination port, there are chances that the operating system already assigned a random source port over 1024. Reaching a remote HTTPS server on port 443, does not involve that the source port is 443.

Related Topic