NAT'ing firewall

From ArchWiki
Revision as of 12:03, 17 April 2006 by FUBAR (talk | contribs)
Jump to navigation Jump to search


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.


Not only will the gateway route, it will also feature:

  • DHCP server: allowing dynamic IP configuration of connected machines
  • caching DNS server: useful when your ISP's DNS server is temporarily down
  • 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!
  • SSHd: 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
  • 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.

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


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

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

Securing the SSHd

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.

  • 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. You can add more than one IP address and port here, just remember not to put the WAN address in it unless you're absolutely sure you know what you're doing. Changing the port doesn't really offer a great deal of security though, a simple port scan will reveal on which port the SSHd is actually listening so don't rely too much on it.
  • Setting users allowed to log in: this is probably 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 box by brute force, i.e. trying every possible password for user root until one works. 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!!! ^_^
AllowUsers foobar barfoo@ 
DenyUsers root
PermitRootLogin no

I don't know the difference between "DenyUsers root" and "PermitRootLogin no" but better to be safe than sorry.

  • Only allow the ssh2 protocol:
Protocol 2

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.

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.

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

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

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

HTTP proxy

Time for Squid! We're going to run it as a transparent web proxy server. No need to configure any browsers on the LAN: they'll use it automagically.


pacman -S squid


nano /etc/squid/squid.conf

Add these lines to the config file:

http_port # change it to the IP of eth0
icp_port 0 # disables ICP queries to neighbor caches, unless you have other Squids, I guess.

acl ALbox_network src # <-- change CIDR appropriately
acl all src

http_access allow ALbox_network
http_access deny all
httpd_accel_host virtual
httpd_accel_port 80
httpd_accel_with_proxy on 
httpd_accel_uses_host_header on

maximum_object_size 50000 KB # max size of cachable objects
minimum_object_size 0 KB
cache_mem 7867 KB # read docs for more info
cache_dir aufs /var/cache/squid 300 16 256 # assign disk space for Squid's cache, see docs
visible_hostname # hostname that will be shown in status/error messages


Using Shorewall with Squid Transparency happens by redirecting all www requests eth0 picks up, to Squid. Edit /etc/shorewall/rules and add

REDIRECT	loc	3128	tcp	www # redirect to Squid on port 3128
ACCEPT		$FW	net	tcp	www # allow Squid to fetch the www content


/etc/rc.d/shorewall restart
/etc/rc.d/squid start

et voila: a transparent proxy!

Ad blocking

Adzapper is a plugin for Squid. It catches ads of all sorts (even Flash animations) and replaces them with an image of your choice, so the layout of the page isn't altered too much.


Normally, I'd tell you to

pacman -S adzapper

but the current version of the package is horribly out of date. I've contacted dorphell who used to maintain it. Until it's back up to date, grab my less outdated package. Install it with

pacman -A adzapper-20060414-1.pkg.tar.gz


echo "redirect_program /usr/bin/adzapper.wrapper" >> /etc/squid/squid.conf

That's it! If you want, you can configure adzapper to your liking. The configuration out of the box works wonderfully well though.

nano /etc/adzapper/adzapper.conf

Content filtering

Now that everyone on the LAN can access the web, it's time to filter it! >-) Here's a rudimentary guide to DansGuardian, a very powerful content filtering tool. I was going to use DansGuardian to filter ads, but it seems there is no site with a freely downloadable ad host list.


pacman -S dansguardian

This pacman thingy really is handy, isn't it. :P


nano /etc/dansguardian/dansguardian.conf
filterip = # eth0 IP
filterport = 8080
proxyip = # eth0 IP
proxyport = 3128
reserveaddresslookups = on # "... unless you have a local caching DNS, leave it off ..." <- we do!! :)
usernameidmethodproxyauth = off # 
usernameidmethodntml = off # it's going to be a transparent proxy: auth wouldn't make much sense
usernameidmethodident = off #
daemonuser = 'proxy' # same uid Squid uses
daemongroup = 'proxy' # same gid Squid uses

