August 27, 2015 draft firewalld

'(Firewalld Best Practices)

Audience: sysadmins

Firewalld is the replacement for iptables in RedHat-family distros. Like it or not, you’ll probably end up having to wrestle with it at some point. I’ve read several articles describing it with an overview, but most miss out on important subtleties of a tool that’s in production but maybe not friendly enough for prime time. Here you’ll find my guide to getting the most out of Firewalld and avoiding its gotchas.

The commands get long, long, and very long to type frequently. What’s worse is that it seems you usually need to repeat them with a --permanent option, which is painful and easy to forget.

Command line completion

There appears to be a bash completer. I haven’t tried it since I’m fully in Zsh land these days for all activities. It’s not any RH repo I’m aware of anyway, so let’s forget it.

Firewalld supports a poor man’s version of completion. Instead of typing --zone, you can just type --zo or even --z. You’d have to memorize how much of each option is unambiguous. So you still have to type --list-all-z to get --list-all-zones.

So aliases are the way to go.

I did write a Zsh completer here, if you want to use it.

Ansible support

TLDR: don’t bother with Ansible for Firewalld. Even if you do, you’ll likely need to experiment with firewall-cmd to get your rules right.

Ansible’s new version 2 purports to support most of the full set of options, including --source, which I use frequently. Unfortunately, I’ve found this bleeding edge Ansible to be way too buggy to use. However, you can actually copy the newest firewalld add-on python module into Ansible v1.9. However, I don’t think it actually words, whatever version of the module your get.

Really understanding “zones”

You can actually create your own new zone:

Creating a services file

It should look like this:

<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>Some Service</short>
  <description>Something very descriptive</description>
  <port port="1234" protocol="tcp"/>
  <source ip="10.1.10.10" />
</service>

Put it into /usr/lib/firewalld/services and run fwr.

Needed aliases

alias fw='firewall-cmd'
alias fwz='fw --zone'
alias fwp='fw --permanent'
alias fwr='fw --runtime-to-permanent'
alias fwpz='fw --permanent --zone'
alias fwl='fw --list-all-zones'

Gotchas

Sometimes you want to specify a source and port. But it’s not at all obvious when it’s an AND or OR specification. No one seems to mention this. But I did find this gem in the firewalld.zone man page:

The default target is {chain}_ZONE_{zone} and will be used if the target is not specified. If other than the default target is used, all settings except interface and source are ignored, because the first rule created in firewall for this zone is 'jump to target'.

To discover all the man pages, in Zsh do man firewalld«tab»

firewalld                     firewalld.lockdown-whitelist
firewalld.conf                firewalld.richlanguage
firewalld.dbus                firewalld.service
firewalld.direct              firewalld.zone
firewalld.icmptype            firewalld.zones