With a firewall, admins define firewall rules, which sets a policy for things like application ports (TCP/UDP), network ports, IP addresses, and accept-deny statements. This guide helps you get started managing firewall rules with Puppet.
Firewall rules are applied with a top-to-bottom approach. For example, when a service, say SSH, attempts to access resources on the other side of a firewall, the firewall applies a list of rules to determine if or how SSH communications are handled. If a rule allowing SSH access can’t be found, the firewall will deny access to that SSH attempt.
To best way to manage firewall rules with Puppet is to divide them into pre
and post
groups to ensure Puppet checks them in the correct order.
Using this guide, you will learn how to:
-
Install the puppetlabs-firewall
module.
-
Write a module to define the firewall rules for your Puppet managed infrastructure.
-
Add the firewall module to the main manifest.
-
Enforce the desired state using the my_firewall
class.
- The first step is installing the
puppetlabs-firewall
module from the PuppetForge. The module introduces the firewall
resource, which is used to manage and configure firewall rules. For more information about the
puppetlabs-firewall
module, see its README. To install the module, on the master, run:
puppet module install puppetlabs-firewall
The resulting output is similar to this:
Preparing to install into /etc/puppetlabs/puppet/environments/production/modules ...
Notice: Downloading from https://forgeapi.puppetlabs.com ...
Notice: Installing -- do not interrupt ...
/etc/puppetlabs/puppet/environments/production/modules
└── puppetlabs-firewall (v1.6.0)
That's it! You’ve just installed the
firewall
module.
- Next, you'll write the
my_firewall
module, which contains three classes. You'll create the my_firewall
module directory, its manifests
subdirectory, a pre.pp
manifest file and a post.pp
manifest file.- From the command line on the master, navigate to the modules directory:
cd /etc/puppetlabs/code/environments/production/modules
- Create the module directory and its manifests directory:
mkdir -p my_firewall/manifests
- From the
manifests
directory, use your text editor to create pre.pp
. - The pre rules are rules that the firewall applies when a service requests access. It is run before any other rules. Edit
pre.pp
so it contains the following Puppet code:
class my_firewall::pre {
Firewall {
require => undef,
}
firewall { '000 accept all icmp':
proto => 'icmp',
action => 'accept',
}
firewall { '001 accept all to lo interface':
proto => 'all',
iniface => 'lo',
action => 'accept',
}
firewall { '002 reject local traffic not on loopback interface':
iniface => '! lo',
proto => 'all',
destination => '127.0.0.1/8',
action => 'reject',
}
firewall { '003 accept related established rules':
proto => 'all',
state => ['RELATED', 'ESTABLISHED'],
action => 'accept',
}
}
These default rules allow basic networking to ensure that existing connections are not closed.
- Save and exit the file.
- From the
manifests
directory, use your text editor to create post.pp
. - The post rules tell the firewall to drop requests that haven’t met the rules defined by
pre.pp
or in site.pp
. Edit post.pp
so it contains the following Puppet code:
class my_firewall::post {
firewall { '999 drop all':
proto => 'all',
action => 'drop',
before => undef,
}
}
- Save and exit the file.
That’s it! You’ve written a module that contains a class that, once applied, ensures your firewall has rules in it that will be managed by Puppet.
- Now you'll add the
firewall
module to the main manifest so that Puppet is managing firewall configuration on nodes.- On the master, navigate to the main manifest:
cd /etc/puppetlabs/code/environments/production/manifests
- Use your text editor to open
site.pp
. - Add the following Puppet code to your
site.pp
file:
resources { 'firewall':
purge => true,
}
This will clear any existing rules and make sure that only rules defined in
Puppet exist on the machine.
- Add the following Puppet code to your
site.pp
file:
Firewall {
before => Class['my_firewall::post'],
require => Class['my_firewall::pre'],
}
class { ['my_firewall::pre', 'my_firewall::post']: }
These settings will ensure that the pre and post classes are run in the
correct order to avoid locking you out of your node during the first
Puppet run, and declaring
my_firewall::pre
and
my_firewall::post
satisfies the specified dependencies.
- Add the
firewall
class to your site.pp
to ensure the correct packages are installed: - To apply the configuration, on the agent, run Puppet:
puppet agent -t
That's it! Puppet is now managing the firewall configuration on the agent.
- To check your firewall configuration, on the agent, run:
iptables --list
The resulting output is similar to this:
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT icmp -- anywhere anywhere /* 000 accept all icmp */
ACCEPT all -- anywhere anywhere /* 001 accept all to lo interface */
REJECT all -- anywhere loopback/8 /* 002 reject local traffic not on loopback interface */ reject-with icmp-port-unreachable
ACCEPT all -- anywhere anywhere /* 003 accept related established rules */ state RELATED,ESTABLISHED
DROP all -- anywhere anywhere /* 999 drop all */
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
- Finally, let’s take a look at how Puppet will ensure the desired state of the
my_firewall
class on your agents. In the previous step, you applied the firewall rules. Now, simulate a scenario where a member of your team changes the contents the iptables
to allow connections on a random port that was not specified in my_firewall
:- On an agent where you applied the
my_firewall
class, run:
iptables --list
Note that the rules from the
my_firewall
class have been applied.
- From the command line, add a rule to allow connections to port 8449 by running:
iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 8449 -j ACCEPT
- Run
iptables --list
again and see that this new rule is now listed. - Run Puppet on that agent:
puppet agent -t --onetime
- Run
iptables --list
on that node once more, and notice that Puppet has enforced the desired state you specified for the firewall rules
That’s it! Puppet has enforced the desired state of your agent.
You can learn more about the Puppet firewall module by visiting the
Forge
.
Puppet offers many opportunities for learning and training, from formal certification courses to guided online lessons. See the Learning Puppet page for more information.