ce-provision

Firewall Config

This role provides a wrapper for Jeff Geerling’s Ansible firewall role for iptables .

Note, it explicitly does not state that dependency in meta because in some cases iptables needs installing from buster-backports and that cannot work if Ansible tries to install it as a dependency. This is why the first task in this role is installing iptables from buster-backports if the is_local variable is set (e.g we are in a ce-dev container).

Usage

The role has a concept of rulesets which take the form of a set of lists of firewall rules to apply. We ship some standard rulesets, such as this one called web_open which opens TCP ports 80 and 443:

firewall_config:
  web_open:
    firewall_allowed_tcp_ports:
      - "80"
      - "443"

See the main firewall role for available options and usage: https://github.com/geerlingguy/ansible-role-firewall/blob/master/defaults/main.yml#L7

Your firewall_config rulesets can be loaded in from anywhere Ansible will load variables, so modules can invoke this role directly and set their own rulesets in their variables files. To work through an example, if I wanted to have a list of restricted IPs for SSH on a web server, I could make a custom ruleset like this in a file in config/hosts/group_vars/all:

firewall_config:
  ssh_restricted:
    firewall_additional_rules:
      - "iptables -A INPUT -p tcp --dport 22 -s 1.0.0.1 -j ACCEPT" # old vpn
      - "iptables -A INPUT -p tcp --dport 22 -s 1.1.1.1 -j ACCEPT" # vpn
      - "iptables -A INPUT -p tcp --dport 22 -s 8.8.8.8 -j ACCEPT" # infra1

Then in my variables for the web server I can set rulesets like this:

firewall_config:
  rulesets:
    - ssh_restricted
    - web_open

So Ansible will apply my custom ssh_restricted ruleset and the built-in web_open ruleset.

Default variables

---
firewall_config:
  # Because firewall.bash isn't overwritten once it exists we need to delete it to apply rule changes.
  purge: true
  # General settings
  # See https://github.com/geerlingguy/ansible-role-firewall/blob/master/defaults/main.yml
  firewall_state: started
  firewall_enabled_at_boot: true
  firewall_enable_ipv6: false
  firewall_log_dropped_packets: true
  firewall_disable_ufw: true
  firewall_allowed_tcp_ports: [ "22" ] # initially open port 22 so we don't lose connection
  rulesets:
    - ssh_open
    - web_open
    - common_network # rule always needs to be last so the DROP rules in the OUTPUT chain get applied at the end

  # Ruleset definitions
  # Permitted rule lists
  # firewall_allowed_tcp_ports
  # firewall_allowed_udp_ports
  # firewall_forwarded_tcp_ports
  # firewall_forwarded_udp_ports
  # firewall_additional_rules
  # firewall_ip6_additional_rules
  ssh_open:
    firewall_allowed_tcp_ports:
      - "22"
  web_open:
    firewall_allowed_tcp_ports:
      - "80"
      - "443"
  mailpit_open:
    firewall_allowed_tcp_ports:
      - "8025"
  ftp_open:
    firewall_allowed_tcp_ports:
      - "20"
      - "21"
  sftp_open:
    firewall_allowed_tcp_ports:
      - "989"
      - "990"
  letsencrypt:
    firewall_allowed_tcp_ports:
      - "80"
  # Standard ports for Prometheus outbound rules to allow scraping of exporters
  prometheus_server_scraping:
    firewall_additional_rules:
      - "iptables -A OUTPUT -p tcp --dport 9100 -j ACCEPT" # allow scraping node exporter
      - "iptables -A OUTPUT -p tcp --dport 9101 -j ACCEPT" # allow scraping process exporter
      - "iptables -A OUTPUT -p tcp --dport 9093 -j ACCEPT" # allow posting to alertmanager
      - "iptables -A OUTPUT -p tcp --dport 9115 -j ACCEPT" # allow scraping blackbox exporter
  # Commonly required outbound ports for PHP web servers
  common_web:
    firewall_additional_rules:
      - "iptables -A OUTPUT -p tcp --dport 2049 -j ACCEPT" # allow NFS
      - "iptables -A OUTPUT -p udp --dport 2049 -j ACCEPT" # allow NFS
      - "iptables -A OUTPUT -p tcp --dport 3306 -j ACCEPT" # allow MySQL
  # Recommended general firewall settings
  common_network:
    firewall_additional_rules:
      - "iptables -A INPUT -p icmp --icmp-type 8 -s 0/0 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT" # ICMP ping in
      - "iptables -A INPUT -p icmp --icmp-type 128 -s 0/0 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT" # ICMP ping in
      - "iptables -A OUTPUT -p icmp --icmp-type 0 -d 0/0 -m state --state ESTABLISHED,RELATED -j ACCEPT" # ICMP ping out
      - "iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT" # established connections out
      - "iptables -A OUTPUT -o lo -j ACCEPT" # allow all local traffic
      - "iptables -A OUTPUT -p tcp --dport 1025:65535 -j DROP" # block high port tcp traffic outbound
      - "iptables -A OUTPUT -p udp --dport 1025:65535 -j DROP" # block high port udp traffic outbound
  ossec:
    firewall_allowed_udp_ports:
      - "1514"
      - "1515"
  openvpn:
    firewall_allowed_udp_ports:
      - "1194"
    firewall_additional_rules:
      - "echo 1 > /proc/sys/net/ipv4/ip_forward" # Enable forwarding of IP
      - "iptables -A INPUT -s 10.8.0.0/24 -i tun0 -j ACCEPT" # Accept traffic from the VPN on all interfaces - change this if you change openvpn_config default addresses
      - "iptables -A FORWARD -i tun0 -o eth0 -j ACCEPT" # Forward traffic from the VPN interface out via eth0
      - "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE" # Replace the source IP with the eth0 public IP when forwarding outbound