Now we have to make use of DansGuardian: instead of letting Squid catch the HTTP requests, we'll direct them to DansGuardian first. DG will in turn forward the allowed requests to Squid.

nano /etc/shorewall/rules
REDIRECT	loc	8080	tcp	www	# 8080 (DG port) used to be 3128 (Squid port)


/etc/rc.d/shorewall restart
/etc/rc.d/dansguardian start

You should see a "Access denied" page generated by DansGuardian. If not, you'll be exposed to gay porn which is why I suggest you to use elinks. ;) The domain is listed in /etc/dansguardian/bannedsitelist .

Setup filters

Check out the files in /etc/dansguardian/ : they're all used for filtering. Edit /etc/dansguardian/dansguardianf1.conf , it's the config for group "1". This is the default group all users belong to. If you want, you can make several groups with different sets of rules. I'm not going to do it, but if you do, be sure to add your steps to this Wiki. The dansguardianf1.conf file contains all the different rules DG can use to censor the WWW traffic. If you don't comment out a line, be sure to check the filename the line describes: it contains the actual rules.

nano /etc/dansguardian/dansguardianf1.conf

Traffic shaping

Shorewall can shape traffic! This is very useful, especially when you're not the only one on the LAN. Don't you just hate it when your ping sores just because some n00b forgot to disable or limit the upload of their P2P program. The idea is to assign a priority to different types of traffic. Interactive traffic (ssh, online gaming) probably needs the highest priority, while P2P traffic can do with the lowest. And then there's everything in between. ;)


If you already installed Shorewall, there's nothing to be done for now. If not, scroll up and do it!


Read Shorewall's Traffic Shaping/Control guide. It's very good and it saves me a lot of typing. :P

OpenNTPD - a time server

The following text is a shameless copy/paste of Network Time Protol. I've edited a bit to get it up to date.

OpenNTPD is a FREE, easy to use implementation of the Network Time Protocol. It provides the ability to sync the local clock to remote NTP servers and can act as NTP server itself, redistributing the local clock.

OpenNTPD is primarily developed by Henning Brauer as part of the OpenBSD Project.

OpenNTPD is a brand new implementation of the ntp protocol. It is much easier to configure and use than ntpd.


pacman -S openntpd


Once installed, the /etc/ntpd.conf file must be edited. This is much easier than with ntpd.

The default configuration is actually usable if all you want is to sync the local computer.

# $OpenBSD: ntpd.conf,v 1.7 2004/07/20 17:38:35 henning Exp $
# sample ntpd configuration file, see ntpd.conf(5)
# Addresses to listen on (ntpd does not listen by default)
#listen on *
#listen on
#listen on ::1
# sync to a single server
# use a random selection of 8 public stratum 2 servers
# see

To sync to a particular server, uncomment and edit the "server" directive.


The "servers" directive works the same as the "server" directive, however, if the dns name resolves to multiple IP address, ALL of them will be synched to. The default, "" is working and should be acceptible in most cases.

Any number of "server" or "servers" directives may be used.

If you want the computer you run OpenNTPD on to also be a time server, simply uncomment and edit the "listen" directive:

listen on # change to eth0 IP

If you want to see the status of of your syncing, look at /var/log/daemon.log

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
  • shorewall : to configure iptables, traffic shaping, ...
  • dnsmasq
  • adsl : if you're sharing an ADSL connection
  • sshd
  • squid : if you're running a caching web proxy
  • dansguardian : if you're going to filter webcontent (add squid too)
  • openntpd : if you're running an NTP client / server

This will result in the following line:

DAEMONS=(syslog-ng crond network iptables shorewall dnsmasq adsl sshd squid dansguardian openntpd)

"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
# Squid
NoUpgrade etc/squid/squid.conf
# AdZapper
NoUpgrade etc/adzapper/adzapper.conf
# DansGuardian # add every DG config file you've edited to the list below
NoUpgrade etc/dansguardian/dansguardian.conf
# Traffic shaping
NoUpgrade etc/shorewall/tcclasses etc/shorewall/tcdevices etc/shorewall/tcrules
# OpenNTPd
NoUpgrade etc/ntpd.conf

Squid config