Lately I have had some troubles with my routers. I hate calling them routers but calling them "NAT Gateways" would confuse a lot of people. I have been experiencing occasional disconnects from my USR 8000A router and complete lockups from my Linksys BEFSR81. I have a D-Link DI-604 lying around but I just didn't feel like fucking with it. These devices have pretty limited requirements (make network connections and transfer packets between them using NAT), there are other features but frankly it shouldn't be that demanding. None of my routers are good candidates for dd-wrt or OpenWrt so I wondered if it might be reasonable to make my own Linux "NAT Gateway". I am kind of partial to Debian but this could be done with any current distribution.
NOTE: It is important to realize that the Linux kernel version will influence what methods are used to route packets. Kernel 2.0 used ipfwadm for this functionality, while 2.2 used ipchains, 2.4 and 2.6 kernels use iptables. Since 2.4 has been around for almost a decade I think it is safe to say that iptables should be used if you are on anything even remotely current.
Step 0: Where to start?
To begin with, it probably helps to have some idea why you want to have a router and what it actually does. The Internet is not a "thing" and it is not a "place"… it is simply a bunch of little networks all plugged into each other. If you want to add your PC to the chaos then you can plug it right into your ISP. However, if you have more than 1 PC at home, or if you want to shelter your PC's from Internetards then a router is a simple solution. What's that mean? Well, let's start with the "shelter" concept. Network cables plug all this shit together, and TCP/IP is the language that computers speak when using those cables. There are different kinds of cables and different languages computers use, but for the home Internet user, ethernet and TCP/IP are pretty much the standard. TCP/IP works kind of like regular postal mail, everyone needs an address to communicate with others. Here are a few examples that might help make the analogy a little more clear
| IP address |
this would be your home address in postal mail |
| Packet |
this would be like the envelope you send your letter in |
| TCP/IP |
English |
| Router |
one of the postal service locations |
I'm just making that shit up but the idea is that there are some similarities between the way information moves around on the Internet and how it moves around by snail mail. So why do you care? Well, the addresses is why you care. In TCP/IP there are a limited number of addresses and that means there are a limited number of machines that can talk on the Internet. However, there's a workaround/exception that let's many more machines talk without having to use up extra addresses. Certain ranges of addresses are reserved for "private networks" and if you have a home router you have probably seen this in the form of 192.168.0.X addresses. Those addresses do not actually exist on the Internet. So how does that work?

If you were to plug your PC directly into your home Internet connection then it would likely end up with a real Internet address. This means that if your PC were running any "Listening Services" then they would likely be accessible by the Internet at large. What does that mean? Well if you had webserver software like IIS, Apache or PWS then anyone who could find you could see whatever your computer is serving up. Or if your machine had some ftp software running on it, then people could potentially be trying to log in to your ftp server. In case you hadn't picked up on it yet, this is bad. Now hopefully your PC is setup appropriately and you do not have anything listening for people who want to contact your computer. Perhaps you have a software firewall installed on your PC (or maybe it came with one) and your PC won't reply to these people. However, if your home network is configured as in the above picture, then the router is the one that gets the real address from your Internet provider. It then uses those fake 192.168.0.X addresses to talk to your computers, laptops, printers, iPods and other devices in your home. When your PC wants to see something on the Internet it passes the request to the router and the router uses it's real address to make the request for you. When the reply comes back, the router knows it is for your PC and it sends it in to you. In addition to all this, if you actually WANT your webserver to be accessible to the outside world, then you can setup "port forwarding" rules on the router to let just that service be accessed as if your PC was the one with the real address. Names for this are often NAT, PAT, SNAT and a couple others… the important part is the "T" at the end. It stands for Translation and that is what the router does to make individual services available from within your network. This is how a router "shelters" your PC, this is also how a router allows you to give multiple devices Internet access with only a single address.
Now that you know it is nice to have a router, why would you want to build one instead of just going to the store and buying one? Well I can only think of a few reasons
1. You want to learn about Linux
2. You want very detailed control of your router's rules
3. You want logging that doesn't suck
4. You want additional features your router doesn't have
5. You want to see if a Linux machine will be more stable than that locked up crappy router
6. You think I am brilliant and just want to copy me
7. You know that chicks dig geeks
Step 1: OK, where to really start?
I am sure that some people would love to brag about the antiquated hardware they can run a Linux router on, however, I'm not that guy. I would think that a mid-level Pentium III with 256M (maybe 512M) of memory would be nice. This is plenty of horsepower… of course it could be run on less but why push your luck? Too cheap to pull an old PIII out of the closet? Your machine will need two network cards of course, one to connect to your internal network and one to connect to the ISP's network. Then you'll need a copy of Linux. I would suggest going to Debian.Org and getting that, but you could use almost any distribution (though some of the instructions might be slightly different for other distros). If you decide to try Debian then the netinst CD should probably do fine. It is about 150M or so for the i386 version. Get it and burn it on to CD… run through the install on your box. I did a "standard system" install on my box (which has no X-Windows) but you can do whatever the hell you want with yours. Almost all of what is required for the router is command line stuff and editing text files. You can edit text files with something similar to Notepad in X-Windows or just use nano at the command line.
Step 2: Network Cards
Now once you have Linux up and running you need to make sure that you can see both of the network cards. In Linux the command line interpreter is often called "terminal", whatever you want to call it, you wanna open it and use the ifconfig command to check out your network cards.

