The aim

In the past, ipset and iptables configurations are largely maintained manually, by using user scripts with some help from official tools like iptables-save and iptables-restore. Fortunately, in recent Debian and Ubuntu releases, there are official tools specifically designed to minimize such manual work.

The how-to

1. Install the required software

In Debian Buster or Ubuntu Disco (19.04):

sudo apt update && apt install ipset iptables netfilter-persistent ipset-persistent iptables-persistent

As the names suggest, 'ipset-persistent' and 'iptables-persistent' packages enables easy, but not 100% hands-free, saving of current ipset and iptables configurations, respectively. The 'netfilter-persistent' package is the one reponsible of reading and restoring the saved configurations at next boot, or at user's request if necessary.

During installation, you will be prompted whether current ipset and iptables (both v4 and v6) configurations should be saved. Choose 'yes' if no changes to the configurations are required. Regardless, it is possible to do this anytime later.

Currently, 'ipset-persistent' is not officially available for earlier versions of Debian or Ubuntu.

2. Set up ipset

Following is an example demonstrating ipset configuration:

# IPv4 IPs
sudo ipset create AllowedIP hash:ip comment
sudo ipset add AllowedIP comment "My Bastion"

# IPv4 subnets
sudo ipset create AllowedSubnet hash:net comment
sudo ipset add AllowedSubnet comment "My servers"

# IPv6 IPs
sudo ipset create AllowedIPv6 hash:ip family inet6 comment
sudo ipset add AllowedIPv6 1234:5678:: comment "My Bastion"

# IPv6 subnets
sudo ipset create AllowedSubnetv6 hash:net family inet6 comment
sudo ipset add AllowedSubnetv6 1234:5678:9ABC::/48 comment "My servers"

3. Set up iptables and ip6tables

Following is an example configuration exclusively allowing incoming connection from localhost and ipsets defined in the previous section:

# IPv4 rules
sudo iptables -P INPUT ACCEPT
sudo iptables -F
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -m set --match-set AllowedIP src -j ACCEPT
sudo iptables -A INPUT -m set --match-set AllowedSubnet src -j ACCEPT
sudo iptables -P INPUT DROP
# Don't use this if any VPN, container, etc. will be used
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT

# IPv6 rules
sudo ip6tables -P INPUT ACCEPT
sudo ip6tables -F
sudo ip6tables -A INPUT -i lo -j ACCEPT
sudo ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
sudo ip6tables -A INPUT -m set --match-set AllowedIPv6 src -j ACCEPT
sudo ip6tables -A INPUT -m set --match-set AllowedSubnetv6 src -j ACCEPT
sudo ip6tables -P INPUT DROP
# Don't use this if any VPN, container, etc. will be used
sudo ip6tables -P FORWARD DROP
sudo ip6tables -P OUTPUT ACCEPT

You can use sudo ipset list and sudo iptables -L to check whether everything is as intended

4. Make everything persistent!

With the help of the '*-persistent' packages, you can now save the respective configurations simply by running:

sudo netfilter-persistent save

The output will tell you what has been saved where, so you can check the saved configurations if necessary.

Alternatively, you can also do this for ipset and iptables configurations separately:

# Save ipset configurations to /etc/iptables/ipsets
sudo dpkg-reconfigure ipset-persistent

# Save iptables and ip6tables configurations to /etc/iptables/rules.v[46]
sudo dpkg-reconfigure iptables-persistent

Last but not least, make sure netfilter-persistent service is enabled:

sudo systemctl enable netfilter-persistent
sudo systemctl start netfilter-persistent
sudo systemctl status netfilter-persistent

At next boot, the saved configurations will be automatically loaded and installed by netfilter-persistent, through running scripts in /usr/share/netfilter-persistent/plugins.d.


[1] man netfilter-persistent

[2] man ipset-persistent

[3] man iptables-persistetn


comments powered by Disqus