Manage firewall rules

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.

Before you begin

Before starting this walk-through, complete the previous exercises in the common configuration tasks.

Ensure you’ve already installed Puppet, and at least one *nix agent. Also, log in as root or Administrator on your nodes.

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.

  1. 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.
  2. 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.
    1. From the command line on the primary server, navigate to the modules directory:
      cd /etc/puppetlabs/code/environments/production/modules
    2. Create the module directory and its manifests directory:
      mkdir -p my_firewall/manifests
    3. From the manifests directory, use your text editor to create pre.pp.
    4. 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.
    5. Save and exit the file.
    6. From the manifests directory, use your text editor to create post.pp.
    7. 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,
           }
         }
    8. 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.

  3. Now you'll add the firewall module to the main manifest so that Puppet is managing firewall configuration on nodes.
    1. On the primary server, navigate to the main manifest:
      cd /etc/puppetlabs/code/environments/production/manifests
    2. Use your text editor to open site.pp.
    3. 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.
    4. 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.
    5. Add the firewall class to your site.pp to ensure the correct packages are installed:
      class { 'firewall': }
    6. 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.

    7. 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
  4. 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:
    1. 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.
    2. 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
    3. Run iptables --list again and see that this new rule is now listed.
    4. Run Puppet on that agent:
      puppet agent -t --onetime
    5. 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.