linux vs freebsd firewalls

FreeBSD – Linux and FreeBSD Firewalls – Part 2

Linux vs. FreeBSD

Linux and FreeBSD Firewalls – The Ultimate Guide

Part 2

When it comes to choosing a firewall technology for your operating system, the options can be overwhelming. This is particularly true for Linux and FreeBSD, which offer multiple choices. In this article, we’ll take a closer look at four of the most popular firewall options for both systems: iptables, nftables, ipfw, and pf, to help you make an informed decision.

So here’s our contribution to the effort, this article is essentially your four-way comparison of iptables, nftables, IPFW and PF 

In the first article of this series, we covered the major differences between two types of firewalls platforms – either Linux or FreeBSD based and what the options are. We covered how pf, IPFW, iptables and nftables act when actions are applied to different packages and just in general the differences between deploying a FreeBSD-based firewall and a Linux-based firewall. In the second part, we go a bit deeper and discuss how egress filtering is done, and how tables and sets are built.

Egress Filtering

For our second example, we’ll consider the case of filtering outgoing packets. 

When a firewall rule determines that a particular packet should be blocked, it can either silently drop the packet or it can send an ICMP error response to the sender. If the purpose of your firewall is to protect against malevolent actors it can be better to simply drop the packet. This avoids revealing information about the structure of your network and reduces the effectiveness of denial-of-service type attacks. However, if you are filtering outgoing packets from your network, the ICMP errors can allow your software to quickly return an error message instead of waiting until a timeout has elapsed.

Let’s suppose we have some software that bypasses the system DNS settings and goes directly to a public name server, and we want to prevent it from doing this.


For iptables, we now use the OUTPUT chain. The protocol and port are also included, though you might choose to leave them out and simply block all packets to the destination addresses. The -d option allows for matching on the destination address. The REJECT jump target is an extension rather than a chain and enables the –reject-with option to select the specific type of response to send.

  iptables -A OUTPUT -p udp -d, --dport 53 -j REJECT \ --reject-with icmp-port-unreachable

As before, the nftables example needs an appropriately named chain and table combination. Assuming those exist, the rule would be as follows:

  nft add rule inet filter output ip daddr '{, }' udp \ dport 53 reject with icmp port-unreachable

IPFW has “unreach” as an action, so it comes first with the following word “port” indicating the type of ICMP error it should throw.

  ipfw add unreach port udp from any to, 53 out

For PF, we could set the block-policy option to use ICMP returns for all block rules—but here, we use a per-rule option. For the rule itself, differences are only cosmetic and there is nothing remarkable in the PF example.

  block return-icmp out proto udp to {, } port 53

With PF, rules are defined in a configuration file named /etc/pf.conf. For iptables and IPFW, it is common to use a shell script. An advantage of using a shell script is that you can make use of shell features like variables and the sourcecommand for including other files. All four firewalls (and/or the shells they’re managed from) use a dollar symbol for variable references.

PF supports an include keyword in pf.conf to include additional configuration files. Furthermore, as a substitute for shell variables, it supports macros. It is common to use a macro when naming network interfaces so, for example, you might define:


Rules often allow for a list of values so you might define a macro for the TCP port numbers a mail server needs open, for example:

You might also be interested in

Maximizing your FreeBSD performance starts with understanding its current state.

A FreeBSD performance audit can help you identify areas for improvement and optimize your systems.

  mail_ports={ 25 110 143 465 587 }

While nftables allows individual rules to be added from the command line with the nft command, it also supports a config file. The config file supports rules in the same form they are specified with nft along with include files and variables, for example:

  define IFACE = eno1

While the pfctl command doesn’t support filtering rules specified directly as arguments, it can be used to change the ruleset. To facilitate this the configuration file needs to reference an anchor. pfctl can then be used to load rules into the anchor. Aside from being useful for dynamic rule changes, this can be convenient when testing out rules.

In general, PF anchors allow a number of rules to be associated together so that they can be manipulated together much as can be done with chains on Linux. The nearest IPFW equivalent is sets which are numbered rather than named.

The consistent structure in the initial part of IPFW rules helps with clarity when viewing a large number of rules, since leading common elements align vertically. More unusual rule options come last, can be ordered flexibly, and are always preceded by an identifying word such as “dst-port” rather than being implicit.

  ipfw add 420 allow tcp from any to me 25,110,143 in

PF uses the word “pass” to denote packets that are accepted. Otherwise, the rule resembles that for IPFW closely enough that the explanation of individual elements need not be repeated. Because PF uses a configuration file, there is no shell quoting for the braces as in earlier examples.

  pass in proto tcp from any to any port {25, 110, 143}

Tables and Sets

When matching many IP addresses in a firewall rule it would be clumsy to need to list many different addresses. Linux has a feature named IP sets for maintaining lists of network addresses and port numbers. This allows firewall rules to target just the name of the set. In addition to being more flexible in allowing for dynamic changes, sets also facilitate much more efficient implementations of address matching for lists containing many addresses. IP sets are common to both iptables and nftables. The sets can be manipulated using the ipset(8) utility.

