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