Skip to content

This document is a WORK IN PROGRESS.
This is just a quick personal cheat sheet: treat its contents with caution!


firewalld

firewalld provides a dynamically managed firewall with support for network/firewall zones that define the trust level of network connections or interfaces. It has support for IPv4, IPv6 firewall settings, Ethernet bridges and IP sets. There is a separation of runtime and permanent configuration options (runtime mode vs permanent mode). It also provides an interface for services or applications to add firewall rules directly.

Reference(s)

Table of contents


Install

# emerge -a net-firewall/firewalld
# pacman -S firewalld

For Artix users

  • If using openrc:
    # pacman -S cronie firewalld-openrc
    
  • If using runit:
    # pacman -S cronie firewalld-runit
    
  • If using s6:
    # pacman -S cronie firewalld-s6
    

TODO

TODO

# apt install firewalld
# yum install firewalld
# dnf install firewalld

Use

WIP

Service

Zones

A network zone defines the level of trust for network connections. This is a one to many relation, which means that a connection can only be part of one zone, but a zone can be used for many network connections. These are the zones provided by firewalld, sorted according to the default trust level of the zones from untrusted to trusted:

  • drop: Any incoming network packets are dropped, there is no reply. Only outgoing network connections are possible.

  • block: Any incoming network connections are rejected with an ICMP-host-prohibited message for IPv4 and ICMP6-adm-prohibited for IPv6. Only network connections initiated within this system are possible.

  • public: For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.

  • external: For use on external networks with masquerading enabled especially for routers. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.

  • dmz: For computers in your demilitarized zone that are publicly-accessible with limited access to your internal network. Only selected incoming connections are accepted.

  • work: For use in work areas. You mostly trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.

  • home: For use in home areas. You mostly trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.

  • internal: For use on internal networks. You mostly trust the other computers on the networks to not harm your computer. Only selected incoming connections are accepted.

  • trusted: All network connections are accepted.

firewall-cmd

Runtime mode and permanent mode

Runtime mode

By default, whenever firewall-cmd is executed, the "runtime mode" is used. It means that if no --permanent option has been passed, then the executed command won't be permanent. I.e. settings changes will be gone after reload or restart, and accessed settings only tell about their current value (not about what the settings will be after a reload or restart).

Permanent mode

For firewall-cmd to access or change settings permanently, the --permanent option is needed and it must be the first option passed. Also, the --permanent option is not affecting runtime mode. I.e. permanent changes are only available after a reload or restart, and permanent accessed settings only tell about the value they will take after a reload or restart.

Example

When accessing/querying a setting, you will retrieve its runtime mode value by default.

E.g. you might want to know if the ssh port (port 22) is open or closed in the public zone, if so, you will run the following command: $ firewall-cmd --zone=public --query-service=ssh.

The result of this command will only inform you on the actual/currently running state of the ssh port in runtime mode (i.e. if the ssh port is currently closed or open).

The result will not tell if the ssh port will be closed or open after a restart or reload (in permanent mode).

Indeed, the ssh port might be currently open (so, the 22 port is open in the runtime mode), but simultaneously, the ssh port might scheduled to be closed after a restart or reload (so, the 22 port is closed in the permanent mode).

In order to know if the ssh port will be closed or open after a restart or reload you will run the following command: $ firewall-cmd --permanent --zone=public --query-service=ssh.

Runtime mode AND Permanent mode

  • In order to change a setting in runtime mode AND in permanent mode, the associated firewall-cmd command has to be executed twice: once with the --permanent option (for permanent mode) and once without it (for the runtime mode).
  • In order to access a setting in runtime mode AND in permanent mode, the associated firewall-cmd command also has to be executed twice: once with the --permanent option (for permanent mode) and once without it (for the runtime mode).

Status

  • Get the status of firewalld:

    $ firewall-cmd --state
    

  • Reload firewall without losing state information:

    # firewall-cmd --reload
    

  • Reload firewall completely (even netfilter kernel modules). This will most likely terminate active connections, because state information is lost. This option should only be used in case of severe firewall problems. For example if there are state information problems that no connection can be established with correct firewall rules (note that runtime changes applied via the direct interface are not affected and will therefore stay in place until the firewalld daemon is restarted completely):

    # firewall-cmd --complete-reload
    

  • Save active runtime configuration and overwrite permanent configuration with it. The way this is supposed to work is that when configuring firewalld you do runtime changes only and once you're happy with the configuration and you tested that it works the way you want, you save the configuration to disk:

    # firewall-cmd --runtime-to-permanent
    

  • Run checks on the permanent configuration:

     # firewall-cmd --check-config
    

Zones

  • Get a space separated list of all supported zones:

    $ firewall-cmd [--permanent] --get-zones
    

  • List everything added for or enabled in all zones:

    $ firewall-cmd [--permanent] --list-all-zones
    

  • Get the default zone set for network connections:

    $ firewall-cmd --get-default-zone
    

Warning

In all the bellow examples using the --zone option: if this option is is omitted, the default zone will be used.

  • Set the default zone, e.g. to public (⚠️ this is a runtime AND permanent change ⚠️):

    # firewall-cmd --set-default-zone=public
    

  • Print information about a specific zone (e.g. the public zone):

    $ firewall-cmd [--permanent] --info-zone=public
    

  • List everything added for or enabled in a specific zone (e.g. public):

    $ firewall-cmd [--permanent] --zone=public --list-all
    

  • Print currently active zones altogether with interfaces and sources used in these zones. Active zones are zones, that have a binding to an interface or source.

    $ firewall-cmd --get-active-zones
    

  • Create a new, permanent and empty zone:

    $ firewall-cmd --permanent --new-zone=zone_name
    

  • Delete an existing permanent zone:

    $ firewall-cmd --permanent --delete-zone=zone_name
    

  • Print the path of the configuration file of a zone:

    $ firewall-cmd --permanent --path-zone=zone_name
    

