Tag Archives: ip masquerading

Using a Raspberry Pi 2 Model B as a router/firewall for the home LAN

Since 1999 I have been using a 1996 vintage DEC PII desktop as the router/firewall between the internet and my home network.  The DEC computer came to me with Win95 (or possibly Win98) in 1998, got SuSE linux and started its mission as router and firewall (and CUPS server, and IMAP server, and various other server stuff). When upgrading the SuSE installation to a newer version went south, it spent a while running ThomasEz’s floppyfw, until I used a floppy net install to install debian potato, immediately switched it to debian testing, until debian woody arrived, when it was moved to debian stable, and then I just kept running “apt-get dist-upgrade” until I finally had it running debian 8 “jessie” on june 6 in 2015.

The old DEC desktop has survived its maker company, survived lightning strikes that have sent the power supplies and/or main boards of other computers on the same LAN into continously beeping mode (i.e. broken). However, in December 2015 it started acting up, and crashing with irregular intervals (sometimes two weeks, sometimes one day).

So… the time for a replacement would have to be not too far ahead. The question was what to replace it with?

The simplest solution would be to just get a wireless router with a cabled switch. But that would mean:

  • No possibilities for SSH or mosh into the home LAN
  • No ntop
  • No support for netboot and TFTP in the home LAN
  • Limited, cumbersome and inflexible firewall setup

My requirements were:

  • Cheap
  • Two wired NICs
  • The ability to run debian
  • Preferrably fanless
  • Compact

ThomasEz immediately suggested using a raspberry pi with two NICs, but I thought that would be too puny, and I investigated alternatives like Shuttle Barebone DS57U but I found that the raspberry pi alternative was so cheap, I might as well order one.

And then it turned out to be so simple to set up so I had it up and running before I really had decided on anything, so now the r-pi is what I have.

This is what I ordered:

