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.
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.
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.
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:
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,220.127.116.11 # 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 18.104.22.168 #cns1.gc-net.eu nameserver 22.214.171.124
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:
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
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]