Interfaces

  • Get zone(s) related to an interface (e.g. the eth0 interface):

    $ firewall-cmd [--permanent] --get-zone-of-interface=eth0
    

  • List interfaces that are bound to zone (e.g. the public zone) as a space separated list:

    $ firewall-cmd [--permanent] --zone=public --list-interfaces
    

  • Bind an interface (e.g. the eth0 interface) to a zone (e.g. the public zone):

    $ firewall-cmd [--permanent] --zone=public --add-interface=eth0
    

  • Change the zone an interface belongs to (e.g. move the eth0 interface to the work zone):

    $ firewall-cmd [--permanent] --zone=work --change-interface=eth0
    

    Tip

    Permanently moving an interface into the block zone, will effectively block all communication associated to this interface. E.g. $ sudo firewall-cmd --permanent --zone=block --change-interface=eth0

  • Remove an interface from a zone (e.g. remove the eth0 interface from the block zone):

    $ firewall-cmd [--permanent] --zone=block --remove-interface=eth0
    

  • Query if an interface is in a zone (e.g. is eth0 in the public zone):

    $ firewall-cmd [--permanent] --zone=public --query-interface=eth0
    

Services

  • Get a list of all supported services:

    $ firewall-cmd [--permanent] --get-services
    

  • List services added for a specific zone as a space separated list (e.g. the public zone):

    $ firewall-cmd [--permanent] --zone=public --list-services
    

  • Add one or more service(s) for a zone, e.g. the http and https services in the public zone (this will result in opening the http and https ports - port 80 and 443 - in the public zone):

    $ firewall-cmd [--permanent] --zone=public --add-service=http -add-service=https
    

  • Disable a service in a zone, e.g. the https service in the public zone (this will result in closing the https port - port 443 - in the public zone):

    $ firewall-cmd [--permanent] --zone=public --remove-service=https
    

  • Query if a service is enabled in a zone:

    $ firewall-cmd [--permanent] --zone=public --query-service=https
    

  • Print information about a specific service, e.g. the http service:

    $ firewall-cmd [--permanent] --info-service=http
    

Protocols

Protocol

A protocol can be any communication protocol supported by the system. Please have a look at /etc/protocols for supported protocols.

  • List protocols added for zone (e.g. the public zone) as a space separated list:

    $ firewall-cmd [--permanent] --zone=public --list-protocols
    

  • Add/allow one or more protocols for a zone, e.g. add the TCP and the UDP protocol to the public zone:

    $ firewall-cmd [--permanent] --zone=public --add-protocol=tcp --add-protocol=udp
    

  • Remove the protocol from zone. If zone is omitted, default zone will be used. This option can be specified multiple times.

    $ firewall-cmd [--permanent] [--zone=zone] --remove-protocol=protocol
    

  • Return whether the protocol has been added for zone. If zone is omitted, default zone will be used. Returns 0 if true, 1 otherwise.

    $ firewall-cmd [--permanent] [--zone=zone] --query-protocol=protocol
    

Ports

  • List ports added for a zone (e.g. the public zone) as a space separated list:

    $ firewall-cmd [--permanent] --zone=public --list-ports
    

  • Enable specific port/protocol combination(s) in a zone, e.g. enable port 123123 for TCP communication and 321321 for UDP communication in the public zone:

    $ firewall-cmd [--permanent] --zone=public --add-port=123123/tcp --add-port=321321/udp
    

  • Disable specific port/protocol combination(s) in a zone, e.g. disable port 123123 for TCP communication and 321321 for UDP communication in the public zone:

    $ firewall-cmd [--permanent] --zone=public --remove-port=123123/tcp --remove-port=321321/udp
    

  • Query if a port/protocol combination is enabled in a zone, e.g. is the port 123123 for TCP communication enabled in the public zone:

    $ firewall-cmd [--permanent] --zone=public --query-port=123123/tcp
    

ICMP

TODO

Port forwarding and port mapping

TODO

Reference(s)

To forward inbound network packets from one port to an alternative port or address, first enable IP address masquerading for a zone, for example external, by entering the following command:

$ sudo firewall-cmd --zone=external --add-masquerade
    > success
$ sudo firewall-cmd --zone=external --query-masquerade
    > yes

Now, let's say you want to forward your local TCP port 127.0.0.1:102 to a remote TCP port, e.g. 192.168.1.1:10102, then you could do it like so:

$ sudo firewall-cmd --zone=external --add-forward-port=port=102:proto=tcp:toport=10102:toaddr=192.168.1.1
    > success
$ firewall-cmd --zone=external --query-forward-port=port=102:proto=tcp:toport=10102:toaddr=192.168.1.1
    > yes

Similar forwarding can also be done with ssh, e.g.:

$ ssh -L 20999:10.10.1.1:10999 123.1.2.3 -l username -N
Now 10.10.1.1:10999 is redirected to 127.0.0.1:20999

See ssh tunneling for more details.

Masquerading

TODO

Rich rules

TODO

Sources

TODO

IPSet

TODO

Lockdown

TODO

Direct

TODO

Panic

  • Enable panic mode to block all network traffic in case of emergency:

    # firewall-cmd --panic-on
    

  • Disable panic mode:

    # firewall-cmd --panic-off
    

  • Query panic mode

    $ firewall-cmd --query-panic && echo "On" || echo "Off"
    


If this cheat sheet has been useful to you, then please consider leaving a star here.