firewall

{Build Status]

Table of Contents

  1. Overview - What is the Firewall module?

  2. Module Description - What does the module do?

  3. Setup - The basics of getting started with Firewall

  4. Usage - Configuration and customization options

  5. Reference - An under-the-hood peek at what the module is doing

  6. Limitations - OS compatibility, etc.

  7. Development - Guide for contributing to the module

Overview

The Firewall module lets you manage firewall rules with Puppet.

Module Description

PuppetLabs' Firewall module introduces the firewall resource, which is used to manage and configure firewall rules from within the Puppet DSL. This module offers support for iptables and ip6tables. The module also introduces the firewallchain resource, which allows you to manage chains or firewall lists and ebtables for bridging support. At the moment, only iptables and ip6tables chains are supported.

The Firewall module acts on your running firewall, making immediate changes as the catalog executes. Defining default pre and post rules allows you to provide global defaults for your hosts before and after any custom rules. Defining pre and post rules is also necessary to help you avoid locking yourself out of your own boxes when Puppet runs.

Setup

What Firewall Affects

Setup Requirements

Firewall uses Ruby-based providers, so you must enable pluginsync enabled.

Beginning with Firewall

In the following two sections, you create new classes and then create firewall rules related to those classes. These steps are optional, but provide a framework for firewall rules, which is helpful if you’re just starting to create them.

If you already have rules in place, then you don’t need to do these two sections. However, be aware of the ordering of your firewall rules. The module will dynamically apply rules in the order they appear in the catalog, meaning a deny rule could be applied before the allow rules. This might mean the module hasn’t established some of the important connections, such as the connection to the Puppet master.

The following steps are designed to ensure that you keep your SSH and other connections, primarily your connection to your Puppet master. If you create the pre and post classes described in the first section, then you also need to create the rules described in the second section.

Create the my_fw::pre and my_fw::post Classes

This approach employs a whitelist setup, so you can define what rules you want and everything else is ignored rather than removed.

The code in this section does the following:

Therefore, the run order is:

