- 1 Introduction
- 2 Installation
- 3 Remote administration - OpenSSH
- 4 Custom kernel
- 5 NIC config
- 6 ADSL connection - rp-pppoe
- 7 DNS & DHCP for the LAN - dnsmasq
- 8 Sharing the connection
- 9 Intrusion detection & prevention - Snort
- 10 Finishing touches
- 11 Advanced features
This document will (try to) explain how to turn a spare computer into an internet gateway using NAT, allowing you to share a single broadband connection with an entire LAN.
NOTE: This document's purpose is to set up a box exclusively as a gateway/router, this means that it's not suited (although it could be adapted or used partially) to set up a shared connection between 2 (two) 'desktop' PCs using cross-over cables, as the PC where this document applies will be turned into a 'server', not having the desktop applications necesary for normal use, and should be conected to a hub/switch.
Not only will the gateway route, it will also feature:
- dial-up support: if you have an xDSL-connection, you'll be able to share it
- remote administration: the gateway will probably a headless machine sitting in a dark spot of your house where it won't disturb anyone. An SSHd will allow us to connect remotely to the machine and execute commands as if we had physical access to it.
- DHCP server: allowing dynamic IP configuration of connected machines
- caching DNS server: useful when your ISP's DNS server is temporarily down
- a stateful firewall: the gateway won't just let any incoming packet through. By using iptables (combined with Shorewall if you want), you can set up your own rules adding security to your LAN.
- intrusion detection and prevention (to do): Snort will inspect the incoming and outgoing packages on the firewall, detecting suspicious (viral/spyware/adware/...) behaviour and take appropriate countermeasures.
These features require extra packages and configuration but will enhance the functionality of the gateway greatly:
- transparent caching web proxy: the Arch box can be set up to act as a proxy server, increasing download speeds on frequently used websites and reducing your internet traffic: the files are cached on the Arch box. Because it's transparent, computers on the LAN will automagically use it for HTTP traffic.
- ad blocking: the web proxy can be configured to block (static and dynamic) ads from a list of known spam hosts. This will not block pop ups, but pop ups will be empty. :D The ads won't even be downloaded at all, again improving your internet speed and traffic and generally making surfing the web a nice experience again. This doesn't require any configuration on the LAN computers either!
- traffic shaping / QoS: when you're sharing an internet connection, chances are at least one person will use it to leech the internet. To prevent other users from getting suicidal (or worse, homicidal!) by slow connections, packet loss and enormous latency we'll do some traffic shaping. This way, a few .torrents shouldn't prevent the rest from online gaming.
- NTPd: the gateway will run a time server, allowing computers on the LAN to sync their system clock.
I've split up the wiki into this basic guide, and an advanced guide. Mainly because MediaWiki started complaining about the length of the document and possible browser incompatibilities. ^_^
Since the gateway is connected directly to the internet, security is a big issue. It shouldn't run any services available from the outside world. Towards the LAN, it should only run gateway specific services. So no HTTPd, no FTPd, Samba, NFSd, ... those belong on a server on the LAN or DMZ (if you want to make these services available to the outside world) as they can introduce security flaws.
I am fully aware of specific gateway distributions such as IPCop, Smoothwall and FreeSCO to name a few. I have even been using IPCop for years and it's never failed me. Making my own gateway just seems like a useful experience to gain some Linux networking experience. Since Arch is so easy to configure and to maintain, it makes it a great choice for the gateway I'm going to build!
- a fully i686 compatible computer: as you (should) know, Arch is i686 optimized, meaning it will not run on anything slower / older than a Pentium Pro or Pentium II.
- some RAM: routing shouldn't be an intensive job, 64MB of RAM should suffice unless you start loading your gateway up with tons of features. If you're going to implement the advanced features, more is better of course.
- some hard disk: for now, make sure you have at least a GB of diskspace available. Maybe in the future, if I don't have anything better to do, I might make a custom gateway repo full of tiny packages with only the essential stuff compiled in. Until then, we'll use regular Arch packages. The base install will take up around 500MB of space and if you want to use a caching web proxy, you will need to reserve space for the cache as well.
- at least two network interfaces: a gateway connects two networks with each other. You will need to be able to connect those networks to the same box. The most common combination is two simple ethernet cards. You can also use an ADSL-modem and a ethernet card, or an ADSL-modem and a wireless card, ... whatever floats your boat. As long as you at least have two! ;)
- a hub, switch or straight UTP cable: what's the use in having a shiny gateway if you can't connect other computers to it. :P
- (Arch) Linux experience: if "compile your own kernel" scares you, you're better off with one of the aforementioned gateway distributions: you'll save yourself a lot of time, effort and frustration.
This is the hardware I'm going to use as a gateway. I'll be installing most of the features described in this Wiki. I'll update this page with performance information.
- Intel Celeron 466 (66MHz FSB)
- 256MB SDRam
- WD Caviar 13GB (IDE, 5400rpm)
- 3com 3c905B 10/100MBit FD PCI
- similar DEC NIC
- Thomson Speedtouch 510v4 ADSL Ethernet modem (in bridged mode)
- 4MBit / 256KBit ADSL connection
- simple 8 port switch
I'm currently sharing the same connection with a Pentium 200 with 80MB of RAM and ~ 1.5GB HD space. It works quite well, so if you have a box with the minimal specs to run Arch, it should be fine. Booting and installing packages will just take a little longer, your connection shouldn't suffer though.
- eth0 will be the network card connected to the LAN. It will have a static IP.
- eth1 will be the network card connected to the network (or WAN). Depending on your situation it will have a static IP or obtain one through DHCP.
First off, you need to install ArchLinux. If you don't know how, use the ArchLinux install guide. Once you've installed Arch, boot it and upgrade all the packages to their latest version:
Add a normal user so you don't have to be logged in as root constantly: I don't know why, but I get nervous logging in as root. Also, we'll set up OpenSSH to not allow root logins, so a normal user has to be added or you won't be able to login remotely.
Trimming down Arch
Now that you have the latest and greatest of every base package, it's time to ... remove as many packages as possible! We're making a gateway, so keeping unneeded packages only "bloats" the system: the packages take up space and they will be updated every once in a while aswell. Even worse: the more stuff you have on your computer, the bigger the chance is one or more packages have security exploits in them. So have pacman print a list of orphaned packages (packages without dependencies, i.e. packages that can safely be removed without breaking other packageS):
pacman -Qe | less
Obviously, make sure you only remove packages you won't need: if you're going to hook up your gateway to an ADSL-modem, you'd better not removed rp-pppoe or ppp. If you're not sure what a package does, simply read its description:
pacman -Qi rp-pppoe
Here's a list of packages suitable for removal. Review every package to see if you can safely remove or not!
- hwd: I know what hardware I have
- lshwd: a dependency of hwd
- usbutils: although my box has USB-ports, I won't be using them. If you're going to use a USB modem (good luck with that! :')) you better keep this.
- libusb: dependency of usbutils
- kernel26: the Arch-kernel is configured to support as many desktops and servers as possible. So there's a lot of functionality in it we don't need, and it's missing a lot of necessary routing stuff! For the time being, a custom kernel is in order.
- devfsd: we will be using udev, devfsd is deprecated anyway.
- mkinitrd: unless you are going to use a ramdisk with your kernel, there's no need for this.
- pcmciautils: only useful if you're using PCMCIA/CardBus hardware.
- grub / lilo: you can only use one, so remove the other one.
- nano / vim: I never use vim (shame on me, I know), so why would I keep it? Install your favorite editor and get rid of the rest.
- raidtools: only useful if you're running RAID.
- e2fsprogs / jfsutils / reiserfsprogs / xfsprogs: you only need the package for the filesystem you are using.
- wireless_tools: only useful if you're going to build a wireless gateway
Completely remove the packages you don't need:
pacman -Rn package1 package2 package3
Remote administration - OpenSSH
Wouldn't it be a lot easier doing the rest of this Wiki remotely so you can put your gateway out of your sight and remove its monitor and keyboard? Make sure you leave in the power cord and network cable tho. ;)
Install and run OpenSSH!
pacman -S openssh && /etc/rc.d/sshd start
You'll get a connection refused if you try to ssh into your box though. You have to edit your /etc/hosts.allow and add a line telling your box it's OK to recieve ssh connections.
echo "sshd sshd1 sshd2 : ALL : allow" >> /etc/hosts.allow
This will allow every IP-address (cf. ALL) to try and log into your box. In the next part, we'll configure the SSHd to only accept connections from the LAN, but it certainly won't harm if you specify your LAN's subnet in /etc/hosts.allow. If you don't know which one you're going to use, or even worse, don't know what a subnet is, I'll come back to this later.
The SSH daemon provides a secure remote shell, meaning that (when using default settings) anyone who has a valid user account on the computer running the SSHd, can remotely log into the computer. It should be clear that this service should be well secured.
Fire up your favorite edtior and open /etc/ssh/sshd_config. Put the following "code lines" in it.
ListenAddress 10.0.0.1:2367 # Changing the port and address the daemon listens on: SSH's default port is 22. # For a little added security, change it to a different (much higher) number. # We also don't want the daemon listening for connections on the WAN side, the internet is an evil place nowadays. # Replace 10.0.0.1 by the IP your gateway will be using, 2367 by the portnumber of your choice. AllowUsers foobar firstname.lastname@example.org # Setting users allowed to log in: this is a very simple yet powerful option. #As you know, root is always the superuser on a Linux box. So if you want to gain access to a box, #you can start "cracking" the root password by brute force. If you don't allow root to log in with SSHd, # the cracker has to find out a valid user first which will take him more time. You can also add a host from which #the user must login ... added security!!! ^_^ DenyUsers root # I don't know the difference between "DenyUsers root" and PermitRootLogin no # "PermitRootLogin no" but better to be safe than sorry. Protocol 2 # Only allow ssh2 connections, safer than ssh1 connections.
Read the Using SSHD and SSH wiki if you don't know how.
Since we're going to compile a kernel for a gateway, it doesn't have to be packed with patches. I went with a simple vanilla 2.6.16 kernel, because I figured it would be the most stable. You can choose whatever kernel with whatever patchset you like, but this wiki is based on a recent 2.6 kernel so if things don't turn out the way you'd hoped you're on your own. Be sure to read up on udev.
To keep my kernel lean and mean, I only compiled in the utmost important parts. Everything I don't need to be able to boot is compiled as a module. It's up to you to decide whether you want a modular, a monolithic or a somewhere in between kernel. Just remember to add the modules you want to load at boot time to the MODULES=() in /etc/rc.conf. I'm totally ripping off the next part: it's my first gateway kernel so I had no idea what to put in and what not. Fortunately, I found Mike Frysinger's Gentoo Wiki page and he's made a nice list of stuff you
- really need (marked x)
- need if you are going to share ADSL (marked a)
- need if you want traffic shaping (marked s)
Networking ---> [*] Networking support Networking options ---> <M> Packet socket <*> Unix domain sockets [*] TCP/IP networking [*] IP: multicasting [*] IP: advanced router [*] IP: policy routing [*] IP: use netfilter MARK value as routing key <M> IP: tunneling <M> IP: GRE tunnels over IP [*] IP: broadcast GRE over IP [*] IP: multicast routing [*] IP: PIM-SM version 1 support [*] IP: PIM-SM version 2 support [ ] IP: ARP daemon support (EXPERIMENTAL) [*] IP: TCP syncookie support (disabled per default) <M> IP: AH transformation <M> IP: ESP transformation <M> IP: IPComp transformation <M> IP: tunnel transformation <M> INET: socket monitoring interface <M> The IPv6 protocol [*] IPv6: Privacy Extensions (RFC 3041) support <M> IPv6: AH transformation <M> IPv6: ESP transformation <M> IPv6: IPComp transformation <M> IPv6: IPv6-in-IPv6 tunnel [*] Network packet filtering (replaces ipchains) ---> Core Netfilter Configuration ---> <M> Netfilter Xtables support (required for ip_tables) <M> "CLASSIFY" target support <M> "CONNMARK" target support <M> "MARK" target support <M> "NFQUEUE" target Support <M> "NOTRACK" target support <M> "comment" match support <M> "connbytes" per-connection counter match support <M> "connmark" connection mark match support <M> "conntrack" connection tracking match support <M> "DCCP" protocol match support <M> "helper" match support <M> "length" match support <M> "limit" match support <M> "mac" address match support <M> "mark" match support <M> "pkttype" packet type match support <M> "realm" match support <M> "sctp" protocol match support <M> "state" match support <M> "string" match support <M> "tcpmss" match support IP: Netfilter Configuration ---> mark everything you need <M> IPv6: Netfilter Configuration (EXPERIMENTAL) ---> mark everything you need <M> QoS and/or fair queueing ---> [s] QoS and/or fair queueing mark everything you need <M> Device Drivers ---> Network device support ---> [*] Network device support <a> PPP (point-to-point protocol) support [a] PPP filtering <a> PPP support for async serial ports <a> PPP support for sync tty ports <a> PPP Deflate compression <a> PPP BSD-Compress compression <a> PPP over Ethernet (EXPERIMENTAL)
You'll notice I have enabled quite a lot in the kernel. This is because of my inexperience. I made modules of everything I thought had something to do with this project, so if I don't use some functions all they cost me was a little extra compile time. :) The above kernel options are just meant for the routing part of the kernel. Don't forget to select the regular stuff for a working kernel and support for all your hardware!
Compile and install the kernel
make bzImage && make modules && make modules_install
I still use these commands to build everything, they still work fine. Don't forget to copy the kernel to /boot and update your bootloader. It's possible (and recommended) to build the kernel on another machine. Just do the exact same things. Once it's done compiling, do the following
scp /usr/src/<routerkerneldir/arch/i386/boot/bzImage <normaluser>@<routerip>:/boot/vmlinuz26 scp -r /lib/modules/<kernelversion> <normaluser>@<routerip>:/lib/modules
Setting the aliases
When you let udev handle loading the modules, you'll notice your NIC's switch names: one boot your LAN NIC is eth0, the other boot it's eth1. The easiest fix for this is to load the modules "manually". Edit /etc/rc.conf and make put in these lines:
MOD_AUTOLOAD="no" MODULES=(3c59x tulip)
Those are the modules for my NIC's. Change them to the ones you need. 3c59x is loaded first, so my 3com NIC will be eth0, and my DEC NIC will be eth1. I don't know how long this quick and easy fix will work, if you want to do it the udev way, check out this Wiki page.
Open /etc/rc.conf once more and scroll down to the network config section. Here's where you define how your network cards should obtain their IP. The LAN card will have a static IP, I'm going with 10.0.0.1 because it's easy to type. :D I'm building a gateway for a small student home with 4 rooms so I'm keeping the subnet fairly small: 4 bits allow 16 IP's. 16 - 3 IP's:
- one for the network address: 10.0.0.0
- the gateway: 10.0.0.1
- and the broadcast address: 10.0.0.15
leaves 13 IP's for computers on the LAN. This translates into
lo="lo 127.0.0.1" eth0="eth0 10.0.0.1 netmask 255.255.255.240 broadcast 10.0.0.16" eth1="dhcp"
ADSL connection - rp-pppoe
Using rp-pppoe, we can connect an ADSL modem to the eth1 of the firewall and have Arch manage the connection. Make sure you put the modem in bridged mode though, otherwise the modem will act as a router too.
pacman -S rp-pppoe
It's in Arch's base installation, so you probably already have it.
The questions are all documented. You can select "no firewall" because we'll let Shorewall / iptables handle that part.
There's a bug in the package, so we need to manually create a symbolic link:
ln -s /usr/sbin/pppd /sbin/pppd
Everything should be in place.
DNS & DHCP for the LAN - dnsmasq
We'll use dnsmasq, a DNS and DHCP daemon for the LAN. It was specifically designed for small sites. As an alternative, you could also use dhcpcd and bind, but you're on your own.
pacman -S dnsmasq
Edit /etc/dnsmasq.conf and add the following lines
interface=eth0 # make dnsmasq listen for requests only on eth0 (our LAN) expand-hosts # add a domain to simple hostnames in /etc/hosts domain=foo.bar # allow fully qualified domain names for DHCP hosts (needed when "expand-hosts" is used) dhcp-range=10.0.0.2,10.0.0.14,255.255.255.240,1h # defines a DHCP-range for the LAN: from 10.0.0.2 to .14 with # a subnet mask of 255.255.255.240 and a DHCP lease of 1 hour (change to your own preferences)
Somewhere below, you'll notice you can also add "static" DHCP leases, i.e. assign an IP-address to the MAC-address of a computer on the LAN. This way, whenever the computer requests a new lease, it'll get the same IP. That's very useful for network servers with a DNS record. You can also deny certain MAC's from getting an IP. Evil!! ^_^ Now start dnsmasq
and add the daemon to the DAEMONS list in /etc/rc.conf. I initially had trouble getting dnsmasq to start. If you get an "could not create leases: no such file or directory" error or something similar, create a few directories (they're mentioned in dnsmasq's man page)
mkdir -p /var/db mkdir -p /var/lib/misc
and try starting dnsmasq again. It should work nicely from now on.
Sharing the connection
Time to tie the two network interfaces to each other!
pacman -S iptables
iptables is a very powerful firewall. So powerful that I haven't bothered reading up on all the types of rules it can use to filter network traffic. However, this HOWTO describes an iptables setup that you can use if you don't want to use shorewall.
pacman -A shorewall-3.0.6-2.pkg.tar.gz
Replace the filename with the correct one.
Time to configure Shorewall! Open its config file in /etc/shorewall/shorewall.conf and start editing. The file is very well documented.
SUBSYSLOCK=/var/run IP_FORWARDING=On : it's a gateway, remember! ;) STARTUP_ENABLED=Yes # when you're done editing
After installing shorewall, run
pacman -Ql shorewall | grep Sample
to see where the sample files are. cd into the directory "two-interfaces" and copy the contents to the /etc/shorewall/ directory. Now use Shorewall's guide to set up the files correctly.
Read the document carefully. Take special care to change eth0 and eth1 (or ppp0 in if you're using PPPoE where appropriate in your config files as the Shorewall guide uses different names for the interfaces. When you've followed it thoroughly, make the following changes:
- /etc/shorewall/interfaces : add "dhcp" to the loc line to allow computers on the LAN to make use of our DHCP server
- /etc/shorewall/rules : add
ACCEPT loc $FW TCP 2367
but change 2367 into whatever port you have your SSH server listening on.
From here on, the Arch box is operational! Connect a hub or switch to eth0 and a computer to the LAN to test it.
--Add a script to open up ports on the firewall to run pacman.--
Port forwarding (DNAT)
- /etc/shorewall/rules : here's an example for a webserver on our LAN with IP 10.0.0.85. You can reach it on port 5000 of our "external" IP.
DNAT net loc:10.0.0.85:80 tcp 5000
Intrusion detection & prevention - Snort
According to the site's homepage title, Snort is "the de facto standard for intrusion detection/prevention". Sounds good. Let's use this one!
You guessed it:
pacman -S snort
The main configuration file is /etc/snort/snort.conf
Read it carefully, as usual it's very well documented.
var HOME_NET 10.0.0.0/28 # change to the subnet of your LAN var EXTERNAL_NET !$HOME_NET var DNS_SERVERS $HOME_NET var SMTP_SERVERS $HOME_NET # comment these if you're not running any servers on the LAN var HTTP_SERVERS $HOME_NET var SQL_SERVERS $HOME_NET var TELNET_SERVERS $HOME_NET var HTTP_PORTS 80 var SHELLCODE_PORTS !80 var ORACLE_PORTS 1521 var AIM_SERVERS [188.8.131.52/24,184.108.40.206/24,220.127.116.11/24,18.104.22.168/24, 22.214.171.124/24,126.96.36.199/24,188.8.131.52/24,184.108.40.206/24,220.127.116.11/24] var RULE_PATH /etc/snort/rules var HTTP_PORTS 80:5000 # for HTTPd's running on port 80 and 5000. Change appropriately to the #ports you are using on your LAN config detection: search-method lowmem # if you're using a machine "with very limited resources"
At the bottom of the file, there's a list of includes. These define which rules you want to enforce. (Un)comment as you please.
groupadd snort mkdir -p /var/log/snort useradd -g snort -d /var/log/snort snort chown -R snort:snort /var/log/snort
Under review -- I'm not sure about this yet :/
SNORT_ARGS="-u snort -g snort -l /var/log/snort -K ascii -c /etc/snort/snort.conf -D -h 10.0.0.0/28 -A full
Replace 10.0.0.0/28 with the CIDR of your LAN.
Now Snort will run as user snort in group snort. Should improve security. The other options make it log to /var/log/snort in ASCII mode. Run snort -h to see other available options.
I've been running my router for 12 days now, and using the above snort options, I had around 120MB of logs! So I changed the -A switch to "-A none". This only logs alerts. I didn't know what to do with all the logs anyway.
Update the rules - Oinkmaster
If you want to be able to download Snort's latest rules, you'll need a subscription. This costs money. If you're happy enough with 5 days old rules, you just need to register for free. If you don't, the only updates you'll get are the new rules distributed with a new Snort release. Go ahead and register at Snort. If you really don't want to register, you can use the rules from BleedingSnort.com. They're bleeding edge, meaning they haven't been tested thoroughly.
I've created a PKGBUILD for oinkmaster, grab it, build it and install it with pacman -A ...
Look for the URL section and uncomment the 2.4 line. Make sure to replace <oinkcode> by the Oink code you generated after logging into your Snort account. For Bleeding Snort rules, uncomment the appropriate line.
When you log into your new account, create an "Oink code". Another thing to change is
use_external_bins = 1 # 1 uses wget, tar, gzip instead of Perl modules
The rest of the config file is fine.
oinkmaster.pl -o /etc/snort/rules
Create an executable script with the exact command and place it in /etc/cron.daily to update the rules daily automatically.
Edit DAEMONS list
Here's a list of daemons you need to add to /etc/rc.conf to make sure every service you've installed is started at boottime:
- network : ehm ... duh!
- iptables : only if you're not using shorewall
- shorewall : to configure iptables, traffic shaping, ... Don't add iptables AND shorewall to the list
- adsl : if you're sharing an ADSL connection
This will result in the following line:
DAEMONS=(syslog-ng crond network sshd shorewall snort adsl dnsmasq)
"Lock" config files
It's important to add every config file edited in the process to the NoUpgrade list of pacman.conf. This will prevent pacman from overwriting them when there's a new version of the package available.
nano /etc/pacman.conf # OpenSSH NoUpgrade = etc/hosts.allow etc/ssh/sshd_config # rp-pppoe NoUpgrade = etc/ppp/pap-secrets etc/ppp/pppoe.conf # dnsmasq NoUpgrade = etc/dnsmasq.conf # iptables NoUpgrade = etc/conf.d/iptables # Snort NoUpgrade = etc/snort/snort.conf etc/conf.d/snort # Shorewall NoUpgrade = etc/shorewall/interface etc/shorewall/masq etc/shorewall/policy NoUpgrade = etc/shorewall/outestopped etc/shorewall/rules etc/shorewall/shorewall.conf NoUpgrade = etc/shorewall/zones
Final clean up
Review the list of packages without dependencies and decide which ones can be removed.
Read NAT'ing firewall - Adding advanced features if you feel like it. It's completely optional, though.