Skip to main navigation
#! code
Code Tips, Snippets, Resources, Tutorials And Help
  • Home
  • Tools
  • About
  • Contact

Adding iptables Rules With Ansible

By philipnorton42 on 16th February 2014

Many systems and applications require certain access to certain ports and protocols. When installing these systems using Ansible it is necessary to also open up the needed ports so that the systems can function correctly. As there is no iptables module in Ansible the shell command is needed to add the iptables rules.

As an example, here is a task that adds a iptables rule to allow Apache to communicate on port 80.

  1. - name: Apache | add apache iptable rule
  2. command: /sbin/iptables -I INPUT 1 -p tcp --dport http -j ACCEPT -m comment --comment "Apache"
  3. sudo: true

Once this is in place you might need to save and/or restart iptables in order to get the rule to be permanently saved. The following two rules will save the iptables rule and restart the iptables service. Note that these commands are specific to Ubuntu and so might not work on your system setup.

  1. - name: save iptables
  2. command: iptables-save
  3. sudo: true
  4.  
  5. - name: restart iptables
  6. service: name=ufw state=restarted
  7. sudo: true

This allows Apache to communicate, but the trouble is that when the Ansible task is run a second time a second iptables rule will be added. This can cause problems, especially when Ansible is run over and over again to maintain the configuration of the server. For this reason another step must be added to detect for the existence of the rule before it is added. This is done by using the shell module to print the available iptables rules out and store them into a variable. The Ansible keyword 'register' allows any returned value from the current task to be saved as a variable, in this case the variable registered is called 'iptablesrules'.

  1. - name: Apache | get iptables rules
  2. shell: iptables -L
  3. register: iptablesrules
  4. sudo: true

With this in place we can now run the iptables insertion command only when we cannot find a rule that matches the one that we want to add. The find function is run on the iptablesrules.stdout parameter to find the word "Apache" within the contents. This matches the comment that was used in the iptables rule creation. and Here is the modified task.

  1. - name: Apache | add apache iptable rule
  2. command: /sbin/iptables -I INPUT 1 -p tcp --dport http -j ACCEPT -m comment --comment "Apache"
  3. sudo: true
  4. when: iptablesrules.stdout.find("Apache") == -1

The only problem now is that when checking that an Ansible playbook will execute as expected (by using the --check flag) the added conditional will fail. This is because the iptablesrules variable that is generated is not done in this case and so Ansible will error and complain about a missing variable. The way around this it to force the iptables rules variable registry task to always run, even if we are in check mode. To do this we add the always_run flag to the task.

  1. - name: Apache | get iptables rules
  2. shell: iptables -L
  3. register: iptablesrules
  4. always_run: yes
  5. sudo: true

Here is the entire playbook in full. Note that it is better practice to use create the iptables save and restart tasks as handlers and notify them from the needed tasks. This allows them to be reused when generating iptables rules for other services.

  1. ---
  2. - name: Apache | get iptables rules
  3. shell: iptables -L
  4. register: iptablesrules
  5. always_run: yes
  6. sudo: true
  7.  
  8. - name: Apache | add apache iptable rule
  9. command: /sbin/iptables -I INPUT 1 -p tcp --dport http -j ACCEPT -m comment --comment "Apache"
  10. sudo: true
  11. when: iptablesrules.stdout.find("Apache") == -1
  12.  
  13. - name: save iptables
  14. command: iptables-save
  15. sudo: true
  16.  
  17. - name: restart iptables
  18. service: name= ufw state=restarted
  19. sudo: true
Category
Ansible
Tags
Apache

Comments

Permalink

Gastón Sánchez - Wed, 04/23/2014 - 20:57

Great! now there is a module to handle that http://docs.ansible.com/ufw_module.html
Permalink

adrinux - Thu, 04/24/2014 - 17:14

It's also worth taking a look at Ferm[1] for managing iptables configuration. It remains a less than perfect solution, but It is possible to add firewall rules with each role. See http://wiki.gema-soft.de/doku.php?id=it-administration:tools:ansible:fe… for an example Ansible Ferm setup. [1] http://ferm.foo-projects.org/
Permalink

iamc - Wed, 04/30/2014 - 09:42

Great playbook, thanks for sharing. I just added changed_when: false to the "get iptables rules" task so that it does not report as changed when running the playbook. - name: Apache | get iptables rules shell: iptables -L register: iptablesrules always_run: yes changed_when: false # Never report as changed sudo: true
Permalink

Mike Gleason j… - Tue, 11/10/2015 - 13:50

I created a role to ease the process of using iptables with Ansible, check it out: https://github.com/mikegleasonjr/ansible-role-firewall Thank you
Permalink

Tom - Wed, 05/04/2016 - 14:43

iptables-save doesn't save the iptables...
Permalink

Am Elemara - Wed, 09/07/2016 - 11:15

Another way to do it...
  1. -name: Save iptables rules
  2. command: /sbin/service iptables save
  3. sudo: True

Add new comment

The content of this field is kept private and will not be shown publicly.
About text formats
CAPTCHA This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.
  • Add new comment

Categories

  • Ansible
  • Apache
  • Book Reviews
  • CSS
  • DOS/Windows
  • Drupal
    • Drupal 8
    • SimpleTest
  • Flex/Flash
  • General
  • Git
  • HTML/XHTML
  • JavaScript
    • JavaScript Strings
    • JavaScript Websites
    • JQuery
    • MooTools
    • OpenLayers
    • Script.aculo.us
  • Linux/Unix
  • MS SQL
  • OSX
  • PhoneGap
  • PHP
    • Phing
    • PHP Arrays
    • PHP Questions
    • PHP Strings
    • PHP Websites
    • Zend Framework
  • PostgreSQL
  • Python
  • Regular Expressions
  • Regular Expressions Websites
  • SQL
    • MS SQL
    • MySQL
    • PostgreSQL
  • Vagrant
  • Websites
  • WordPress

User login

  • Reset your password

© 2019 #! code

  • Twitter
  • Facebook
  • Google+
  • Github
  • RSS
  • Colophon
  • Privacy Policy
  • Terms and License