Table of Contents
Yeah I figure why not, at the same time that I’m replacing another key piece of network infrastructure, I might as well just replace the (second) most important piece, right? So cue the music, because…
Now, this is a story, all about how my
life network got flipped, turned upside down, and I’d like to take a minute, just sit right there, I’ll tell you how I became the prince of a town called Bel Air the owner of a… just… just cut the music. Let’s begin.
So, the basics… I upgraded the box that sits between my network and the rest of the internet. (Technically, my network and the rest of the house, but…) In terms of core features, it’s the network router and gateway, and in terms of other features… it’s a firewall. The software package I was using was the UTM 9 (Unified Threat Management) by Sophos, and, if you’re familiar with that name, then you already know it does a lot.
Sophos UTM 9
Note: the successor to this is called Sophos XG, which… I’ve never touched, I just didn’t upgrade.
UTM 9, besides being a pretty standard firewall / NAT device, also did a lot more like application traffic shaping, what’s effectively Snort traffic monitoring, HTTP download virus scanning, URL blocking, email download scanning, email DKIM signing, email spam detection.. a lot of things. UTM could even do things like webserver protection, act as an AP controller, so much fun stuff.
It ran mainly off a system called
confd, a central (to the device, in this case) configuration management engine, wrapped up in a nice (and slow) graphical web interface.
To the best of my knowledge, the real backend of the firewall / NAT section is
iptables, which, let’s just say I’m glad it’s much simpler to use graphically.
A home use (non-commercial) version is available for free, licensed for 50 LAN-side IP addresses. This also comes with software and virus database updates.
And one final thing to note that will be important later: the UTM installer checks how many NICs (translated: Ethernet ports) your device has, and it will refuse to run unless there’s at least two, one for the WAN (internet / ISP / “everyone else”) side, and one for the LAN (own network) side.
pfSense is a network firewall application built on FreeBSD.
It doesn’t have all the features of a full UTM, but in some ways it’s a little better.
Besides being FOSS, it’s also based not on
iptables for filtering and routing, but
pf (packet filter) instead, hence the name, pfSense.
Instead of relying on one central configuration manager to keep all the services in check, pfSense makes edits directly, many of them requiring an explicit “save” or “apply” to take effect.
pfSense has a built in package manager to allow installing additional features that have been created by the community, like a
.ovpn file exporter or a Zabbix monitoring agent, but by default you’ve still got quite a few things to play with: IPsec and OpenVPN VPNs, CARP for pfSense high availability, various methods of traffic shaping… and as a router, it’s got decent DHCP and DNS capabilities, with.. some quirks.
I’m obviously not going to give you a full, detailed walkthrough, but as a general comparison, the UI looks much cleaner, less cluttered, and feels more responsive, in my opinion, and it’s a very capable system indeed.
iptables is a core part of linux at this point, with a list of “chains” of rules that are evaluated top to bottom, and the first one to match within a chain will send the rule to any other specified chain, or specify a final action instead like
pf uses a rules file, like this:
pass in quick on $IPsec inet from any to any tracker 1597637882 keep state label "VPN" pass in quick on $OpenVPN inet from any to any tracker 1597540135 keep state label "VPN" block in quick on $WAN reply-to ( re0 192.168.1.1 ) inet proto tcp from any to any port 23 tracker 1597471764 flags S/SA label "No telnet" pass in quick on $WAN reply-to ( re0 192.168.1.1 ) inet proto tcp from any to 192.168.5.73 port $Syncthing tracker 1597548003 flags S/SA keep state label "NAT Syncthing" pass in quick on $WAN reply-to ( re0 192.168.1.1 ) inet proto tcp from any to $BorderProxy port $Jellyfin tracker 1597548009 flags S/SA keep state label "NAT Media server access" pass in quick on $WAN reply-to ( re0 192.168.1.1 ) inet proto tcp from any to $BorderProxy port $Matrix tracker 1597548015 flags S/SA keep state label "NAT Allow Synapse to fedrerate with Matrix" pass in quick on $WAN reply-to ( re0 192.168.1.1 ) inet proto tcp from any to $BorderProxy port $NewsTransfer tracker 1597548030 flags S/SA keep state label "NAT Allow NNTP access to blog articles" pass in quick on $WAN reply-to ( re0 192.168.1.1 ) inet proto tcp from any to $BorderProxy port $Web tracker 1597548036 flags S/SA keep state label "NAT Web access to services" pass in quick on $WAN reply-to ( re0 192.168.1.1 ) inet proto tcp from any to 192.168.5.20 port 22 tracker 1597548044 flags S/SA keep state label "NAT Allow SSH for Git repos" pass in quick on $WAN reply-to ( re0 192.168.1.1 ) inet proto tcp from any to 192.168.5.21 port $SSHAlt tracker 1597548050 flags S/SA keep state label "NAT Allow SSH for other VCS repos"
If you read it left to right it actually just spells out what to do:
pass: Pass (allow)
in: Incoming traffic
on $WAN: On the WAN interface
reply-to ( re0 192.168.1.1 ): (send all replies to
192.168.1.1NOT the original source)
inet: That’s IPv4 traffic, not IPv6
proto tcp: Using TCP
from any: Coming from anywhere
to $BorderProxy: Going to
port $Jellyfin: Destined for port
flags S/SA: Inspect the
ACKflags, and only match traffic with the
SYNflag set and the
keep state: When matched, add a state entry to allow further communications through
While cool, it’s also a headache to understand.
Like for example, notice how all the rules say
pf evaluates top to bottom, but the last rule that was matched will decide the outcome, not the first.
quick keyword causes rule evaluation to end right there, meaning that by putting
quick on every rule, it’s effectively a first match wins again.
The user interface here automatically sets
quick since it presents the rules table in a top-to-bottom, first match wins order.
This firewall just by itself is very powerful, with the ability to match many protocols (not just TCP / UDP), inspect arbitrary flag combinations, state tracking, and a rule can even, as a bonus action, set what processing queue to filter matched traffic into (for traffic shaping).
Both UTM and pfSense offer DHCP to their LAN side, presented in a nice DHCP lease table. In Sophos UTM, from here you can press “Make static” and it’ll bring up the network host creation dialog with the host MAC, current IP, and hostname all pre-filled. You can assign any valid IP address to this, then save it. Next time it tries to renew it’s lease, it’ll be sent the static reservation data.
pfSense can do the same thing, except it only fills in the MAC address, you have to specify the IP, hostname (useful for (r)DNS), additional DNS servers (overrides global setting), and other pieces.
You also *cannot assign a static reservation within the DHCP range.
It just straight-up won’t let you.
For example, if my DHCP range is set for
192.168.5.200, then adding a static for
192.168.5.53 will just give me an error.
For the technical reasons, the DHCP service doesn’t take static reservations out of the DHCP pool, meaning that if it allows this to happen, it can actually double-book an address, giving the same IP to two different hosts, which is uh… kinda a big deal.
With pfSense, you’ll want to set the DHCP range to be a sort of “guest” address range, and make reservations for permanent clients that reside outside of that range.
For me, that means
199 is the DHCP range, if a host is not in that range, I’ve made it static.
Two Interfaces, One NIC
And now for something that pfSense can do that UTM can’t: Run with one physical NIC. This is because the installer lets you configure the default LAN and WAN interfaces not just as a particular network card, but also a VLAN tag, if it needs one. I’ve already see this in practice, for example, default, untagged packets are the LAN side, and VLAN 10 tagged packets are the WAN side. It’ll take this and… just work, assuming the switch(es) that are handling the VLANs are handling it correctly. Meaning if you want to be budget, just about any device can become a network router and firewall if you have a VLAN-capable switch.