Building a Linux based router from a laptop

Introduction
I have a Linksys WRTL54GL running the opensource firmware DD-WRT and have been quite happy with this up until recently. A short while back I upgraded my Internet connection to a 50/50 mbit and then the problems started. It turned out that the Linksys WRTL54GL can’t route much more than 30/30 mbit on the WAN side.

My old WRTL54GL router and my new Thinkpad T42 based router.

This means that even though the computers on the LAN side could easily talk to each other with 100/100 mbit through the internal switch I could not connect to the Internet with more than 30/30 through the router. As I researched the marked I discovered two things: firstly, it was hard to find information on the WAN side speedlimit on the product spec sheets and secondly that the few that I found was capable was expensive (>1500 DKK). This page does actually list the WAN side speeds:Router Charts [smallnetbuilder.com]

At my work I had the option to buy a old retired Thinkpad T42 cheaply and I had and an old PCMCIA netcard lying around, so I figured I might as well put a router together myself using CentOs. I am aware that there are many router distributions available, see en.wikipedia.org/wiki/List_of_router_or_firewall_distributions, but I work with RHEL and CentOS daily and would like the freedom of not using a dedicated distribution.

The plan
I have a picture of the services that the new router should be able to do manage. This is really not very demanding as I already have another server running NFS, CIFS, SSH, WWW any many other services. This could of course also have been done on my existing server but I found it more pleasing to have the router separated from sever that hosts data.

  • Route WAN side with 100/100 mbit.
  • Provide NAT (IP masquerading) for the clients on the LAN side.
  • Serve as a local caching DNS server.
  • Serve as a local DHCP server.
  • Serve as a statefull firewall for my LAN.

Installation
I would have liked to use UNetbootin to install CentOs 5.4 on the laptop but UNetbootin currently have a bug, so I just downloaded the netinstall image from the fast Danish host klid.dk:
ftp://ftp.klid.dk/centos/5.4/isos/i386/
and once it came to the server part I entered

site: ftp.klid.dk
path: ftp/centos/5.4/os/i386

In the server I have put an extra PCMCIA network card. This meant I had two devices: one connected to directly to the Internet and one connected to my LAN side gigabit switch:

WAN - eth0: RealTek RTL8139
LAN - eth1: Intel(R) PRO/1000

On the WAN side I made eth0 get a IP from my ISP’s DHCP server. On the LAN side I made eth1 have the following settings (from /etc/sysconfig/network-scripts/ifcfg-eth1)

# Intel Corporation 82540EP Gigabit Ethernet Controller (Mobile)
DEVICE=eth1
BOOTPROTO=static
BROADCAST=192.168.1.255
HWADDR=00:11:22:33:44:56 (Altered for this post only)
IPADDR=192.168.1.1
NETMASK=255.255.255.0
NETWORK=192.168.1.0
ONBOOT=yes
IPV6INIT=no

and for completness eth0:

# D-Link System Inc DFE-690TXD CardBus PC Card
DEVICE=eth0
BOOTPROTO=dhcp
HWADDR=00:11:22:33:44:55 (Altered for this post only)
ONBOOT=yes
DHCP_HOSTNAME=wasserman
IPV6INIT=no
PEERDNS=no

After this I completed the rest of the install. Now the router was running but none of the computers on the LAN side could access the Internet and the router it self was showing off everything to the Internet. Time to configure.

Setting dnsmasq as DHCP and DNS server
I initially started out setting up caching nameserver with bind and a DHCP server with dhcpd, but found out that the configuration was to much cumbersome for my liking and needs. Instead I ended up installing dnsmasq which was really easy to setup. dnsmasq serves both as a DHCP server and caching DNS server for my network. I installed dnsmasq with

[root@wasserman ~]$ yum install dnsmasq

