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 denies 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 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
Puppet
Forge. 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 primary server, 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 primary server, 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, after it's applied, ensures your
firewall has rules in it that are 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 primary server, 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
clears 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 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 ensures 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 one more time, 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.
Results
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.