The rules in the pre and post classes are fairly general. These two classes ensure that you retain connectivity and that you drop unmatched packets appropriately. The rules you define in your manifests are likely specific to the applications you run.

  1. Add the pre class to my_fw/manifests/pre.pp. pre.pp should contain any default rules to be applied first. The rules in this class should be added in the order you want them to run.

    class my_fw::pre { Firewall { require => undef, }

    # Default firewall rules firewall { '000 accept all icmp': proto => 'icmp', action => 'accept', }-> firewall { '001 accept all to lo interface': proto => 'all', iniface => 'lo', action => 'accept', }-> firewall { '002 accept related established rules': proto => 'all', state => ['RELATED', 'ESTABLISHED'], action => 'accept', } }

The rules in pre should allow basic networking (such as ICMP and TCP) and ensure that existing connections are not closed.

  1. Add the post class to my_fw/manifests/post.pp and include any default rules to be applied last.

    class my_fw::post { firewall { '999 drop all': proto => 'all', action => 'drop', before => undef, } }

Create Firewall Rules

The rules you create here are helpful if you don’t have any existing rules; they help you order your firewall configurations so you don’t lock yourself out of your box.

Rules are persisted automatically between reboots, although there are known issues with ip6tables on older Debian/Ubuntu distributions. There are also known issues with ebtables.

  1. In site.pp or another top-scope file, add the following code to set up a metatype to purge unmanaged firewall resources. This will clear any existing rules and make sure that only rules defined in Puppet exist on the machine.

Note - This only purges IPv4 rules.

resources { "firewall":
  purge => true
}
  1. Use the following code to set up the default parameters for all of the firewall rules you will establish later. These defaults will ensure that the pre and post classes are run in the correct order to avoid locking you out of your box during the first Puppet run.

    Firewall { before => Class, require => Class, }

  2. Then, declare the my_fw::pre and my_fw::post classes to satisfy dependencies. You can declare these classes using an External Node Classifier or the following code:

    class { ['my_fw::pre', 'my_fw::post']: }

  3. Include the firewall class to ensure the correct packages are installed.

    class { 'firewall': }

Upgrading

Use these steps if you already have a version of the Firewall module installed.

From version 0.2.0 and more recent

Upgrade the module with the puppet module tool as normal:

puppet module upgrade puppetlabs/firewall

Usage

There are two kinds of firewall rules you can use with Firewall: default rules and application-specific rules. Default rules apply to general firewall settings, whereas application-specific rules manage firewall settings for a specific application, node, etc.

All rules employ a numbering system in the resource's title that is used for ordering. When titling your rules, make sure you prefix the rule with a number, for example, 000 accept all icmp requests

  000 runs first
  999 runs last

Default Rules

You can place default rules in either my_fw::pre or my_fw::post, depending on when you would like them to run. Rules placed in the pre class will run first, and rules in the post class, last.

In iptables, the title of the rule is stored using the comment feature of the underlying firewall subsystem. Values must match '/^d+[[:digit:][:space:]]+$/'.

Examples of Default Rules

Basic accept ICMP request example:

firewall { "000 accept all icmp requests":
  proto  => "icmp",
  action => "accept",
}

Drop all:

firewall { "999 drop all other requests":
  action => "drop",
}

Application-Specific Rules

Puppet doesn't care where you define rules, and this means that you can place your firewall resources as close to the applications and services that you manage as you wish. If you use the roles and profiles pattern then it makes sense to create your firewall rules in the profiles, so that they remain close to the services managed by the profile.

This is an example of firewall rules in a profile:

class profile::apache {
  include apache
  apache::vhost { 'mysite': ensure => present }

  firewall { '100 allow http and https access':
    port   => [80, 443],
    proto  => tcp,
    action => accept,
  }
}

Rule inversion

Firewall rules may be inverted by prefixing the value of a parameter by “! ”. If the value is an array, then every item in the array must be prefixed as iptables does not understand inverting a single value.

Parameters that understand inversion are: connmark, ctstate, destination, dport, dst_range, dst_type, port, proto, source, sport, src_range, src_type, and state.

Examples:

firewall { '001 disallow esp protocol':
  action => 'accept',
  proto  => '! esp',
}
firewall { '002 drop NEW external website packets with FIN/RST/ACK set and SYN unset':
  chain     => 'INPUT',
  state     => 'NEW',
  action    => 'drop',
  proto     => 'tcp',
  sport     => ['! http', '! 443'],
  source    => '! 10.0.0.0/8',
  tcp_flags => '! FIN,SYN,RST,ACK SYN',
}

Additional Uses for the Firewall Module

You can apply firewall rules to specific nodes. Usually, you will want to put the firewall rule in another class and apply that class to a node. Apply a rule to a node as follows:

node 'some.node.com' {
  firewall { '111 open port 111':
    dport => 111
  }
}

You can also do more complex things with the firewall resource. This example sets up static NAT for the source network 10.1.2.0/24:

firewall { '100 snat for network foo2':
  chain    => 'POSTROUTING',
  jump     => 'MASQUERADE',
  proto    => 'all',
  outiface => "eth0",
  source   => '10.1.2.0/24',
  table    => 'nat',
}

The following example creates a new chain and forwards any port 5000 access to it.

firewall { '100 forward to MY_CHAIN':
  chain   => 'INPUT',
  jump    => 'MY_CHAIN',
}
# The namevar here is in the format chain_name:table:protocol
firewallchain { 'MY_CHAIN:filter:IPv4':
  ensure  => present,
}
firewall { '100 my rule':
  chain   => 'MY_CHAIN',
  action  => 'accept',
  proto   => 'tcp',
  dport   => 5000,
}

Additional Information

Access the inline documentation:

puppet describe firewall

Or

puppet doc -r type
(and search for firewall)

Reference

Classes:

Types:

Facts:

Class: firewall

Performs the basic setup tasks required for using the firewall resources.

At the moment this takes care of:

Include the firewall class for nodes that need to use the resources in this module:

class { 'firewall': }

ensure

Parameter that controls the state of the iptables service on your system, allowing you to disable iptables if you want.

ensure can either be running or stopped. Default to running.

Type: firewall

This type enables you to manage firewall rules within Puppet.

Providers

Note: Not all features are available with all providers.

Autorequires:

If Puppet is managing the iptables or ip6tables chains specified in the chain or jump parameters, the firewall resource will autorequire those firewallchain resources.

If Puppet is managing the iptables or iptables-persistent packages, and the provider is iptables or ip6tables, the firewall resource will autorequire those packages to ensure that any required binaries are installed.

Features

Parameters

If you specify no value it will simply match the rule but perform no action unless you provide a provider-specific parameter (such as jump).

For some firewall providers you can pass a range of ports in the format: 'start number-end number'. For example, '1-1024' would cover ports 1 to 1024.

The destination IP range is must in 'IP1-IP2' format. Values must match '0.0.0.0-0.0.0.0' through '255.255.255.255-255.255.255.255'. Requires the iprange feature.

Valid values are:

Requires the address_type feature.

For the values 'ACCEPT', 'DROP', and 'REJECT', you must use the generic action parameter. This is to enforce the use of generic parameters where possible for maximum cross-platform modeling.

If you set both accept and jump parameters, you will get an error, because only one of the options should be set. Requires the iptables feature.

firewall { '000 this runs first':
  # this rule will run first
}
firewall { '999 this runs last':
  # this rule will run last
}

Depending on the provider, the name of the rule can be stored using the comment feature of the underlying firewall subsystem. Values must match '/^d+[[:digit:][:space:]]+$/'.

# If anyone's appeared on the 'badguy' blacklist within
# the last 60 seconds, drop their traffic, and update the timestamp.
firewall { '100 Drop badguy traffic':
  recent   => 'update',
  rseconds => 60,
  rsource  => true,
  rname    => 'badguy',
  action   => 'DROP',
  chain    => 'FORWARD',
}
# No-one should be sending us traffic on eth0 from localhost
# Blacklist them
firewall { '101 blacklist strange traffic':
  recent      => 'set',
  rsource     => true,
  rname       => 'badguy',
  destination => '127.0.0.0/8',
  iniface     => 'eth0',
  action      => 'DROP',
  chain       => 'FORWARD',
}

Requires the recent_limiting feature.

Valid values are:

Requires the address_type feature.

Note that you specify flags in the order that iptables --list rules would list them to avoid having Puppet think you changed the flags. For example, 'FIN,SYN,RST,ACK SYN' matches packets with the SYN bit set and the ACK, RST and FIN bits cleared. Such packets are used to request TCP connection initiation. Requires the tcp_flags feature.

Type: firewallchain

Enables you to manage rule chains for firewalls.

Currently this type supports only iptables, ip6tables, and ebtables on Linux. It also provides support for setting the default policy on chains and tables that allow it.

Autorequires: If Puppet is managing the iptables or iptables-persistent packages, and the provider is iptables_chain, the firewall resource will autorequire those packages to ensure that any required binaries are installed.

Providers

iptables_chain is the only provider that supports firewallchain.

Features

Parameters

Full example:

  firewallchain { 'INPUT:filter:IPv4': 
    purge  => true, 
    ignore => [
       # ignore the fail2ban jump rule
       '-j fail2ban-ssh', 
       # ignore any rules with "ignore" (case insensitive) in the comment in the rule 
       '--comment "[^"](?i:ignore)[^"]"', 
     ],
  }

iptables_chain: iptables chain provider

* Required binaries: `ebtables-save`, `ebtables`, `ip6tables-save`, `ip6tables`, `iptables-save`, `iptables`.
* Default for `kernel` == `linux`.
* Supported features: `iptables_chain`, `policy`.

Fact: ip6tables_version

A Facter fact that can be used to determine what the default version of ip6tables is for your operating system/distribution.

Fact: iptables_version

A Facter fact that can be used to determine what the default version of iptables is for your operating system/distribution.

Fact: iptables_persistent_version

Retrieves the version of iptables-persistent from your OS. This is a Debian/Ubuntu specific fact.

Limitations

SLES

The socket parameter is not supported on SLES. In this release it will cause the catalog to fail with iptables failures, rather than correctly warn you that the features are unusable.

Oracle Enterprise Linux

The socket and owner parameters are unsupported on Oracle Enterprise Linux when the “Unbreakable” kernel is used. These may function correctly when using the stock RedHat kernel instead. Declaring either of these parameters on an unsupported system will result in iptable rules failing to apply.

Other

Bugs can be reported using JIRA issues

tickets.puppetlabs.com

Development

Puppet Labs modules on the Puppet Forge are open projects, and community contributions are essential for keeping them great. We can’t access the huge number of platforms and myriad of hardware, software, and deployment configurations that Puppet is intended to serve.

We want to keep it as easy as possible to contribute changes so that our modules work in your environment. There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things.

You can read the complete module contribution guide on the Puppet Labs wiki.

For this particular module, please also read CONTRIBUTING.md before contributing.

Currently we support:

Testing

Make sure you have:

Install the necessary gems:

bundle install

And run the tests from the root of the source code:

rake test

If you have a copy of Vagrant 1.1.0 you can also run the system tests:

RS_SET=ubuntu-1404-x64 rspec spec/acceptance
RS_SET=centos-64-x64 rspec spec/acceptance

^1 a-zA-Z0-9-_

^2 a-zA-Z0-9-._+

^3 a-zA-Z0-9-._+

^4 a-zA-Z0-9-._+