firewalld and common equivalents in iptables
As I increasingly use distributions that rely on firewalld over the old ways of manually configuring iptables this article notes down some common patterns encountered.
First and foremost firewalld provides a stateful firewall configuration by default and puts emphasis on restricting incoming connections/ports/services while outgoing traffic is always allowed.
Note that the default configuration will allow a limited number of services including SSH
in the public
zone. Different interfaces can be assigned to different zones (e.g. home
or trusted
)
also via NetworkManager configuration.
Blocking source IPs
firewall-cmd --zone=block --add-source=1.2.3.4 firewall-cmd --zone=block --add-source=1.2.3.0/24 # or firewall-cmd --zone=drop --add-source=1.2.3.4 firewall-cmd --zone=drop --add-source=1.2.3.0/24
⇔
Blocking a large list of IPs
This works like before with IP sets, except firewalld will also manage them for you.
However note that firewalld might choose to use an nftables set, so it won't be
visible to the ipset
command line tool.
firewall-cmd --permanent --new-ipset=asdf --type=hash:ip firewall-cmd --ipset=asdf --add-entry=223.223.0.0 firewall-cmd --zone=block --add-source=ipset:asdf
⇔
ipset create asdf hash:ip ipset add asdf 223.223.0.0 iptables -I INPUT -m set --match-set asdf src -j REJECT
Combinations with rich rules are also possible:
firewall-cmd --zone=public --add-rich-rule='rule source ipset="china" port port="22" protocol="tcp" drop'
⇔
Whitelisting source IPs
Allowing blanket access to all ports is easily done using the pre-existing
trusted
zone:
⇔
For fine-grained control a new zone can be created:
firewall-cmd --permanent --new-zone=mgmt-access firewall-cmd --permanent --zone=mgmt-access --add-service=ssh firewall-cmd --permanent --zone=mgmt-access --add-service=http firewall-cmd --permanent --zone=mgmt-access --add-source=3.4.5.6 firewall-cmd --permanent --zone=mgmt-access --add-source=6.6.6.0/24
⇔
NAT (masquerade) for outgoing traffic
firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="10.0.0.0/27" masquerade' firewall-cmd --zone=public --add-rich-rule='rule family="ipv6" source address="fd12:3456:789a::/48" masquerade'
⇔
Destination NAT
⇔
Filtering outgoing traffic?
The whole design of firewalld seems to be built around not allowing you do this.
Yet, as long as iptables-legacy
is installed it's still possible
to use the deprecated "direct rule" functionality for this.
firewall-cmd --direct --add-rule ipv4 filter OUTPUT 0 -p tcp -m tcp --dport 25 -j REJECT # the rule will literally show up in iptables as entered
⇔
Apparently policies are firewalld's replacement for direct rules but I have not figured those out yet.
By the way, direct rules are not bound to a particular zone and only show up in
firewall-cmd --direct --get-all-rules
.