Linux Firewalling in 2021 and a Gentle Introduction to NFTables Part I

Posted on Wed 27 October 2021 in Computing

Introduction

My first time using a firewall was ipchains back in Linux 2.2. I used it to firewall and share, over a BNC terminated LAN, my wvdiall-ed 56.6kbit/s US Robotics modem's connection to NTL - routinely racking up ~£90/month telephone bills.

Since then, I've learnt and used iptables, PF, Juniper ScreenOS and recently nftables which frankly had not been on my radar at all. This article describes the current state of firewalling for Linux in 2021, my opinions of it and lastly in part II, a brief tour of NFTables, walking through a complete ruleset I wrote recently for a public DNS-Over-TLS (DoT) project I've been working on.

The Current State of Linux Firewalling in 2021

Also note, firewalld is not solely a frontend for iptables, it generates rules for netfilter and can be configured to generate nftables or iptables rules. There's a vast amount of prose online that would lead you to believe it's purely a tool generating iptables rulesets or even it's own firewall completely.

Firewalld

I've been a big fan of firewalld for a number of years but that has changed in recent weeks. Let it be stated that for simple firewall creation and particularly for DevOps when using it with Puppet or Ansible, firewalld is excellent and covers the simple use cases really well if you intend to never look at the rulesets it generates.

Here's two examples where I think firewalld falls short:

Huge Ruleset Generation

In Suse Leap 15.3 at least, the default firewall ruleset sets the public zone (completely vanilla) and allows DHCPv6 and TFTP traffic inbound. Very simple. However, the resulting nftables ruleset that's generated (after removing blank lines) is 667 lines long. That completely unacceptable. e.g.

sudo nft list ruleset | sed '/^$/d' | wc -l
667

Furthermore, the amount chains that are used by default is insane. e.g.

sudo nft list chains | grep 'chain' | wc -l
153

Complex Rules - abstraction more complicated than the underlying implementation

For the aforementioned DNS project I've been working on, one of the requirements was to have traffic rate-limiting by the firewall on the host itself. Generating these slightly more sophisticated rules with firewalld actually turned out to either be impossible or very complicated.

For example, to implement a rule which rate-limits traffic per source IP address with a burst-limit (pretty vanilla requirement) only seemed possible using a "firewalld.direct" configuration file or possibly a "rich language" rule

If it is possible to implement my rule requirement using one or other of these mechanisms, I'm happy to stand corrected, but given that I'll end up with a ruleset at least 667 lines long and would have essentially written implementation level syntax, I've definitely lost interest in using firewalld for this usecase.

So, as an engineer I am now forced to make a decision:

  • Always use firewalld, but never be able to comfortably debug the generated ruleset. (For simple firewall requirements this may be acceptable)

  • Never use firewalld because I want a simple ruleset that is manageable and easy to read but lose the use of managing rules easily with Ansible.

Conclusion

For very simple firewalls, I'd maybe stick with firewalld and you won't need to care about iptables or nftables.

If you want to do anything beyond simple port blocking and some basic logging and rate limiting, go and learn nftables. My personal opinion is that nftables is incredible and I may even prefer it to PF - and that's really saying something.

Lastly, if you do go and learn nftables my thoughts are these:

  • Documentation is not prolific and most of what you will read will be in the context of translating iptables to nftables along with the usual mixed bag of quality on Stack Overflow

  • The syntax at first does not look intuitive - set that aside and be prepared to do some reading

  • READ THE NFT MAN PAGE - It's excellent and the best resource out there

  • Read everything on the wiki

  • Keep the quick reference handy at all times

  • Search the mailing list when you need help

  • The iptables-translate tool maybe useful