Output from my ifconfig
What the hell is all that? Well the last one (the one called lo) is the "loopback" device which is not actually a network card but rather a reference to your machine's ability to talk TCP/IP. The ones you would care about are eth0 and eth1 (which are basically "ethernet device 0" and "ethernet device 1"). For those of you who are accustomed to starting at 1 when you begin counting, just suck it up and accept that this numbering system starts at 0.
Now what happens if you don't have eth0 and eth1?I would suggest editing your /etc/interfaces and check to make sure that your second NIC is listed there.
nano /etc/interfaces
You can find general information about the syntax and setup of the interfaces file here (PS: I know it says Ubuntu, but did you know that Ubuntu is based on Debian and many configuration files are very similar?). OK, you added an entry for the second nic but it doesn't show up still?
Well you can use the command
ifconfig -a
to see all your NICs even if they are currently down. If you do not see both your NICs then you are likely having a problem with the driver for one or both of them. You can use
apt-get install modconf
to install a nice little util for playing with the drivers… you'll probably have to scroll down a fair bit to get to the NIC drivers, but they're there. Just type in modconf to start it and it will pop up as a menu driven app that you navigate with your arrow keys. Make sure that the driver for your network card is loading, Google is your friend here, use the right driver. Now what if you have both cards listed but they list as eth0 and eth3? Where do you change those names? Well, if you made multiple changes with modconf or different network cards it might be udev screwing that up. I had this problem and had to
nano /etc/udev/rules.d/70-persistent-net.rules
to get rid of the extra junk that was left behind by installing different network cards and screwing with drivers. You'll see that the names of your NICs are there and you can change incorrectly named NICs as well as delete entries that are not needed. If this doesn't get both of your NICs setup as eth0 and eth1 you got something seriously fucked up going on.
NOTE: When setting up the /etc/interfaces file I found it best to give both cards static addresses on different subnets. If you don't know much about subnetting, try this explanation. If you still don't understand it much use 192.168.0.1 for your internal card and DHCP (or your ISP issued static IP) for your external card. This will mean that later on, during the DHCP portion in Step 6, you'll be using the 192.168.0.X subnet for your DHCP scope.
Step 2b: You have a PPPoE Link?
Some folks will have a PPPoE link that doesn't work quite the same as a regular DHCP or staic address. The PPP part stands for Point To Point Protocol and the oE is for "Over Ethernet". It is often seen on DSL links for authentication and as a result requires a name and password from your ISP. If this is what you have then you will want to
apt-get install pppoeconf
Have both of your network cards setup as eth0 and eth1, then plug in to your provider and run pppoeconf. It is a nice little menu driven app that will look for a concentrator to log in to, ask you for the name and password needed and then update your /etc/interfaces file for you. If you have this kind of link you will probably find that you need to use ppp0 as your external network card.
Step 3: Get Rid Of Shit You Don't Need
There's a few things that may have been put on your system by default during the install which you can get rid of, or should get rid of. Try using
userdel -r <name>
to get rid of a lot of the non-essential users that you'll find in /etc/passwd. It would be wise to keep root, a non-privileged user to login as, and man. When you are done doing that you might want to get rid of some applications that are installed by default. To dump them you can use
apt-get remove <packagename>
here's a little list of some of the stuff you can drop… I am sure there's more though:
eject
iamerican
ibritish
ispell
laptop-detect
wamerican
exim4-base
exim4-config
nfs-common
nfs-kernel-server
netatalk
portmap
analog
samba
Step 4: Remote Management
I personally didn't install X-Windows on my router box, my plan is to use SSH to manage it. SSH allows me to log in to it from wherever I need to, and it is encrypted so I could even access my router from a machine across the Internet if I wanted. You may choose to install X-Windows and you may even decide to use VNC (or SSH/VNC) to remotely manage it. Hell, maybe you'll plan to manage it right from the local console. To install SSH run
apt-get install ssh
If you elect to use SSH as I did, here are some suggestions I would make:
1. Set the ListenAddress directive in your /etc/ssh/sshd_config to the address of your internal network card. This will limit access to the router to your internal network only and will keep "external goofs" from trying to guess passwords.
2. If you make your router's SSH accessible from the Internet (the external card), use the Port directive to make it listen on a port other than 22. This means that when you try to connect to your router you'll have to connect to the non-standard port. It also means that jackasses in Korea are less likely to find your SSH server.
3. Deny root access to your SSH server with DenyUsers root. You may wish to further limit access to other usernames and groups but if you are the only one logging in to your router then the best setup might be only allowing a non-privileged user to SSH in and then use su to perform tasks that require admin access (which is most of what you would do on this box anyways).
Step 5: Is It A Router Yet?
Now to make your box into a router you need to use iptables commands. The commands are put together in a script (similar to a DOS batch file). The script should begin by clearing out any current rules, then setup the ability for your internal machines to "get out", then provide rules for machines to come in on (if necessary). The folks at AboutDebian have a REALLY nice writeup on these scripts, you first look at their Proxy page HERE and then the Firewall page HERE. You can seriously make these scripts relatively simple or brutally complex, it's up to you. It is entirely fine to use the proxy setup alone and if you need to allow for some port forwarding, just add two lines to allow access. Just remember that iptables will be cleared upon reboot so if this thing is your primary means of Internet access then you must add the script to your startup (see Automated Startup section on Proxy page). This part of the config is entirely personal based on your network config and what you want to have available from both directions.
Step 6: So That Is It Right?
Sure it is… but there are a couple of extra features that you will probably want for your router. DHCP services can be added by
apt-get install dhcp3-server
and then you modify /etc/dhcp3/dhcpd.conf to configure it. Assuming that your internal subnet is 192.168.0.X then you'll want to add a DHCP scope like this:
subnet 192.168.0.0 netmask 255.255.255.0 {
range 192.168.0.100 192.168.0.150;
option domain-name-servers 192.168.0.1;
option routers 192.168.0.1;
default-lease-time 3600;
}
The first line just names a domain and can really be whatever you like. The next couple of lines tell clients on your network to use 192.168.0.1 (your router) as their DNS server and their default gateway. A lease time and additional subnet infor are thrown in, and then finally a range of addresses is given to the DHCP server. If you bring up a client on this network it should likely receive 192.168.0.100 as it's IP address and it will depend on your router for all of it's Internet access needs.
Now if you just followed those instructions then your router is also designated as the DNS server for your network. So you should
apt-get install dnsmasq
so that it will answer the DNS queries from the clients on your network. To configure DNSMasq you want to edit /etc/dnsmasq.conf, and hopefully you'll find yours as well commented as mine. You should really need only minimal changes to this file, but if you are as anti-marketing as I am you'll want to use it for more than just DNS queries. You can use it to block ad servers! Scrolling down a little in the config file will bring to you a spot with an example of how to force an address for a particular name. You can add in ad servers here with an address of 127.0.0.1 which will point your browser to your local PC whenever it tries to load something from the listed servers. Mine came with this example
address=/doubleclick.net/127.0.0.1
This means that any machine using your router as a DNS server will not be able to load ads from doubleclick.net. This works for all services, not just browsing as well. Some ad servers use many subdomain names like ads1.crap.com and ads2.crap.com – to block these you do not need to list all of them, you can simply use a wildcard like this
address=/.crap.com/127.0.0.1
which will block crap.com and all of the machines under it. Another thing that might come in handy here is that you can also make entries in DNSMasq to point to things on your local network… like if you had a network printer setup as 192.168.0.10 you could make an entry in DNSMasq like this
address=/printer.mydomain.com/192.168.0.10
and then you wouldn't have to use the ip address, you could just refer to it as printer.mydomain.com. Finally, if you end up using DNSMasq for blocking, here's what might happen: You open "www.coolwebsite.com" and it has banner ads at the top from "ads.douchebag.com" but instead of seeing the ads, DNSMasq points the douchebag server to your local PC. If your PC is not a webserver (which most are not by default) then you might see a message saying "Can't Find Freakin' Content" where the ads used to be. This can be cleaned up significantly by setting up a little webserver on your local machine. Nothing fancy, just something that servers up a 1×1 transparent GIF file for all requests. I typically use Windows machines for a desktop environment and have found that Homer is a great little utility for this. Assuming that you want to run Homer all the time and that you don't want to see the Homer window/icon, you could optionally run it as a service and not allow it to interact with the desktop. This can be achieved with SRVANY and INSTSRV from the Windows Resource Kit (and perhaps a little reading on a previous post I made).