I discovered a way to configure the
iptables firewall on CentOS with Ansible. I’ve been struggling with this for a while and was pleased when I discovered a cool utility called ferm.
ferm is a set of scripts that you can use to manage
iptables from a simple text configuration file. I’ve adopted it and am very pleased with how well it works. It even has good primary documentation. In the rest of this post I will explain why you need
ferm and how to automate it with Ansible.
Most of the applications we automate using Ansible can be configured using a text file. This paradigm makes management easy, we just edit the text file, upload it, and then restart the application. The problem is that
iptables doesn’t work that way. That is why
ferm is so useful. Yes,
iptables does save its rules in a text file (at
/etc/sysconfig/iptables) but this file isn’t a true configuration file, its more of an internal shorthand. Editing it directly, as I tried, produces odd errors and doesn’t really work.
Another approach is to use the
iptables command line API directly through statements like:
iptables -P OUTPUT DROP
This almost works but is very tedious to do in Ansible. You have to enter each line as a command. The problem is that changing
iptables can easily disconnect you from the server you have SSH’ed into. The declarative nature of Ansible means that it tries to recreate your ruleset each time so the rules must ‘flush’
iptables and add all the rules back in from scratch. It’s a mess.
Chef and Puppet use a Perl script to manage
iptables. Their script is very similar to
ferm but I think
ferm has better features.
ferm with Ansible on CentOS 6.5 you must take the following steps:
1. Ensure target server has Perl installed. CentOS comes with it so it doesn’t need to be installed separately using
ferm on the target server. Unfortunately
ferm does not have a CentOS package in the default repository so you must install it from EPEL.
3. Create a configuration file called
/etc/ferm/ferm.conf. This configuration file uses unique syntax that is largely based on
iptables own rule syntax. If you know
ferm won’t be a challenge. However,
ferm comes with a very cool and time-saving tool called
import-ferm. This will convert your existing
iptables rules into the
ferm format. Just type
import-ferm > ferm.conf and move the resulting file to your Ansible workstation for automated copying.
5. Save your new iptables configuration so it survives a reboot by:
service iptables save.
And that’s it.
ferm will rebuild your ruleset and does not disconnect your SSH session.
ferm and Ansible
I recommend that you install
ferm using your core role. Mine is called “centos”. Then, install role-specific firewall rules using those roles. For convenience I will put all the Ansible tasks in a single file. Put the
ferm.conf file in
templates\ferm.conf.j2. You will eventually want to add custom variables to your firewall rules.
Ferm conf Example
Here is a simple example for a DHCP server:
In the SSH rule I restrict access to a certain subnet. This templated version uses my Ansible global variables (i.e., those found in the file
[Update: February 24,2014. See part 2 for an improved method.]