Secure NAT setup with iptables

I have a Debian running device that needs to act as an internet-gateway. On top of that I want to provide a firewall that not only blocks inbound traffic, but also outbound traffic. And I figured iptables should be able to do the job.

The problem: I've configured NAT properly (I think?), but once I set the default policy to DROP and add rules to for instance allow HTTP traffic from inside the LAN, HTTP is not going through. So basically my rules don't seem to work.

Below is the initialization script that I use for iptables. The device has two NICs, respectively eth0 (the WAN interface) and eth1 (the LAN interface).

echo 1 > /proc/sys/net/ipv4/ip_forward

# Flush tables
iptables -F
iptables -t nat -F

# Set policies
iptables -P INPUT DROP
iptables -P OUTPUT DROP

# NAT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -A FORWARD -i eth0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT

# Allow outbound HTTP from LAN? 
iptables -A FORWARD -i eth1 -o eth0 -p tcp --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT

Can anyone shed some light on this?

Solved: Mike suggested to use telnet and an IP instead of domain name to test HTTP traffic, and that led to two discoveries: DNS wasn't working properly and outbound filtering wasn't working either (I could telnet to port 8080).

So first of all I added rules to allow the LAN clients to use services of the gateway, DNS for instance. (And yes, don't worry, I'm going to narrow this down to offered services)

iptables -A INPUT -i eth1 -d 172.16.0.1 -j ACCEPT
iptables -A OUTPUT -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT

You'd think I'd be able to do DNS-requests now. And I actually could, but the requests were timing out because the gateway couldn't do DNS-requests itself. Rules for outbound DNS were added:

iptables -A OUTPUT -o eth0 -p tcp --dport 53 -j ACCEPT
iptables -A OUTPUT -o eth0 -p udp --dport 53 -j ACCEPT

Finally I set default policy of the FORWARD chain to DROP. And we were back to square one.

I was about post an update when I saw Ram's reply that suggested I allow inbound traffic for existing connections. I also applied this principle on the OUTPUT chain above.

iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

So now it seems to be working exactly how I want it. Full script here. Thanks!


Solution 1:

You need to allow replies to your outbound requests.

Solution 2:

I was going to add this as an answer after I got a response to the comment, but it looks like you followed my train of thought... I noticed that you didn't have DNS allowed on the inside interface. Good luck with your services.