Here’s what I did:

  1. Downloaded the Raspbian Jessie Lite image to a debian jessie computer and unpacked it into the /tmp directory
  2. Plugged an USB SD card reader into the debian computer, and followed the instructions in Installing operating system images on Linux 
  3. I plugged the cheapest USB keyboard I could get from my local teknikmagasinet store into one of the USB port, yanked the HDMI cable from the DVD player and plugged the r-pi into the TV, plugged a network cable into the local LAN, and plugged in the power… and the raspberry pi booted quickly into the familiar debian login
  4. I logged in with the built-in “pi” user with password “raspberry”, and created my own user with the following command line command:
    adduser sb

    the changed the password of the root user and removed the pi user

  5. I copied in a public ssh keys from my other computers, and put them into the ~/.ssh/authorized_keys file and then opened /etc/ssh/sshd_conf in a text editor and modified it in the following way:
    1. Disabled root login by changing
      PermitRootLogin without-password

      to

      PermitRootLogin no
    2. Disabled password login by changing
      #PasswordAuthentication yes

      to

      PasswordAuthentication no

      (removed the comment and changed “yes” to “no”)

  6. Edited /etc/hostname to change the name from the default “raspberrypi” to “ocon”
  7. Rebooted the pi to check the startup state of the ssh daemon and ssh’d in
  8. Resized the disk to fill the entire SD card:
    1. Typed the command
      raspi-config
    2. Selected
      1 Expand Filesystem            Ensures that all of the SD card storage is available to the OS

      and got the response

      Root partition has been resized.
      The filesystem will be enlarged upon the next reboot
    3. Rebooted the system to get the full 16GB in the file system
  9. Updated the system by giving the following command line commands:
    apt-get update
    apt-get dist-upgrade

    (the “update” command updates the local package database against the package servers. The “dist-upgrade” command upgrades all packages that have a newer version, and the required dependencies)

  10. Installed some useful software:
    1. GNU emacs (my favorite text editor)
      apt-get install emacs
    2. mosh
      apt-get install mosh
    3. git (I’ve got my home directory versioned in git)
      apt-get install git
    4. rcs (I use it to version control operating system configuration files)
      apt-get install rcs
  11. I cloned my home directory in git and created a new branch (I have a different branch for each computer)
  12. I set the built-in NIC permanently as eth0:
    export INTERFACE=eth0
    export MATCHADDR=`ip addr show $INTERFACE | grep ether | awk '{print $2}'`
    /lib/udev/write_net_rules
  13. I added configuration for a second NIC by adding the following to /etc/network/interfaces:
  14. # The internal network card
    allow-hotplug eth1
    iface eth1 inet static
       address 10.10.10.1
       netmask 255.255.255.0
  15. I plugged in the USB NIC to have it appear, and then made the USB NIC permanently eth1 with the following command line commands:
    export INTERFACE=eth1
    export MATCHADDR=`ip addr show $INTERFACE | grep ether | awk '{print $2}'`
    /lib/udev/write_net_rules
  16. Installed dnsmasq
    apt-get install dnsmasq
  17. Edited /etc/dnsmasq.conf to make dnsmasq respond to DHCP requests on eth1:
    1. Removed the comment in front of
      #interface=

      and set “eth1” as the value:

      interface=eth1
    2. Uncommented the domain directive
      #domain=thekelleys.org.uk

      and changed it to my domain

      domain=hjemme.lan
    3. Uncommented the dhcp-range directive
      #dhcp-range=192.168.0.50,192.168.0.150,12h

      and changed it to a 10.10.10.* range with a 5h lease on the addresses

      # Our HOME LAN 5h lease time
      dhcp-range=10.10.10.6,10.10.10.40,5h
  18. Opened the /etc/hosts file in a text editor and added the raspberry pi itself, to so that DNS lookups of the raspberry pi will work in a LAN where the raspberry pi is handling the DHCP requests (dnsmasq will handle DNS requests for the IP addresses it has given DHCP leases to, as well as what it finds in the hosts file.  The rest is delegated to the upstream DNS server)
    127.0.0.1       localhost
    ::1             localhost ip6-localhost ip6-loopback
    ff02::1         ip6-allnodes
    ff02::2         ip6-allrouters
    
    127.0.1.1       ocon
    
    # local hosts
    10.10.10.1  hjemme ocon hjemme.hjemme.lan ocon.hjemme.lan
    
  19. Edited the /etc/sysctl.conf file to set up IPv4 routing in the linux kernel, removed the comment in front of the net.ipv4.ip_forward line:
    # Uncomment the next line to enable packet forwarding for IPv4
    net.ipv4.ip_forward=1
    
  20. ferm is a utility that makes it easy to set the routing and firewall rules at boot time
    1. Installed ferm using apt-get from a command line:
      apt-get install ferm
    2. Modified the /etc/ferm/ferm.conf file to allow everything inside t oroute out, but only allow ssh in
      @def $DEV_WORLD = eth0;
      @def $DEV_PRIVATE = eth1;
      
      def $NET_PRIVATE = 10.10.10.0/24;
      
      table filter {
          chain INPUT {
              policy DROP;
      
              # connection tracking
              mod state state INVALID DROP;
              mod state state (ESTABLISHED RELATED) ACCEPT;
      
              # allow local packet
              interface lo ACCEPT;
      
              # allow private net
              interface $DEV_PRIVATE ACCEPT;
      
              # respond to ping
              proto icmp ACCEPT;
      
              # allow IPsec
              proto udp dport 500 ACCEPT;
              proto (esp ah) ACCEPT;
      
              # allow SSH connections
              proto tcp dport ssh ACCEPT;
          }
          chain OUTPUT {
              policy ACCEPT;
      
              # connection tracking
              #mod state state INVALID DROP;
              mod state state (ESTABLISHED RELATED) ACCEPT;
          }
      
          chain FORWARD {
              policy DROP;
      
              # connection tracking
              mod state state INVALID DROP;
              mod state state (ESTABLISHED RELATED) ACCEPT;
      
              # connections from the internal net to the internet or
              # to other internal nets are allowed
              interface $DEV_PRIVATE ACCEPT;
      
              # the rest is dropped by the above policy
          }
      }
      
      table nat {
          chain POSTROUTING {
              # masquerade private IP addresses
              saddr $NET_PRIVATE outerface $DEV_WORLD MASQUERADE;
          }
      }
      
  21. The version of ferm in “jessie” doesn’t start at boot, because “jessie” dropped SYSV init in favour of systemd, and the version of ferm in “jessie” doesn’t have a systemd configuration, so I needed to manually download and install the version of ferm from debian testing (I downloaded from regular debian, since ferm doesn’t have anything platform specific):
    cd /tmp
    wget http://ftp.no.debian.org/debian/pool/main/f/ferm/ferm_2.2-5_all.deb
    dpkg --install /tmp/ferm_2.2-5_all.deb
    
  22. fail2ban monitors log files of daemons and adjust the firewall rules to temporary ban hosts it suspects of intrusion attempts. The debian (and raspbian) version of fail2ban will out of the box scan the logs for ssh intrusion attempts, so no configuration is necessary
  23. To have an easy way of monitoring the network traffic in and out of the home LAN, I installed ntop ng
    apt-get install ntopng

    after the installation it is possible to monitor the network traffic by accessing http://ocon.hjemme.lan:3000 (the interesting traffic will be seen after selecting eth1)

  24. The Network Time Protocol is how computers stay in sync, installing the ntp package will make the gateway keep network time, a
    apt-get install ntp
  25. Opened the /etc/ntp.conf file in a text editor, and modified it to provide an NTP deamon for the home LAN, uncommented the “broadcast” line and modified the network match to match the 10.10.10.* network:
    # If you want to provide time to your local subnet, change the next line.
    # (Again, the address is an example only.)
    broadcast 10.10.10.255
    
  26. Installed the apticron utility to make sure that the APT database is updated daily with new candidates for update
    apt-get install apticron

The original plan was to run the raspberry pi headless, but since I had an old VGA only LCD display for the old DEC computer I might as well hook it up the raspberry pi, together with the cheap USB keyboard used for setup.

I bought an HDMI to VGA converter with the manufacturer id VLMP34900W0.20. I plugged it in between the display and the raspberry-pi the display stayed black.  I edited the /boot/config.txt file, removing the comment in front of the hdmi_safe line:

# uncomment if you get no picture on HDMI for a default "safe" mode
hdmi_safe=1

I rebooted the raspberry pi, and this time the LCD displayed showed the boot messages as well as a normal console login prompt.

The raspberry pi 2 model B, with an extra USB NIC, a USB keyboard and connected to a VGA display using an HDMI to VGA converter
The raspberry pi 2 model B, with an extra USB NIC, a USB keyboard and connected to a VGA display using an HDMI to VGA converter

And this is where the current state is. One initial concern was flash wear on the SD card, which doesn’t have the wear leveling features of a “real” SSD, so I had some plans on making the /var/log use tmpfs.

But I decided not to, since having real persistent logs is a useful thing for a gateway, and since 16GB is actually an awful lot of data if all you do is to write textual files. And ff the SD card wears out I’ll just by a new SD card, and make a new system. Since I now know how, this shouldn’t take long