====== Diskless Firewall using Debian (3.1) and Shorewall (2.2) ======
===== Background =====
Back in Auguest of 2004 I setup my home network with two segments, WIFI and LAN. I wanted to keep my WIFI network separate from the LAN to limit the chances of anyone accessing my LAN though wireless. I was using WEP but we all know how easy that is to crack. So I dropped 3 network cards in the oldest computer I had and started setting up a firewall which limited the access between my two networks and the Internet. At first I used some custom iptable scripts but that quickly became cumbersum. I then went in search of a firewall package and decided on shorewall. After spending an hour configuring shorewall all was well for a few months till the firewall hard drive crashes. I was left with four options: get a new hard drive, use a floppy/cdrom based firewall, use a hardware based firewall or go diskless. I hate floppies, was feeling cheap and did not have a hardware based router that had the amount of NICs I wanted. Besides, setting up a diskless firewall with Linux just sound like fun and my firewall did sit right next to a system with a few raid arrays in it.
===== Requirements =====
Two computers, one server and one to use as a firewall.
Firewall:
3 NICs with one being pxe bootable
Server:
DHCP server
TFTP server
NFS server
====== Server Configuration ======
We will start with a stock Debian 3.1 (Sarge) installation for the server
==== Server layout ====
/var/lib/tftpboot (location for pxe linux kernel)
/var/diskless/firewall (location for firewall file system)
==== Network layout =====
LAN: 172.21.0.10 server
LAN: 172.21.0.1 firewall
WIFI: 172.21.50.1 firewall
WAN: dhcp firewall
==== tftp server ====
Install trivial ftp server. The standard tftp package in debian was giving me problems with my 3Com card but then the card I was using is known to have problems with some pxe setups. I have since aquired a lot of Intel Pro 100 cards but have not tested the standard tfpt package with them. The syslinux package is also needed in order to get the pxe bootable images that the tftp server will be handing out.
apt-get install tftpd-hpa syslinux
==== Configure tftp ==== Configure the tftp server to use inetd to handle connections and change the location of the tftp root.
/etc/inetd.conf
---
#:BOOT: Tftp service is provided primarily for booting. Most sites
# run this only on machines acting as "boot servers."
tftp dgram udp wait root /usr/sbin/in.tftpd /usr/sbin/in.tftpd -s /var/lib/tftpboot
---
PXE boot files
Copy the pxe images to the tftp root.
mkdir -p /usr/lib/syslinux/pxelinux.cfg
cp /usr/lib/syslinux/pxelinux.0 /var/lib/tftpboot
==== Configure PXE ====
PXE uses the MAC of the card to find a config file. It will first start with the whole MAC address and then start dropping the right might value till it finds a maching config file. This allow you to have a config for each machine or say all 3Com cards. If a MAC address is not matched then it will lood for a default config called "default".
/usr/lib/syslinux/pxelinux.cfg/$mac-address-of-nic
---
default nfs
label nfs
kernel firewall-nfsboot-0.1
append root=/dev/nfs rw nfsroot=172.21.100.225:/var/lib/diskless/firewall ip=dhcp console=ttyS0,19200 console=tty0 devfs=nomount
---
==== DHCP Server ====
apt-get install dhcp
/etc/dhcpd.conf
---
# option definitions common to all supported networks...
option domain-name "pxe";
option domain-name-servers 216.28.8.51;
option subnet-mask 255.255.255.0;
default-lease-time 600;
max-lease-time 7200;
subnet 172.21.100.0 netmask 255.255.255.0 {
}
group {
filename "pxelinux.0";
next-server 172.21.0.225;
host firewall {
hardware ethernet 00:04:76:E8:9F:A0;
fixed-address 172.21.0.1;
}
}
---
This DHCP server is setup to only answer to the firewall because the firewall itself will also run a dhcp server.
nfs
apt-get install nfs-kernel-server
/etc/exports
---
/var/lib/diskless/firewall 172.21.0.1(rw,async,no_root_squash)
---
==== Kernel ====
We are almost ready to create a filesystem for our diskless based firewall but before that lets create a kernel. The default Debian kernel does not support nfsroot. So we will have to compile a new kernel which supports it. I went a step further and actually stripped everything out of the kernel that was not needed and built everything into the kernel, no modules. This was done so I would not have to deal with initrd and my goal was to have a small kernel anyways.
apt-get install kernel-tree-2.6.8 kernel-package libc6-dev
configure the kernel to your liking
make config
make-kpkg --revision=firewall.0.1 kernel_image
cp kernel-image-2.6.8_firewall.0.1_i386.deb /var/lib/diskless/firewall
We will hold off on actually installing the kernel into your firewall and pxe environment till we have a filesystem setup for the firewall.
===== Firewall Setup =====
The first thing we need to do is create a file system which will become our nfs root. There are a few different ways to create this file system. You can mount up a fresh install of Debian and copy the whole file system to /var/diskless/firewall. Or you can your the diskless utilities that are include with Debian. These tools are designed to create images for nfs rooted systems. They are designed to create a read only file system that is shared amoung many systems while creating a read/writable section for /home, /etc ...
Install and setup disk images
apt-get install diskless
diskless-createbasetgz /tmp/diskless sarge http://mirrors.kernel.org/debian/ /var/lib/diskless/base.tgz
The diskless tools can turn the base.tgz into read only filesystem and then create a writable filesystem for each client. This is used more if you wanted to create multiple computers that only change part of their file system and not say /etc/, even if they get compromised. This approch is a bit of over kill since we are creating a specialized nfs rooted system and most likely will not need more than one system running this image. So we will just extract the base.tgz into /var/lib/diskless/firewall and manually customize it. Besides the diskless-newimage command failed when I tried it on Sarge, it did work the first time on set the system up when Sarge was still in testing.
Now that we have a base filesystem lets chroot into it and setup a few things. Here is a list of files that should be updated.
/etc/apt/sources.lis
/etc/hostname
/etc/mailname
/etc/network/interfaces
/etc/resolv.conf
... sure there a few more that I missed
Now is a good time to install the kernel that was built
inside the jail dpkg -i kernel-image-2.6.8_firewall.0.1_i386.deb
outside the jail cp /var/lib/diskless/firewall/vmlinuz /var/lib/tftpboot/firewall-nfsboot-0.1
setup the network interfaces
/etc/network/interfaces
-------------------------------------------------------------------------------
# The loopback network interface
auto lo
iface lo inet loopback
auto eth0 eth1 eth2
# LAN
iface eth0 inet static
address 172.21.0.10
netmask 255.255.255.0
# WIFI
iface eth1 inet static
address 172.21.50.1
netmask 255.255.255.0
# WAN (Internet)
iface eth2 inet dhcp
-------------------------------------------------------------------------------
==== DHCP Server ====
I actually run my main DHCP server from the diskless machine. The main reason for this was because I did not want to look into forwarding dhcp requests from the WIFI network to my LAN.
/etc/default/dhcp
---
# Defaults for dhcp initscript
# sourced by /etc/init.d/dhcp
# installed at /etc/default/dhcp by the maintainer scripts
#
# This is a POSIX shell fragment
#
# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
# Separate multiple interfaces with spaces, e.g. "eth0 eth1".
INTERFACES="eth0 eth1"
---
/etc/dhcpd
---
option domain-name "krynn";
option domain-name-servers 216.28.8.51;
option subnet-mask 255.255.255.0;
default-lease-time 600;
max-lease-time 7200;
subnet 172.21.0.0 netmask 255.255.255.0 {
range 172.21.0.100 172.21.0.150;
#option broadcast-address 204.254.239.31;
option routers 172.21.0.1;
}
subnet 172.21.50.0 netmask 255.255.255.0 {
range 172.21.50.100 172.21.50.150;
#option broadcast-address 204.254.239.31;
option routers 172.21.50.1;
}
---
==== Shorewall configuration ====
apt-get install shorewall
There are some lines of the shorewall code that needs changed or else the nfsroot gets killed when starting and stopping the firewall.
/usr/share/shorewall/firewall
setpolicy INPUT DROP, comment all of these out
setpolicy OUTPUT DROP, comment all of these out
setpolicy FORWARD DROP, comment all of these out
enable the firewall
/etc/default/shorewall
copy default config files to /etc/shorewall
cp /usr/share/doc/shorewall/default-config/* /etc/shorewall
Setup default config.
You will want to enable IP Forwarding and I disabled TCP/IP v6
/etc/shorewall/shorewall.conf
Define a zone for each interface
/etc/shorewall/zone
---
#ZONE DISPLAY COMMENTS
wan Internet The big bad Internet
lan LAN Local Area Network
wifi Wireless Local Wireless network
---
Associate a zone to each interface
/etc/shorewall/interface
---
#ZONE INTERFACE BROADCAST OPTIONS
lan eth0 detect dhcp
wifi eth1 detect dhcp
wan eth2 detect dhcp,routefilter
---
The dhcp option allows dhcp requests to come in and out on these interfaces. If your wan is a static you can disable it. You can also ignore private ip ranges with nofrc1918 on the wan interface.
setup ip masquerading
/etc/shorewall/masq
---
#INTERFACE SUBNET ADDRESS PROTO PORT(S) IPSEC
eth2 eth0
eth2 eth1
---
Setup some rules
/etc/shorewall/rules
---
####################################################################################################
#ACTION SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE USER/
# PORT PORT(S) DEST LIMIT GROUP
# Allow the firewall to access its NFS root
ACCEPT fw lan:172.21.0.10 tcp 111
ACCEPT fw lan:172.21.0.10 udp
# Allow ssh to come in from the LAN
ACCEPT lan fw tcp 22
ACCEPT wifi fw tcp 22
ACCEPT wan fw tcp 22
# Allow wifi to access web server on lan
ACCEPT wifi lan:172.21.0.10 tcp 80
ACCEPT wifi lan:172.21.0.10 tcp 443
ACCEPT wifi lan:172.21.0.10 udp 80
ACCEPT wifi lan:172.21.0.10 udp 443
# Allow Internet (wan) to access web server on lan
DNAT wan lan:172.21.0.10 tcp 80
DNAT wan lan:172.21.0.10 tcp 443
DNAT wan lan:172.21.0.10 udp 80
DNAT wan lan:172.21.0.10 udp 443
# Make ping work bi-directionally between the wifi, net, Firewall and local zone
# (assumes that the loc-> net policy is ACCEPT).
ACCEPT wan fw icmp 8
ACCEPT lan fw icmp 8
ACCEPT wifi fw icmp 8
ACCEPT lan wifi icmp 8
ACCEPT wifi lan icmp 8
ACCEPT wifi wan icmp 8
ACCEPT fw wan icmp
ACCEPT fw lan icmp
ACCEPT fw wifi icmp
ACCEPT wan wifi icmp 8 # Only with Proxy ARP and
ACCEPT wan lan icmp 8 # static NAT
---
/etc/shorewall/policy
---
###############################################################################
#SOURCE DEST POLICY LOG LEVEL LIMIT:BURST
#SOURCE DEST POLICY LOG LIMIT:BURST
# LEVEL
lan wan ACCEPT
lan wifi ACCEPT
wifi wan ACCEPT
wan fw DROP info
all all REJECT info
---
if a rule does not match we fall back to the policy file to decide what to do.
===== Conclusion =====
It took me about a week to get everything up and going the first time. It was not the easiest firewall to get setup, but in the end I learned a lot about pxe and network booting. The most difficult part was tracking down why the NFS root was getting killed when the firewall started. Google did not turn up much but I finally stumbled across a posting from 2003 on the shorewall list that mention the DROP. After that, things start to go much more smoothly. You could even disable all login accounts on the firewall so you had to use the chroot jail to do all administration, or use conserver and allow serial or console access only.
===== Things to watch for =====
Network card order, a new kernel could change the order of your eth devices.
Updating shorewall with apt will blow away your NFS fixes.
Having your NFS server require a reboot brings the whole system down.