In Linux netfilter, what is the difference between SNAT, MASQUERADE and DNAT? At which hook must each be applied, and when is MASQUERADE the better choice than plain SNAT?
answer
- which end of the packet is rewritten
- the hook follows the routing decision
- one form asks the interface for its address
- replies are handled without a rule
- ports get rewritten when addresses are shared
basics
~20 sDNAT rewrites a packet's destination and runs in PREROUTING, before routing. SNAT rewrites the source in POSTROUTING, after routing. MASQUERADE is SNAT that takes the new source address from the outgoing interface automatically, which suits a changing address.
solid answer
~50 sThey differ in which end of the packet they rewrite and therefore where they must sit. `DNAT` changes the destination address and port, so it belongs in `PREROUTING` — routing has to see the new destination to send the packet the right way. `SNAT` changes the source, so it belongs in `POSTROUTING`, once the outgoing interface has been chosen. `MASQUERADE` is a convenience form of SNAT: instead of you naming the new source address, the kernel takes the primary address of the outgoing interface at translation time. That makes it the right choice when the address is not known in advance — a DHCP WAN link or a dial-up style connection — and it also drops the related tracking entries when that interface goes down. When the address is static, plain SNAT is preferable because it skips the per-flow lookup. In both directions, replies are translated back automatically from the connection-tracking entry; you never write a reverse rule.
go deeper
Know that one form rewrites the source and the other the destination, and that the masquerade form fills in the address of the outgoing interface for you. Say which is used to publish a service and which to share an address.
Explain why each must sit on its side of the routing decision, and that the reverse translation is done from the tracking entry rather than by a second rule you write.
Show operational judgment: pick SNAT over masquerade on a static-address gateway, recognise port exhaustion as the scaling limit, and diagnose the case where a rule seems ignored because the flow is already tracked.
Own the tradeoff between translating at the host and pushing it to the network, the address-pool sizing that keeps a gateway from exhausting ports, and the observability cost of losing original client addresses behind translation.
## Two directions, two hooks Network address translation on Linux comes in exactly two flavours, distinguished by which end of the packet is rewritten. **Destination NAT (DNAT)** rewrites the destination address and optionally the port. Its use case is publishing something: traffic arrives at an address the outside world can reach, and you redirect it to a machine or port that the outside world cannot. It must be applied in `PREROUTING`, because the routing decision runs immediately afterwards and has to see the new destination in order to choose the right interface and next hop. For traffic generated on the host itself there is an equivalent chain at `OUTPUT`; because that path has already been routed, applying a DNAT there causes the kernel to redo the routing lookup. **Source NAT (SNAT)** rewrites the source address and optionally the port. Its use case is hiding: many hosts behind one public address, or making traffic appear to originate from a specific address. It must be applied in `POSTROUTING`, because only after routing does the kernel know which interface the packet will leave by — and that usually determines which source address makes sense. `REDIRECT` is the degenerate case of DNAT: rewrite the destination to an address of the receiving machine itself, which is how transparent proxies capture traffic without naming the local address explicitly. ## MASQUERADE as a special SNAT `MASQUERADE` performs source NAT, but instead of you supplying the address, the kernel looks up the primary address configured on the outgoing interface at the moment the flow is translated. Two practical consequences follow. First, it is the correct tool when the address is not stable — a DHCP-assigned WAN interface, a PPP link, a laptop moving between networks. A static SNAT rule naming an address that has since changed silently produces packets nobody will route back. Second, it is slightly more expensive: the address lookup happens per new flow rather than being baked into the rule. It also has a deliberate side effect — when the interface goes down, connection-tracking entries associated with it are dropped, on the reasoning that after the address changes those flows are dead anyway and keeping them would let a stale mapping survive. With a static address on a busy gateway, plain SNAT is the better choice. ## The reverse direction is automatic The single most important thing to say in an interview here is that **you never write a rule for the return traffic**. When the first packet of a flow is translated, the kernel records both the original tuple and the translated tuple in the connection-tracking entry. Reply packets are matched against the reply tuple and un-translated automatically, and every subsequent packet in the forward direction is translated straight from the entry without re-entering any nat chain. This is also why the nat table is only consulted for packets in the NEW state. ## Port translation and collisions When many internal hosts share one external address, source ports must be rewritten too, otherwise two flows could collapse onto the same tuple. The kernel's NAT engine picks a free source port, preferring to keep the original where possible. Because port selection was historically predictable, iptables and nftables both offer a fully-random port selection option for cases where predictability is a security concern. The port space is the real scaling limit of a NAT gateway: one external address gives roughly 64k source ports *per destination tuple*, and a busy gateway with a single address will exhaust ports long before it exhausts bandwidth. The fix is more external addresses in the SNAT pool. ## Common failure shapes - **DNAT works inbound but replies never arrive.** The reply must come back through the same NAT box; if the internal server has a different route out, the client receives a packet from an address it never talked to and drops it. - **A NAT rule appears to be ignored.** The flow is already tracked, so its packets bypass the nat table entirely — new rules only take effect for new flows. - **MASQUERADE on a static-address gateway.** Works, but adds a per-flow lookup and unnecessary tracking-entry churn on interface events. - **Forgetting that translation is per flow, not per packet.** Rate limits, marks or logging placed in the nat table only ever see the first packet of each flow.
- After SNAT rewrites the source of an outbound packet, what makes the reply reach the original host?The connection-tracking entry. When the first packet was translated, the kernel stored both the original and the translated tuple. Replies match the reply tuple and are un-translated automatically, and the mapping applies to every later packet of that flow without re-entering the nat table. No reverse rule exists or is needed.
- Why does MASQUERADE flush connection-tracking entries when its interface goes down?Because the address it translated to belonged to that interface. Once the interface drops, the address may change, so those flows can no longer receive replies and the stored mappings are stale. Dropping them frees the entries and prevents a new flow from colliding with a mapping that can never complete. Plain SNAT, which names a fixed address, does not do this.
- What limits how many simultaneous flows a single-address NAT gateway can support?The source-port space. Sharing one external address means each flow needs a distinct source port for a given destination tuple, giving roughly 64k concurrent flows per destination endpoint and far fewer in practice once tracking timeouts hold entries open. Adding external addresses to the translation pool is the real remedy; tuning timeouts only buys headroom.
- A port forward set up with DNAT works, but the internal server sees connections from the gateway rather than the real client. Why might that be?Because source NAT is also being applied to the same traffic, usually a broad masquerade rule in POSTROUTING that matches it. DNAT alone preserves the client's source address; the client identity is lost only when something rewrites the source as well. Narrowing the source-NAT rule so it does not cover already-DNATed inbound flows restores the original address.
saying these in an interview costs you the question
- Writes a second rule to translate the replies back
- Puts destination rewriting after the routing decision
- Treats MASQUERADE and SNAT as identical in cost
- Thinks NAT rules are evaluated on every packet
- Believes DNAT alone hides the client's source address