Tuesday, December 28, 2010

NAT how does it work

Yet another attempt to explain NAT, since every time I do it I'm unsatisfied
with the clarity of the result. This time it follows the progress of a TCP
SYN packet from an external client to an NAT'd server and the server's
SYN+ACK response.

SCENARIO

The simplest of set-ups - an ISP router, FW-1 and a single internal host
with an RFC1918 address. All boxes are assumed to have just been booted,
i.e. routing entries present but ARP tables empty. Addresses as follows :-

INTERNET
|
ISP Router
a.b.c.1 / 010101010101 (IP/MAC)
|
a.b.c.254 / 020202020202
Firewall-1
192.168.1.1 / 030303030303
|
192.168.1.2 / 040404040404
Internal Host (public address = a.b.c.2)

NARRATIVE

We'll start at the point where the remote client's (x.y.z.8) TCP SYN
datagram has reached the ISP router via its Internet i'face. At this point
the relevant addresses are as follows :-

Src MAC = Some other Internet router's
Dst MAC = MAC address of Internet interface of ISP Router
Src IP = x.y.z.8
Dst IP = a.b.c.2

The router looks in its routing table and sees that the a.b.c.0 subnet is
locally attached, so as far as it's concerned the next hop is the Dst IP
address itself. The router sees that it has no MAC address for a.b.c.2 and
does an ARP broadcast out of its a.b.c.1 interface. There's no real host
with address a.b.c.2 to reply to the ARP but if you've set the Firewall up
properly (published ARP entry in Unix, local.arp file entry in NT) it will
reply giving 020202020202 as the MAC address for the IP address a.b.c.2.

The router is now happy, puts an entry in its ARP table to save having to
ARP again (for a while), changes the Src MAC address of the datagram to that
of its a.b.c.1 interface and the Dst MAC address to that of the Firewall (as
per the new ARP entry), thus :-

Src MAC = 010101010101
Dst MAC = 020202020202
Src IP = x.y.z.8
Dst IP = a.b.c.2

The card driver on the external side of the Firewall passes the datagram to
the firewall module which checks that it has a rule allowing x.y.z.8 to talk
to a.b.c.2. It has, so it sticks an entry in the connection table and passes
the datagram up to the IP level UNCHANGED.

IP looks at it and says 'this is not for me' and looks in its routing table.
Since routing always uses the most specific matching entry (i.e. host first,
subnet second, network third and default last) it finds your manually-added
routing entry saying that the next hop for a.b.c.2 is 192.168.1.2. It
doesn't have a MAC address associated with 192.168.1.2 but knows that it is
on the 192.168.1.0 subnet so does an ARP broadcast out of its 102.168.1.1
interface. The Host replies, the FW's IP stack creates an ARP entry and
changes the MAC addresses of the datagram again as follows :-

Src MAC = 030303030303
Dst MAC = 040404040404
Src IP = x.y.z.8
Dst IP = a.b.c.2 (STILL!)

The IP stack passes the datagram down to the firewall module which notes the
need for address translation, alters the Dst IP address to 192.168.1.2 and
records an entry in the translation table. Now we have :-

Src MAC = 030303030303
Dst MAC = 040404040404
Src IP = x.y.z.8
Dst IP = 192.168.1.2

The firewall module passes the translated datagram to the card driver which
pops it on the 192.168.1.0 network.

The Host's IP stack receives a TCP SYN datagram with its MAC address and IP
address, passes it to the listener which replies with a SYN+ACK datagram
addressed to x.y.z.8. The Hosts's IP stack looks at its routing table, sees
the default routing entry pointing to 192.168.1.1, realises that it doesn't
have an ARP entry for 192.168.1.1, does an ARP request, stores the result
and forwards the datagram as follows :-

Src MAC = 040404040404
Dst MAC = 030303030303
Src IP = 192.168.1.2
Dst IP = x.y.z.8

The card driver on the internal interface of the firewall passes the
datagram to the firewall module which sees the entry in the translation
table and modifies the source address of the datagram to a.b.c.2. The module
then looks in the connection table, sees that this is part of an established
connection and passes it up to the IP stack.

The IP stack says 'this is not for me', looks in its routing table,
eventually matches against the default entry pointing to a.b.c.1, ARPs to
get the MAC address of a.b.c.1, adds an ARP table entry, modifies the MAC
addresses and forwards the datagram as follows :-

Src MAC = 020202020202
Dst MAC = 010101010101
Src IP = a.b.c.2
Dst IP = x.y.z.8

and thereafter normal routing takes care of the datagram.

No comments: