Why does everybody use MASQUERADE/SNAT instead of NAPT/PAT?
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)
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.
You have somehow the wrong distinction between SNAT/MASQUERADE
and NAPT/PAT
. It is not there.
In Linux, there are two types of dynamic NAT rules, both of which you call "NAPT":
- source NAT, which intends to leave destination address intact and only changes the source address. Sometimes it will also change the source port. For example, if the connection tracking table already contains the record with this particular (proto, src-addr, src-port, dst-addr, dst-port) tuple (src-addr and src-port are after translation), to be able to make a distinction which is which, the new translation must use another src-port (because this is the only degree of freedom), so the "NAPT" will inevitable take place. The examples of SNAT-type rules are
SNAT
andMASQUERADE
. The difference between them is that with SNAT you are required to specify in the rule which address to translate into (and, probably, which range of ports to use), while with the MASQUERADE it makes the choice itself, based on which interface the packet is destined to egress. Both of them are to be installed intoPOSTROUTING
chain, after most other processing was taken place, including the routing of the packet. This type of rule is used to allow many computers to be hidden behind the single exit IP address, e.g. to access the Internet for the LAN and so on. This would include any VPN users too, if you intend to access Internet via VPN. - destination NAT, which leaves the source address as it was and only updates the destination address, and, if you configured that, the destination port, so this is "NAPT" rule too. Rules of this type are
DNAT
,REDIRECT
,CLUSTERIP
and probably some other, I don't remember them all; these are installed intoPREROUTING
chain, because the routing decision usually should be changed under the influence of the rule. The packet which originally destined to the machine itself (has its address as a destination) and was to be traversedINPUT
and reached some local process, is being translated instead and, after traversingFORWARD
chain it is being forwarded further to some other system. Or vice versa. Where to go, INPUT or FORWARD, is the routing decision which we must change with the rule. This type of the rule is used to make access to some internal system from the Internet.
Sometimes, by the way, both rules might be used for the single packet (and connection). This is the special case, but useful if you need packets from some external system (so DNAT must be used in the PREROUTING) to appear as coming from some internal address (for which SNAT is used in POSTROUTING).
In Linux there is also the static NAT-type rules like NETMAP
which is quite special and seldom used. I doubt you are talking about it and that you have seen any howtos which mention this type of the rule.
Linux makes absolutely no distinction between private (RFC1918) and public addresses. You can NAT your public subnet if you want to (but this will be a waste of addresses). You can leave private IPs without translation (but usually this will lead to no Internet connectivity for them).
The VPN is nothing more than additional network interface in the machine and should be treated as such. Consequently, you are allowed to use public addresses for VPN, if you have them. For example, I may have some /29 subnet routed to by VPN router and set up OpenVPN so this whole public subnet will be my VPN network! While OpenVPN example looks artificial, the WireGuard is much more likely to be configured like that. For instance, the new namespace solution allows the wireguard to be the only interface in the system. If there is a requirement for the system to directly have a public IP (I won't discuss any reasons for which this requirement might come from), it's inevitable you'll end up using public IPs inside the VPN! Most probably, without any NAT for them.