mikegleasonjr / ansible-role-firewall

A role to manage iptables rules which doesn't suck.
BSD 2-Clause "Simplified" License
95 stars 39 forks source link

⚠ SECURITY ISSUE: using ipset breaks persistance #43

Open maltfield opened 2 months ago

maltfield commented 2 months ago

This ticket is a bug report for an issue where this ansible role will render a server to have no firewall rules on boot if a user happens to add a rule with ipset to its firewall rules on Debian.

⚠ WARNING: Currently, if a user adds a firewall rule to this ansible role's config (firewall_v4_default_rules or firewall_v6_default_rules, etc), that uses the -m set module then on the next server reboot, the server will come-up without any firewall rules, leaving the server very exposed and at-risk!

Problem

This module installs iptables-persistent but not ipset-persistent. As a result, when a system (whose firewall is managed by this ansible role) reboots, the iptables.v4.generated script will exit with an error if a user uses this ansible role to define an iptables rule using the -m set module:

iptables vA.B.C (legacy): Set example.com doesn't exist.

The result is that the firewall table will be completely empty on-boot, leaving the server very exposed and at-risk!

ipset what?

What is the ipset module? I'll quote from their website:

IP sets are a framework inside the Linux kernel, which can be administered by the ipset utility. Depending on the type, an IP set may store IP addresses, networks, (TCP/UDP) port numbers, MAC addresses, interface names or combinations of them in a way, which ensures lightning speed when matching an entry against a set.

If you want to

  • store multiple IP addresses or port numbers and match against the collection by iptables at one swoop;
  • dynamically update iptables rules against IP addresses or ports without performance penalty;
  • express complex IP address and ports based rulesets with one single iptables rule and benefit from the speed of IP sets

then ipset may be the proper tool for you.

Using ipset is very useful to be able to create iptables rules that match against DNS addresses, for example.

steps to reproduce

To reproduce this issue, first install ipset and create a simple ipset.

# install prereqs
apt install ipset dnsutils

ipset create ipv4-github.com hash:ip family inet
ips=$(dig -t A +short "github.com" | grep -v '\.$')
ipset add ipv4-github.com "${ips}"

# verify
ipset list ipv4-github.com

Update your ansible role variables

firewall_v4_default_rules:
  001 default policies:
    - -P INPUT ACCEPT
    - -P OUTPUT ACCEPT
    - -P FORWARD DROP
  002 allow loopback:
    - -A INPUT -i lo -s 127.0.0.0/8 -d 127.0.0.0/8 -j ACCEPT
  003 block github
    - -A INPUT -m set --match-set ipv4-github.com  -j DROP

Reboot

reboot

The system will come-up without any iptables rules :(

Solution

The solution to this problem appears to be very simple: just ensure ipset-persistent is installed.

maltfield commented 2 months ago

See also:

maltfield commented 2 months ago

@mikegleasonjr I've created a PR to fix this