Saturday, April 15, 2006

Debian Firewall Router w/ IPTables HOWTO

After reading my last post about the Netgear router dilemma, you can probably imagine why I am now writing this post. That's right! Standalone routers that cost less than $1000 suck! What I set about to do was use a debian box as a router (normal), but I wanted the added options of having a dual-wan setup (not-so-normal). My situation is unique -- I don't care at all about load-balancing, since one connection is used for internet access and the other is just used to access an internal school network. So the box is as follows:
-Debian 2.6 kernel, testing because stable is always behind and testing is mostly stable
-3 Ethernet cards
-Doesn't have to be fast, maybe PII 700mhz or so if you want to be able to type without watching the characters come up on the screen in slow motion.
-A little bit of patience... or a lot. Depending on how my tutorial works out.

The Howto:

Step 1: Install the debian base system.

I used the netboot CD for debian-testing, which can be obtained from I use the MIT mirror because it's blazing and they don't really care about bandwidth. Over Adelphia, I am able to max out my 900 or so kbps connection. Sweet.

Anyway, get the netboot .iso image, burn it and install it. If you need more in-depth help installing Debian, use google or drop me an email. Chances are I won't be able to help you but I'll give it a shot. When it asks you to chose packages, you can pretty safely de-select all of them. This will save a few hundred megs of space at most on the hard drive of your new router box.

Step 2: Set up networking

Ok, I lied. I actually don't want the 3-ethernet connection system anymore, just a 2-network system. But you can follow these directions and I will let you know what to change to make it a 3-honed system.

To set up networking in debian, you need to edit the /etc/network/interfaces file. You could also just use ifconfig within your iptables script, but I find that to be stupid -- if you do it that way, I find you, too, to be stupid. Just so you know. Here is what my file looks like:
helga:~# more /etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The adelphia network interface
auto eth0
iface eth0 inet dhcp

# The local network interface
auto eth1
iface eth1 inet static

If you are interested in having a 3-network router, you would need to add the eth2 entry in this file. You should follow the same syntax that is used above, but edit the declarations as needed.

Step 3: Install iptables
First we need to install iptables. Since we de-selected everything we could at the base install, there may well be some other dependencies that apt requires you to download also. Just let it do its thing after typing in the following command:
helga:~# apt-get install iptables

It should give you some information as it installs; make sure there are no errors from the install script, as this will ruin your install. When apt is done installing iptables, we need to tell the kernel to forward ip traffic.
helga:~# echo 1 > /proc/sys/net/ipv4/ip_forward

That line tells the kernel to load ip forwarding each time it boots up. I think. The first time I tried to get these scripts working, I forgot this line -- it won't work if you don't type this, and it will make you want to cut yourself trying to figure out what the problem is if you don't. Seriously, just type it.

Step 4: Configure your iptables rules
Since iptables is installed and the kernel knows that it is supposed to be forwarding traffic between interfaces, we need to set up some rules. The syntax to use in iptables is kind of difficult to get the hang of at first, but allows for a quite a bit of control over the rule sets themselves. When a packet is traversing the iptables chain, it starts at the top and goes down. If you add a command with a -j, which means jump, iptables will jump to the next chain. If it makes it through the chain it jumped to, it will go back to the original chain. There are two commands that are necessary to have the router work at all -- they tell it where to forward traffic to and from:
helga:~# iptables -A FORWARD -i $IN_NIC -s $IN_NET -j ACCEPT
helga:~# iptables -t nat -A POSTROUTING -o $OUT_NIC -j MASQUERADE

Those are just the bare essentials for iptables. There are several other lines that you should type to make sure that things are secure. Be sure to replace the $IN_NIC with the name of your internal interface (eth0) and $OUT_NIC with the name of your external interface (eth1). $IN_NET is the network address of your internal network. In my case, that is If you don't know what that is, you probably read too far. Congratulations, you should be able to access the outside world from your internal network.

Step 5: Finishing up -- FTP connections and hardening the firewall
You may have noticed that you can't use passive FTP through your new linux firewall. Bummer. Luckily, someone smarter than me and smarter than you (you are reading my tutorial after all) designed another kernel module that allows the box to keep track of FTP connections. Type the following and it will work... MAGIC!!:
helga:~# modprobe ip_nat_ftp
helga:~# modprobe ip_conntrack_ftp

You may also have noticed that if you do a port map on your linux box, there are lots of ports open -- a big security risk. The best way to solve this problem is to selectively allow certain ports through (http, ftp, etc) and block everything else. However that has its advantages and disadvantages. You can make the ultimate call, but rather than go into the syntax of how to block or open each port, I am just going to give you the script that I use.
helga:~# more
# Tell the script some info about the interfaces

# Let the script find out some info about the interfaces
# IP addresses obtained from ifconfig.
OUT_IP=$(ifconfig ${OUT_NIC} | grep "inet addr" | \
awk '{print $2}' | sed 's/.*://g')
IN_IP=$(ifconfig ${IN_NIC} | grep "inet addr" | \
awk '{print $2}' | sed 's/.*://g')
# Tell the script what the network addresses are:

# Load the FTP connection tracking modules
/sbin/modprobe ip_nat_ftp
/sbin/modprobe ip_conntrack_ftp
echo 1 > /proc/sys/net/ipv4/ip_forward

# Flush the current policies
iptables -F

# Set the main drop policies
# problems here, it disables everything, need to re-think.

# Drop all packets which have an invalid state (ie, spoofed)
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A FORWARD -m state --state INVALID -j DROP
iptables -A OUTPUT -m state --state INVALID -j DROP

iptables -A FORWARD -i $IN_NIC -s $IN_NET -j ACCEPT
iptables -A INPUT -i $IN_NIC -s $IN_NET -j ACCEPT
iptables -A OUTPUT -i $IN_NIC -d $IN_NET -j ACCEPT
iptables -t nat -A POSTROUTING -o $OUT_NIC -j MASQUERADE

/etc/init.d/dhcp stop
/usr/sbin/dhcpd eth1

# Accept traffic to and from lo
iptables -A INPUT -i lo -p all -j ACCEPT
iptables -A OUTPUT -o lo -p all -j ACCEPT

# Accept traffic to and from the internal network
iptables -A INPUT -i $IN_NIC -d $IN_NET -p all -j ACCEPT
iptables -A OUTPUT -o $IN_NIC -d $IN_NET -p all -j ACCEPT

# Accept traffic that is already established
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allow ping from the internet
iptables -A INPUT -i $OUT_NIC -p icmp --icmp-type echo-request -j ACCEPT

# SSH Port forwarding
iptables -A INPUT -p tcp --dport 222 -j ACCEPT
iptables -A INPUT -p udp --dport 222 -j ACCEPT

# Web Server Port forwarding
iptables -A INPUT -p tcp --dport 62356 -j ACCEPT
iptables -A INPUT -p udp --dport 62356 -j ACCEPT

# Drop all traffic not specified above
iptables -P INPUT DROP

That should be enough information about where to start to give you some bearing. If you need further help, use google or send me an email. Chances are I won't be able to help you but I'll give it a shot. That's it for now.


  1. Thank you so much for your brilliant article.
    I just wrote a tutorial on how to set up Arno IPTABLES firewall.
    May be it may help someone to setup his own firewall based on IPTABLES.

    In my tutorial you can find some examples for a mail server and for a Proxy server using SNAT and port forwarding.
    The location of my tutorial is here:

    I wish it is useful to someone.

  2. This is really great. I like to be visiting your blog. Thanks very much for sharing all this great information here.
    CNC Router Machines