Wednesday, May 11, 2011

Dangers of IPTables NAT with DHCP

For Archer, I have setup a small private LAN for all the core resources to share with a common out into the main network, which connects to the Internet. I use Linux's IPTables via masquerade for NAT or routing the packets from the private network into the Internet and DHCP to automatically assign IP addresses to the resources. Recently, I extended the router to support other hosts to use it to bridge into the local network, which may or may not be responsiblef or a whole host of other issues. The two primary issues were routing of bridged packets through IPTables and DHCP messages traversing the bridge, both request and replies from both sides.

The routing of bridged packets was particularly difficult to figure out. I had recently setup a web server, which had a public IP address and was bridged into the LAN. It was pingable and could ping other IP addresses within the LAN, but it couldn't ping the gateway. Furthermore, it was accessible from the Internet but could not initiate communication with the Internet. It was very strange behavior. I whipped out tcpdump and quickly noticed that packets it was sending out via the bridge were being picked up by IPtables masquerade and having their source address change. So that when the packet came back, it had no where to go. The resolution to this problem was pretty easy: add "-s ip_range/mask" to the masquerade iptables line. So this:
iptables -t nat -A POSTROUTING -o bridged -j MASQUERADE became
iptables -t nat -A POSTROUTING -s -o bridged -j MASQUERADE
where bridged is the network bridge into the LAN, i.e., a Linux bridge connecting eth0 to other devices wanting access to the LAN and is the private address space. Now masquerade will only forward packets with the source address

Perhaps, doing this opened up the other problem, which was that resources on the LAN were somehow getting DHCP requests to the private network. This never makes people happy and worst of all, those individuals were losing their Internet connectivity. This could be related to forwarding of broadcast Ethernet packets as well. The resolution for this was a bit easier, simply drop all DHCP packets that come across the NAT:
iptables -A FORWARD -p udp --dport 67 -i bridged -j DROP
iptables -A FORWARD -p udp --dport 67 -o nat -j DROP
In this case, packets coming from the bridged device (-i bridged) are those on the LAN looking for IPs. The packets coming from the nat device (-o nat) are those on the private network looking for IPs. These rules effectively prevent the retransmission of dhcp packets. The reality is, I probably should prevent the transmission of multicast / broadcast messages from crossing the NAT, since there exists no gateway for packets to get into the private network.

Anyway, this was a rather unfun discovery as I found NOWHERE online that discusses these two issues when configuring NATs. I hope this turns out to be useful for someone else out there.