The importance of a minimal firewall.

I have long been an avid user of the well known interface to iptables – Shorewall. Of late though I have suspected it is slowing my network down. I once decided to see what actual iptables rules it was creating and ran “iptables -L”. There was a lot of output and I wasn’t sure was all of it necessary. It niggled away at the back of my brain for the last few months, and I decided yesterday it was time to do something about it.

I first looked at another “user-friendly” interface that would perhaps give me more control and proper ipv6 support, so I installed Firewall Builder. However it seemed quite complex and after spending some time trying to get to grips with the interface I decided it would be easier to type the rules in manually and anyway that would be the only way I was 100% sure everything in there was needed.

I familiarised myself with the Packet Filtering HOWTO and thought the easiest thing to do would be use “iptables-save” to copy the existing Shorewall rules into an iptables friendly format. The resultant file was 9k long and appeared to have a lot of user defined chains for no good reason. It also didn’t make good use of the multi-port option for tcp connections and therefore there were dozens of rules where there only needed to be one.

I started off by making the rules multi-port which reduced the size of the file by 4k. It also made the internet faster, I’m assuming because packets were taking a long time getting through all the unnecessary rules, somebody may be able to correct me on this? Having done this I decided to get rid of all the user defined chains and just use the built-in ones also. I now have a rules file which is 1.8k long and it has given a much needed boost to my internet connection even when bandwidth is poor (100 Kbps). Here it is:-

# Generated by iptables-save v1.3.8 on Wed Apr  9 12:59:20 2008
*nat
[19:1444] -A POSTROUTING -s 192.168.0.0/255.255.255.0 -o ppp0 -j MASQUERADE
COMMIT
# Completed on Wed Apr  9 12:59:20 2008
# Generated by iptables-save v1.3.8 on Wed Apr  9 12:59:20 2008
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
[53789:23887964] -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
[590:36788] -A INPUT -i lo -j ACCEPT
[273:16433] -A INPUT -i tun0 -j ACCEPT
[41:7913] -A INPUT -i eth0 -p udp -m multiport --dports 53,67,631 -j ACCEPT
[21:1290] -A INPUT -j LOG --log-prefix "iptables denied: " --log-level 7
[19:1444] -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
[0:0] -A FORWARD -i eth0 -o ppp0 -p tcp -m multiport --dports 20:22,80:81,443,554,2083,2096,2401,3306,3389,3690,5900,7070,8000 -j ACCEPT
[0:0] -A FORWARD -i eth0 -o ppp0 -p tcp -m multiport --dports 8443,8080,8890 -j ACCEPT
[19:1444] -A FORWARD -i eth0 -o ppp0 -p udp -m multiport --dports 123,1194,5060 -j ACCEPT
[0:0] -A FORWARD -j LOG --log-prefix "iptables denied: " --log-level 7
[49623:17855294] -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
[3876:232460] -A OUTPUT -o tun0 -j ACCEPT
[590:36788] -A OUTPUT -o lo -j ACCEPT
[47:2676] -A OUTPUT -o eth0 -p tcp -m multiport --dports 631 -j ACCEPT
[0:0] -A OUTPUT -o eth0 -p udp -m multiport --dports 68 -j ACCEPT
[3:194] -A OUTPUT -o ppp0 -p udp -m multiport --dports 53,123,1194,3130,3544,5072,6277,20114,24441,50206 -j ACCEPT
[72:4320] -A OUTPUT -o ppp0 -p tcp -m multiport --dports 20:23,25,37,43,80,110,366,443,554,873,980,993,2083 -j ACCEPT
[0:0] -A OUTPUT -o ppp0 -p tcp -m multiport --dports 2095:2096,2401,2703,3389,3690,3874,5900,7070,8000,8080,8890,10050 -j ACCEPT
[0:0] -A OUTPUT -j LOG --log-prefix "iptables denied: " --log-level 7
COMMIT
# Completed on Wed Apr  9 12:59:20 2008

I will now explain each part of the file so you know what it is doing.

# Generated by iptables-save v1.3.8 on Wed Apr  9 12:59:20 2008
*nat
[19:1444] -A POSTROUTING -s 192.168.0.0/255.255.255.0 -o ppp0 -j MASQUERADE
COMMIT
# Completed on Wed Apr  9 12:59:20 2008

The above simply NATs/masquerades the local network (I have an Ubuntu box that sometimes needs internet access). Obviously your network addresses might be different so the network portion should be changed accordingly. Also your internet interface might be different “eth1”, etc so you might need to change that. For some reason if the comments aren’t in there (beginning with #) iptables won’t start (at least not on my machine).

# Generated by iptables-save v1.3.8 on Wed Apr  9 12:59:20 2008
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]

