DFW v1.2 reintroduced an iptables-based firewall-backend (v1.0 initially dropped iptables-support), specifically the iptables-restore
backend that was made available in v0.4+.
Migrating your host from iptables to nftables is described in the nftables wiki. The rough outline is as follows:
- Export your iptables rules (
iptables-save
). - Translate them into nftables rules (
iptables-restore-translate
). - Import them into nftables (
nft -f
).
One point to add to this: most distributions include the file /etc/nftables.conf
as part of their nftables userspace package, which will be automatically loaded on system-boot through the systemd-service nftables
.
This is an easy way to add your pre-existing (or new) rules to the default nftables-chains and have them be loaded whenever you boot.
For more general information on nftables, see the following resources:
The switch to nftables required changes to the configuration-structure of DFW. Some changes are new, others are breaking and require you to adapt your configuration, and some are backwards compatible but should be applied.
Short summary, here is what you have to do to update your configuration:
- Add/configure the
backend_defaults.custom_tables
setting. - Replace the
initialization.v4
andinitialization.v6
sections by thebackend_defaults.initialization.rules
key, changing the rules to be nft-compatible. - Change any
filter
-fields in your container-to-container, container-to-wider-world, or container-to-host rules tomatches
and update it to be nft-compatible.
For full details see the following sections.
-
The key
custom_tables
was added to thebackend_defaults
section.For DFW to support custom nftables tables to exist in parallel, it needs to hook into the chains in these pre-existing tables. The
custom_tables
key is used for the user to provide the name(s) and chains of their pre-existing tables.(One of the main advantages of nftables is that multiple tables can exist, which allows DFW to manage its rules in a completely separate namespace from the users rules. For this to fully work the mentioned hooks are necessary.)
On a default nftables installation (verified on various Linux distributions) the
filter
table will be created, containing theinput
andforward
chains. The following configuration would be valid for this setup:[defaults] custom_tables = { name = "filter", chains = ["input", "forward"] }
-
The
initialization
section has moved to thebackend_defaults
section and no longer has thev4
andv6
subsections.Not only are they obsolete through the
inet
-tables supported by nftables, they were allowed to contain iptables-compatible rules which are strictly incompatible with nftables commands.The sections were replaced by the
rules
key, a list of commands that are executed usingnft
.Example, before:
[initialization] [initialization.v4] filter = [ "-A INPUT -p tcp --dport 22 -j ACCEPT" ] [initialization.v6] filter = [ "-A INPUT -p tcp --dport 22 -j ACCEPT" ]
After:
[backend_defaults.initialization] rules = [ "add rule inet filter input tcp dport 22 accept" ]
-
The container-to-container, container-to-wider-world, and container-to-host rules no longer have the
filter
field (now calledmatches
).The
filter
field was used to further restrict the rules, e.g. to restrict container-to-container communication to certain ports. Thefilter
argument contained iptables-compatible rule-statements, which are strictly incompatible with nftables.For nftables the field is called
matches
and expects valid nft-statements.Example, before:
[[container_to_container.rules]] network = "reverseproxy_network" src_container = "my_reverseproxy" dst_container = "my_webserver" filter = "-p tcp --dport 8080" action = "ACCEPT"
After:
[[container_to_container.rules]] network = "reverseproxy_network" src_container = "my_reverseproxy" dst_container = "my_webserver" matches = "tcp dport 8080" verdict = "accept"
-
The container-to-container, container-to-wider-world, and container-to-host rules renamed the
action
field toverdict
.nftables no longer uses the word "action" to describe the final result that will be applied to a network-packet, but rather "verdict". Further the representation of the verdict itself is now in all lowercase, rather than all uppercase (e.g.
ACCEPT
->accept
).DFW follows both those changes, although it is fully backwards-compatible to both the key used and values provided. This means that your rules with
action = "ACCEPT"
continue to work the same way, even thoughverdict = "accept"
is the new configuration.Example, before:
[[container_to_container.rules]] network = "common_network" src_container = "container_a" dst_container = "container_b" action = "ACCEPT"
After:
[[container_to_container.rules]] network = "common_network" src_container = "container_a" dst_container = "container_b" verdict = "accept"
-
The container-to-container, container-to-wider-world, and container-to-host
default_policy
-field values should now be in lowercase.nftables no longer uses the uppercase variants of chain-verdicts, they are now all lowercase (e.g.
ACCEPT
->accept
).DFW follows this change, although it is fully backwards-compatible to the value provided. This means that
default_policy = "ACCEPT"
continues to work the same way, even thoughdefault_policy = "accept"
is the new configuration.Example, before:
[container_to_container] default_policy = "ACCEPT"
After:
[container_to_container] default_policy = "accept"
You need to inform DFW that you want to use the iptables-based firewall-backend.
To do this, provide the --firewall-backend iptables
parameter through the command-line interface.
If you are using Docker, it could look like this:
docker run -d \
--name=dfw \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v /path/to/your/config:/config \
--net host --cap-add=NET_ADMIN \
pitkley/dfw:1.2.0 --firewall-backend iptables --config-path /config
If you have previously used the --iptables-backend
parameter you have to remove it, it is no longer used/valid.
(DFW v1.2 uses the iptables-restore
implementation internally to support iptables.)
Some changes to the configuration are new, others are breaking and require you to adapt your configuration, and some are backwards compatible but should be applied.
Short summary, here is what you have to do to update your configuration:
- Replace the
initialization.v4
andinitialization.v6
keys bybackend_defaults.initialization.v4
andbackend_defaults.initialization.v6
respectively. - Change any
filter
-fields in your container-to-container, container-to-wider-world, or container-to-host rules tomatches
.
For full details see the following sections.
-
The
initialization
section has been moved to thebackend_defaults
section.This was required to support multiple backends again.
Example, before:
[initialization] [initialization.v4] filter = [ "-A INPUT -p tcp --dport 22 -j ACCEPT" ] [initialization.v6] filter = [ "-A INPUT -p tcp --dport 22 -j ACCEPT" ]
After:
[backend_defaults.initialization] [backend_defaults.initialization.v4] filter = [ "-A INPUT -p tcp --dport 22 -j ACCEPT" ] [backend_defaults.initialization.v6] filter = [ "-A INPUT -p tcp --dport 22 -j ACCEPT" ]
-
The
filter
field in container-to-container, container-to-wider-world, and container-to-host rules has been renamed tomatches
.This field is used to further restrict the rules, e.g. to restrict container-to-container communication to certain ports.
Example, before:
[[container_to_container.rules]] network = "reverseproxy_network" src_container = "my_reverseproxy" dst_container = "my_webserver" filter = "-p tcp --dport 8080" action = "ACCEPT"
After:
[[container_to_container.rules]] network = "reverseproxy_network" src_container = "my_reverseproxy" dst_container = "my_webserver" matches = "-p tcp --dport 8080" verdict = "accept"
-
The container-to-container, container-to-wider-world, and container-to-host rules renamed the
action
field toverdict
.DFW no longer uses the word "action" to describe the final result that will be applied to a network-packet, but rather "verdict". Further the representation of the verdict itself is now in all lowercase, rather than all uppercase (e.g.
ACCEPT
->accept
).These changes are fully backwards-compatible. This means that your rules with
action = "ACCEPT"
continue to work the same way, even thoughverdict = "accept"
is the new configuration.Example, before:
[[container_to_container.rules]] network = "common_network" src_container = "container_a" dst_container = "container_b" action = "ACCEPT"
After:
[[container_to_container.rules]] network = "common_network" src_container = "container_a" dst_container = "container_b" verdict = "accept"
-
The container-to-container, container-to-wider-world, and container-to-host
default_policy
-field values should now be in lowercase.nftables no longer uses the uppercase variants of chain-verdicts, they are now all lowercase (e.g.
ACCEPT
->accept
).DFW follows this change, although it is fully backwards-compatible to the value provided. This means that
default_policy = "ACCEPT"
continues to work the same way, even thoughdefault_policy = "accept"
is the new configuration.Example, before:
[container_to_container] default_policy = "ACCEPT"
After:
[container_to_container] default_policy = "accept"