And edited the configuration file with the following lines:
Edited the configuration file /etc/dnsmasq.conf:

 
# Number of IP's to cache.
cache-size=10000
# Enforce strict order of lookups from /etc/resolv.conf
strict-order
# Defines some names for my internal computers 
address=/nobel/192.168.1.153
address=/bohr/192.168.1.151
# For a certain MAC computer made the certain MAC always get the same IP
dhcp-host=00:11:22:33:44:55,192.168.1.149
# Always give computers the same addreses. 
dhcp-host=euler,192.168.1.113,infinite
dhcp-host=bohr,192.168.1.151,infinite
# Set's up the DHCP server
dhcp-range=192.168.1.100,192.168.1.150,255.255.255.0,24h
# Provide these DNS servers to the DHCP clients
dhcp-option=6,192.168.1.1,8.8.8.8
# For network (PXE) based linux install on my other server
dhcp-boot=/var/lib/tftpboot/pxelinux.0,nobel,192.168.1.153
# Save some of the activity to a log file. 
#log-queries
log-dhcp
log-facility=/var/log/dnsmasq.log
log-async=100

To explorer other DHCP options such as I did with DNS servers see:

[root@wasserman ~]$ dnsmasq --help dhcp
Known DHCP options:                    
  1 netmask                            
  2 time-offset                        
  3 router                             
  6 dns-server 
...

Now made dnsmasq start after a reboot and started the service

[root@wasserman ~]$ chkconfig dnsmasq on
[root@wasserman ~]$ /etc/init.d/dnsmasq start

By the way I used namebench to find the fastest DNS. I entered the results into /etc/resolv.conf with my localhost (127.0.0.1) first since I am doing caching:

nameserver 127.0.0.1
# Google public DNS 
nameserver 8.8.8.8
#cns1.gc-net.eu
nameserver 77.243.34.11

Enable IP forwarding
At this point the computers on my LAN could talk to each other and receive addresses from my DHCP server but not access the Internet. First I had to enable IP forwarding. The current state can be shown by asking the kernel:

[root@wasserman etc]$ cat /proc/sys/net/ipv4/ip_forward
0

So to enable it just type

[root@wasserman etc]$ echo 1 > /proc/sys/net/ipv4/ip_forward

This will however not survive a reboot, so in /etc/sysctl.conf edit following line to enable it:

# Controls IP packet forwarding
net.ipv4.ip_forward = 1

Setting up a firewall with iptables
At first I wrote a Firewall using iptables that was by default open and afterwards locked down ports – this was easy to get working as any mistakes just left holes open in the firewall and hence seemed fine. The better method is however to deny everything and pokes holes instead. I based my firewall on the following script:
http://www.debuntu.org/sites/www.debuntu.org/files/firewall-simple.txt

Obviously I had to open up some ports to allow SSH access to my server:

# SSH to nobel 
$IPT -t nat -A PREROUTING -i $WAN -p tcp --dport 22-j DNAT --to 192.168.1.153:22
$IPT -A FORWARD -i $WAN -p tcp  --dport 22 -m state --state NEW -j ACCEPT

But after my remote rsync to a server failed after a transfering some big files I found that I had to make a further hack to allow big transfers over SCP and SFTP:

# Solves annoying problem with big files over ssh (includes scp and rsync)
# https://bugzilla.redhat.com/show_bug.cgi?id=161898
$IPT -A FORWARD -m state --state INVALID -m tcp -p tcp --sport 22 -j ACCEPT

Final tweaks
I have disabled alot of services I don’t use such as http, bluetooth, named, setroubleshoot,… This I did using the following tool:

[root@wasserman ~]$ system-config-services

Having a server running 24-7 can be annoying if not very silent. The Thinkpads fan was by default humming away at 3600 RPM even though the CPU usage is close to 0% all the time. By modifying the thinkpad_acpi driver to allow tinkering I can reduce this. First I add the following line to /etc/modprobe.conf to have the driver allow that I change the fan speed.

options thinkpad_acpi fan_control=1

After this I reboot to make the drive being reloaded.

Finally I installed munin-client to monitor my server (described in detail in: Server monitoring with Munin [tjansson.dk]

Only registered users can comment.

  1. I do believe all the concepts you have presented on your post. They’re really convincing and can certainly work. Still, the posts are too brief for newbies. Could you please extend them a little from next time? Thank you for the post.

Leave a Reply