Sets the default policy for you chains i.e. what to do if none of the rules match. I have it set to DROP, you might like it to REJECT instead. Each to their own.

[53789:23887964] -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
[590:36788] -A INPUT -i lo -j ACCEPT
[273:16433] -A INPUT -i tun0 -j ACCEPT
[41:7913] -A INPUT -i eth0 -p udp -m multiport --dports 53,67,631 -j ACCEPT
[21:1290] -A INPUT -j LOG --log-prefix "iptables denied: " --log-level 7

This sets what happens when traffic comes “in” to an interface. It might be coming in from the internet, your local network or even the loop-back. Think of it as the chain you need to play with to open up services to the internet or LAN.

The first line allows traffic related to an existing connection through the firewall. The next 2 lines are allowing all traffic into the loopback (lo) and VPN interface (tun0). To explain this, the only traffic going into the loopback will be from the loopback, and applies to network services you are accessing locally i.e. from the machine itself. You can talk about the merits/drawbacks off allowing all traffic into a VPN interface, however writing this now, my thoughts lead me to the conclusion even VPN participants shouldn’t be trusted fully and I should probably make that more restrictive.

The penultimate line is allowing DNS, DHCP and IPP traffic in through the LAN interface (eth0), mainly so my Ubuntu box can get an IP and resolve DNS from my main machine.

The last line simply logs any other INPUT traffic in syslog the default policy we defined earlier then silently drops it.

[19:1444] -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
[0:0] -A FORWARD -i eth0 -o ppp0 -p tcp -m multiport --dports 20:22,80:81,443,554,2083,2096,2401,3306,3389,3690,5900,7070,8000 -j ACCEPT
[0:0] -A FORWARD -i eth0 -o ppp0 -p tcp -m multiport --dports 8443,8080,8890 -j ACCEPT
[19:1444] -A FORWARD -i eth0 -o ppp0 -p udp -m multiport --dports 123,1194,5060 -j ACCEPT
[0:0] -A FORWARD -j LOG --log-prefix "iptables denied: " --log-level 7

The FORWARD chain refers to routing or NAT i.e. this is traffic that will come in on one interface and then go out on another (hence why FORWARD rules have both the -i and -o options). This allows my Ubuntu box to communicate with the internet. I should mention here the reason there are 2 rules for tcp traffic is that multi-port rules only allow 15 ports per rule (a port range counts as 2 ports) so I was forced to create 2 rules for tcp. The penultimate rule is for udp and the last rule again logs any other traffic attempting to be routed/NATed.

[49623:17855294] -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
[3876:232460] -A OUTPUT -o tun0 -j ACCEPT
[590:36788] -A OUTPUT -o lo -j ACCEPT
[47:2676] -A OUTPUT -o eth0 -p tcp -m multiport --dports 631 -j ACCEPT
[0:0] -A OUTPUT -o eth0 -p udp -m multiport --dports 68 -j ACCEPT
[3:194] -A OUTPUT -o ppp0 -p udp -m multiport --dports 53,123,1194,3130,3544,5072,6277,20114,24441,50206 -j ACCEPT
[72:4320] -A OUTPUT -o ppp0 -p tcp -m multiport --dports 20:23,25,37,43,80,110,366,443,554,873,980,993,2083 -j ACCEPT
[0:0] -A OUTPUT -o ppp0 -p tcp -m multiport --dports 2095:2096,2401,2703,3389,3690,3874,5900,7070,8000,8080,8890,10050 -j ACCEPT
[0:0] -A OUTPUT -j LOG --log-prefix "iptables denied: " --log-level 7
COMMIT
# Completed on Wed Apr  9 12:59:20 2008

This last section pertains to the OUTPUT chain. It concerns connections that originate on the machine and go “out” through one of the interfaces to the internet, LAN, etc. Again we are allowing any traffic going out through the loopback and VPN interfaces as we allowed any traffic coming in previously. The next 2 rules refer to the LAN interface and are for allowing DHCP and IPP traffic to the Ubuntu box (my Ubuntu box has a printer connected which I share using CUPS). The next 3 rules apply to the internet interface and allow the machine itself to access the internet on various tcp and udp ports.

I could also add in rules to prevent smurf attacks and the like but as I am blocking almost all traffic and not sending any response to blocked traffic I don’t see there is scope for such an attack, again maybe somebody else could correct me if they feel I’m wrong.

Leave a comment