Both IPFW and PF have their own separate concept of tables for maintaining large lists of network addresses or values of other types to be referenced from firewall rules. These serve the same purpose as IP sets and have the same benefits.

Tools such as sshguard and fail2ban, which detect brute-force attacks by watching log files, use these address tables to block offending hosts. FreeBSD includes blacklistd in base, which does likewise

—albeit using an interface for other services to report failed connections directly, instead of scanning log files.

Listing Rules and Viewing Counters

When testing rules it can be very useful to see what rules are active, and which are triggering on incoming packets. For the latter purpose, counters are maintained. The following table shows the basic commands related to this.

List the rules iptables -Snft list rulesetipfw listpfctl -s rules
Show countersiptables -vnLnft list countersipfw showpfctl -vs rules
Zero countersiptables -Znft reset countersipfw zeropfctl -z

nftables won’t keep counts of packets unless you specifically add a counter. With IPFW it is often useful to test rules with an action of “count” just to see the counts.

Aside from counters there is also the possibility to add logging.


By covering four separate firewalls we’ve only been able to scratch the surface of their capabilities. They are all highly versatile and can be adapted to a variety of needs.

Of the four, iptables has the least clear syntax but is easy to learn and use. nftables clearly improves on it but can appear overwhelming initially. It incurs some complexity from the legacy of its predecessors – both iptables and the even earlier ipchains – as many concepts were carried forward. With a grasp of nftable’s basic concepts, it is not hard to use and the benefits of its design show. IPFW’s documentation is easy to follow and it manages to be simple without compromising on capability, but there are areas where it shows its age. PF probably has the clearest rule syntax and feels like a clean modern design.

See Also

Nftables Wiki In particular, the page on nftables hooks has a diagram which is very helpful for understanding both the hooks and, by extension, iptables chains.

FreeBSD Handbook, Chapter 32. Firewalls

ipset(8) –

pf.conf(5) –

pfctl(8) –

ipfw(8) –

Other FreeBSD vs. Linux Resources

We’ve written quite a bit in the past about making the right choice between the two operating systems. So here are some useful reads when trying to make a choice between FreeBSD and Linux:

1.) FreeBSD vs Linux – Which Operating System to use for OpenZFS

In December 2020, the OpenZFS project completed unifying the OpenZFS codebase between the FreeBSD and Linux platforms. This helps ensure cross-compatibility between the two—but there are still some implementation and even a few feature differences worth paying attention to. This write-up goes over the remaining OpenZFS differences, to help anyone on the fence decide which OS to use beneath our favorite filesystem.

2.) FreeBSD vs. Linux – Networking At A Glance

Network is incredibly important in every infrastructure, and network configuration differences can be pretty challenging between different OSes. This article covers several network technologies where Linux and FreeBSD have equivalent but different implementations and how to work with them. 

3.) FreeBSD vs. Linux – Virtualization Showdown with bhyve and KVM

Although the bhyve management ecosystem is currently quite limited in comparison to Linux’s KVM, its performance is already quite impressive.  For storage-heavy workloads, the benefit of bhyve’s emulated NVMe controller is difficult to overstate—it produced massive throughput improvements that even a long-time KVM fan simply cannot ignore. 

4.) FreeBSD vs. Linux – Package Management

Package managers on various Unix distributions make it easy for system administrators to manage the software installed on the operating system. Packages are an easy, straightforward way to install software that avoids time-consuming configure, compile, install sequences. The popularity of package managers permeates all Unix distributions. Yet there are subtle differences in the approach that Linux vs. FreeBSD take in handling packages. How does Linux compare to FreeBSD’s way of managing packages?

Are you looking to migrate from a Linux-based environment to FreeBSD? How would you go about it?

5.) Easily Migrating from Linux to FreeBSD

If you are already experienced with Linux, FreeBSD should feel very familiar. The operating systems have a lot in common, due both to their Unix heritage and many shared modern components. Much of what may be unfamiliar to a Linux user adopting FreeBSD is also inconsistent between Linux distributions themselves. This article covers some of the conceptual differences between Linux and FreeBSD, and go on to contrast some aspects of the basic system utilities and the differing views of hardware given by the two systems.

6.) Linux and FreeBSD Firewalls – The Ultimate Guide

If you’re looking to understand security at its most basic level in FreeBSD vs. Linux there’s no better way to start than with how firewalls are being implemented in the two different environments. Take a deeper dive in this two-part article series and understand how different firewalls are implemented in FreeBSD and Linux and what the advantages to them are.

You might also be interested in

Get more out of your FreeBSD development

Kernel development is crucial to many companies. If you have a FreeBSD implementation or you’re looking at scoping out work for the future, our team can help you further enable your efforts.

Tell us what you think!