20

What is the best way to manage iptables from one point and have the ability to edit something on local server.

We need to add some rules centralized on all servers, but we have specific servers with specific requirements which should have their own set of rules.

I thought about bash script with multiple include which is managed centralized with ansible and includes managed on local server. Is it good approach? Or maybe there is something better?

We can't create yml2 templates for ansible because there is too much difference between specific hosts.

Please provide examples of centralized management of iptables.

24

ufw

Ansible has a ufw module in order to handle firewall rules. In roles/common/tasks/main.yml, which is included in all my servers, I have (among other things):

- name: Install ufw
  apt: name=ufw
- name: Allow ssh through firewall
  ufw: proto=tcp port=22 rule=allow
- name: Set ufw policy
  ufw: state=enabled direction=incoming policy=deny

Edit: It is necessary to allow ssh before setting default policy to "deny" (originally it was opposite above), otherwise you may be locked out in between the two steps.

Then, in each role, I have additional firewall rules for that role. For example, in roles/nginx/tasks/main.yml, I have (among other things) this:

- name: Allow nginx firewall
  ufw: proto=tcp port=80 rule=allow
- name: Allow nginx ssl firewall
  ufw: proto=tcp port=443 rule=allow

So all my nginx servers have ports 80 and 443 opened.

This way you can build whatever common configuration you want and add additional rules in more specific roles.

ferm

If you have rules which ufw cannot handle, one solution I think would work nicely is ferm; it can do almost anything, and you can configure it to read rules from directories such as /etc/ferm/input.d/, /etc/ferm/output.d/, /etc/ferm/forward.d/, etc. You could make your common role prepare the essential ferm configuration and then have other roles drop files in these directories.

plain iptables

Your requirement to have ansible specify rules in addition to rules specified in another way is unusual and apparently defies most of the point for using ansible. Unfortunately I don't see any way to do it other than with plain iptables, which would be quite ugly. Here is an example of opening up port 80 in roles/nginx/tasks/main.yml (untested):

- name: Check if port 80 is allowed
  shell: iptables -L | grep -q "Allow http" && echo -n yes || echo -n no
  register: check_allow_http
  changed_when: no
  always_run: yes

- name: Allow port 80
  command: >
    iptables -A INPUT -p tcp -m tcp --dport 80
    -m comment --comment "Allow http" -j ACCEPT
  when: check_allow_http.stdout == "no"
  notify:
  - Save iptables

where Save iptables is a handler that executes iptables-save. All the above is quite tedious to write, but it might be appropriate, especially if you have only a few rules to manage with ansible.

  • If i remember correctly with this approach i can't use ipset and create something very specific. We are using module owner in iptables. For example we have iptables -m owner --uid 0 -j ACCEPT. I can't use this module with ufw in ansible and can't edit something without ansible on local server. – Navern Aug 14 '14 at 10:49
  • Indeed, ufw apparently can't handle your needs; but what do you mean when you say you "can't edit something without ansible on local server"? – Antonis Christofides Aug 14 '14 at 11:25
  • Is there another solution? I stuck with this case, hard to solve. In general i mean that i need to only add NEW rules with ansible without breaking existing one. Do not store all configuration on server with ansible. English not my native language, so i hope i made myself clear:) – Navern Aug 14 '14 at 11:28
  • Updated my answer with some alternatives. – Antonis Christofides Aug 14 '14 at 12:27
  • Thank you veru much i will look into this, especially ferm. – Navern Aug 14 '14 at 14:45
12

lineinfile

If you want to manage rules in your iptables configuration without overwriting existing rules or centrally managing iptables in a template, use Ansible's lineinfile module:

- name: ensure iptables allows established and related traffic
  lineinfile:
    dest=/etc/sysconfig/iptables
    state=present 
    regexp="^.*INPUT.*ESTABLISHED,RELATED.*ACCEPT" 
    insertafter="^:OUTPUT " line="-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT" 
    backup=yes
  notify: restart iptables


- name: ensure iptables is configured to allow ssh traffic (port 22/tcp)
  lineinfile:
    dest=/etc/sysconfig/iptables 
    state=present 
    regexp="^.*INPUT.*tcp.*22.*ACCEPT" 
    insertafter="^.*INPUT.*ESTABLISHED,RELATED.*ACCEPT" line="-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT" 
    backup=yes
  notify: restart iptables

Here's the "restart iptables" handler:

- name: restart iptables
  service: name=iptables state=restarted
2

I created a role to manage iptables rules with the following features:

  • Support virtually all iptables rules
  • Allow granular rules addition/overriding for specific hosts
  • Easily inject variables in the rules
  • Allow rules ordering
  • Simplicity
  • Persistence (reload the rules at boot)

Check out mikegleasonjr.firewall on ansible galaxy or on github

0

We wrote a special module for this called iptables_raw which allows us to easily manage iptables. Everything is explained in this blog post. Here is an example of how to use the module:

# Allow all IPv4 traffic coming in on port 80
- iptables_raw:
    name=allow_tcp_80
    rules='-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT'

# Delete the above rule
- iptables_raw:
    name=allow_tcp_80
    state=absent
  • we have solved this issue with this script: github.com/SmilingNavern/iptables. – Navern Jul 7 '16 at 11:16
  • But there is no proper documentation currently. I can explain how it works and post as answer later. – Navern Jul 7 '16 at 11:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.