Category Archives: Networking

Making a Transparent Firewall

In the latest iteration of my home networking stack I am factoring out my firewall from my router into discrete unit. I decided to try a transparent firewall as this has the advantage of a reduced attack surface. Plus i used it as a chance to try out nftables.

Hardware: I chose the raspberry pi compute module 4 with the DFRobot dual-nic carrier. This board is able to push about 1Gbit of traffic while consuming less than 2 watts of power! All this in about 2 inches square. To enable the 2nd NIC on this board I had to recompile the kernel – see my Recompiling the Kernel on the Pi Compute Module 4 post on this.

Once this is done, we enable the serial port so we can manage the firewall out of band. I specifically do not want a listening port on the firewall (remember, its transparent!). To do this I hooked up a FT232 USB->Serial converter to pins to the DFRobot headers. I then connect to the firewall using minicom, using 115200 8N1 for the serial params. Inside the pi ensure you run “raspi-config” and enable the serial port under the interfaces section.

I also turned off dhcpd to ensure the pi is only passing through – not actually on the network. “systemctl disable dhcpcd; systemctl stop dhcpd”

To get nftables, on the pi, I did have to install it: “apt-get install nftables.” Then we write some basic rules. Subjectively speaking, nftables is a lot nicer to write rules for than iptables, ebatables, etc. Here’s a brief sample:

table inet firewallip {
  chain c1 {
       type filter hook input priority 0;
       meta nftrace set 1
        policy drop
        ip saddr 10.55.0.10 icmp type echo-request  accept
        reject with icmp type host-unreachable
 }
}

A brief description of this example is apropos:

  • The table is named “firewallip” (doesn’t matter) but “inet” can be one of  iparpip6bridgeinetnetdev (see https://wiki.nftables.org/wiki-nftables/index.php/Quick_reference-nftables_in_10_minutes)
  • The chain, c1 (again, name doesn’t matter – although it makes sense to have it match the filter type) is instantiated with the type line – this is extremely significant, as rules will only match packets if on the proper filter type.
  • meta nftrace set 1 (can be 0 or 1) lets us run “nft monitor trace” and trace the rules live
  • there are a LOT of things that can go inside a chain – however it is worth noting “reject” phrases such as the one i show are not applicable in some chain types, such as bridge.

Note that for connection tracking inside a bridge i actually had to build my kernel yet again. If you don’t do this youll get “Protocol unsupported” errors if you try to do connection tracking inside a bridge. To enable this module, follow the same steps as in the procedure for adding realtek driver, however the menu item to enable in the kernel is under: “Networking support” -> “Networking options” -> “Network packet filtering framework” -> “IPV4/IPV6 bridge connection tracking support”. Or just add “CONFIG_NF_CONNTRACK_BRIDGE=m” to your “.config” file inside the linux tree. Once this is done you need to ensure “nf_conntrack_bridge” is loaded: “modprobe nf_conntrack_bridge” should do you.

At this point we can do things like connection tracking INSIDE the bridge. Which is great. I won’t post my actual tableset, but here’s a beginning one that works well, allowing for ssh/http/https from the LAN (assuming LAN is on eth1), and only established connections and arp otherwise.

table bridge firewall {
  chain input {
       type filter hook input priority 0; policy drop;
  }
  chain output {
       type filter hook output priority 0; policy drop;
  }
  chain forward {
       type filter hook forward priority 0;       policy drop;
       meta protocol {arp} accept
       ct state established,related accept
       iifname eth1 tcp dport {ssh,http,https} accept
  }
}

Unfortunately, all this fun on the pi doesn’t seem as readily available on centos. Cent 7.6 is still on a 3.x version of the kernel, and 8.4 is still on a 4.x version. You can upgrade to kernel using elrepo-kernel (http://elrepo.org/tiki/kernel-ml).