Skip to content

Host Firewall rules

Host Firewall rules

We want to enforce iptables rules on all servers fleet, including on the ones behind a corporate firewall (and so using NAT for outgoing connections and/or DNAT for incoming ones)

Baseline

The ansible-role-iptables is one of the few roles that isn't applied through a group membership at the ansible inventory level, but is deployed/imported in our baseline (see the import_role task to import iptables rules)

The basic iptables role would (both for ipv4 and ipv6):

  • only allow sshd (tcp/22) from some known bastion hosts
  • create an iptables rules for ipset (centos-blocked-manual)
  • install ipset service
  • block all the rest

It creates a skeleton of other rules to be assembled by iptables (see /etc/sysconfig/iptables.d) to be then reloaded.

That means that from there, any other ansible role would just have to drop his iptables rules file , assemble new config file and reload.

One example is from baseline role itself, importing zabbix-agent :

- name: Configuring iptables rules
  include_role:
    name: iptables
    tasks_from: custom-policy
  vars:
    iptables_policy_name: zabbix-agent
    iptables_protocol: tcp
    iptables_port: "10050"
    iptables_source: "{{ zabbix_server_ip }}"
  tags:
    - iptables

As you can see, the zabbix-agent role, is just importing the custom-policy.yml tasks from iptables role, with some variables (in our case, mentioning that we only accept traffic from zabbix server on tcp/10050 on the agent side). It's quite modular and other roles follow the same principles (usually). Behind the scene that means that :

  • it's creating the /etc/sysconfig/iptables.d/01-input-service-policy-zabbix-agent (from jinja2 ansible template)
  • using the assemble ansible module to concat all snippet files under /etc/sysconfig/iptables.d/
  • restarting iptables with new ruleset
Custom rules (including NAT/DNAT)

Probably better to read the defaults/main.yml to see other features that you can apply with the iptables rules but there are some other features (speicific to host/group variables and not role bound :

Defining custom local rules (empty by default):

iptables_local_input_rules:
  - source: 192.168.0.0/24
    dport: 80
    protocol: tcp
  - dport: 25  # would open for all tcp/25  

Should the node be used as gateway/router/firewall itself, we can control that through the following variables (see the main.yml files for examples :

  • iptables_gw (boolean, default is False)
  • iptables_forward_allow
  • iptables_nat_postrouting_allow
  • iptables_nat_prerouting_allow
  • iptables_redirects (local port)
Ipset

One of the main advantage with ipset is that if you need to add a lot of hosts in a deny list (either for DROP or REJECT rules) , it's faster to just use ipset in memory than iptables rules for all these IP addresses. That means that you can just create one (or mutiple) iptables rules just pointing to ipset rules.

As said above, our basic iptables rule would at least create one iptable rule pointing to the centos-blocked-manual ipset list (empty), but that means that adding an ip directly into ipset would work without having to reload the whole iptables service/ruleset (ipset add blocked-centos-manual $ip)

We also can use/update some public lists from services like Firehol.org. See again the defaults/main.yml iptables file to see some example but by default ipset_block_lists is empty and so not using any of these lists