Use nftables on Debian along with existing Docker and Libvirt tables
nftables is the modern firewall framework on Linux. However, many applications, like Docker, still only supports iptables. On modern Linux distributions, the iptables
command is actually a shim that translates iptables to nftables:
root@vps-9d0b1db8:~# update-alternatives --display iptables
iptables - auto mode
link best version is /usr/sbin/iptables-nft
link currently points to /usr/sbin/iptables-nft
link iptables is /usr/sbin/iptables
slave iptables-restore is /usr/sbin/iptables-restore
slave iptables-save is /usr/sbin/iptables-save
/usr/sbin/iptables-legacy - priority 10
slave iptables-restore: /usr/sbin/iptables-legacy-restore
slave iptables-save: /usr/sbin/iptables-legacy-save
/usr/sbin/iptables-nft - priority 20
slave iptables-restore: /usr/sbin/iptables-nft-restore
slave iptables-save: /usr/sbin/iptables-nft-save
Using nft list ruleset
you can see the existing tables. The ones created by iptables-nft
will have this warning:
# Warning: table ip filter is managed by iptables-nft, do not touch!
table ip filter {
...
}
This means that we should not touch this table named “filter”, but we are free to create other tables. With a few tweaks, it is possible.
nftables service
By default, the nftables service on Debian has a command that flushes all ruleset when the service is stopped (or restarted). This is not wanted when we only want to manage our own tables and leave the others alone. Remove it:
systemctl edit nftables.service
### Editing /etc/systemd/system/nftables.service.d/override.conf
### Anything between here and the comment below will become the new contents of the file
[Service]
ExecStop=
### Lines below this comment will be discarded
nftables config
The nftables configuration file nftables.conf
by default starts with flush ruleset
. For the same reason as in the systemd service, this line should be removed. Instead, add a rule that only deletes your firewall table:
table inet firewall
delete table inet firewall
table inet firewall {
...
}
delete table
will fail if the table does not exist, so we first create a blank table. Creating a table does not raise an error if the table already exists.