Difference between revisions of "NAT'ing firewall"

From ArchWiki
Jump to navigation Jump to search
Line 1: Line 1:
= Introduction =
= Introduction =

Revision as of 19:57, 19 April 2006


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 'desktop' PCs, as the PC where this document applies will be turned into a 'server', not having the desktop applications necesary for normal use.

Basic features

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.

Advanced features

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.

My hardware

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.


Base ArchLinux

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:

pacman -Syu

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 # 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 by the IP your gateway will be using, 2367 by the portnumber of your choice. 
AllowUsers foobar barfoo@ # 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.

Custom kernel

The sources

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.

Kernel configuration

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

NIC config

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:

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.

IP configuration

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 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:
  • the gateway:
  • and the broadcast address:

leaves 13 IP's for computers on the LAN. This translates into

eth0="eth0 netmask broadcast"

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.

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=,,,1h # defines a DHCP-range for the LAN: from to .14 with
# a subnet mask of 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

/etc/rc.d/dnsmasq start

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.



Instead, I opted for an equally powerful frontend, Shorewall. It's in AUR, so grab it from there or use aurbuild to build it. When the package is built, install it with

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.

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 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.

Finally, run

/etc/rc.d/shorewall start

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 You can reach it on port 5000 of our "external" IP.
DNAT        net        loc:        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

nano /etc/snort/snort.conf

Read it carefully, as usual it's very well documented.

var HOME_NET # change to the subnet of your LAN
var SMTP_SERVERS    $HOME_NET # comment these if you're not running any servers on the LAN
var HTTP_PORTS      80
var ORACLE_PORTS    1521
var AIM_SERVERS     [,,,,,,,,]
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.

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 ...


nano /etc/oinkmaster.conf

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.

Finishing touches

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
  • dnsmasq
  • adsl : if you're sharing an ADSL connection
  • sshd

This will result in the following line:

DAEMONS=(syslog-ng crond network sshd shorewall 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
# 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.

pacman -Qe

Advanced features

Read NAT'ing firewall - Adding advanced features if you feel like it. It's completely optional, though.