Firewalls
Table of Contents
firewall integration in Cisco ACI#
(do a blog search for “service_insertion”)
firewalls in Linux#
The default host-based firewall in RHEL allows all outgoing connections and blocks all incoming ones, except those explicitely permitted.
The firewall daemon is called firewalld. To interact with it, use the firewall-cmd tool. The firewalld daemon translates the instructions of firewall-cmd into policies that use the syntax of the kernel’s netfilter and nftables.
firewall rules#
A rule dictates that a service is allowed to be accessed by an inbound connection. A firewalld service is added with firewall-cmd --add-service or removed with firewall-cmd --remove-service.
firewalld models#
There is no static file that describes the current active firewall rules. This is because firewalld has two internal representations, or models:
- the runtime in-memory model: this model describes what firewalld considers to be active in the present moment. It is built for the first time from the permanent in-memory model files: /etc/firewalld/zones/ (the file that corresponds to whatever default zone is configured) and etc/firewalld/services/ (any custom service definition for any services that are referenced by name in the zone file). At system reboot, firewalld.service restart or
firewall-cmd --reload, the runtime in-memory model is built using the same files again. - the permanent in-memory model: this model describes what firewalld expects to see at system reboot, firewalld.service reload or
firewall-cmd --reload. Including the option--permanentin thefirewall-cmdcommand triggers a serialization in the XML files mentioned above (i.e. disk write operations).
Services#
A firewalld service is and object that is declared by an XML file that contains ports and transport protocols data. All firewalld services are located at /usr/lib/firewalld/services/. But this does not imply that they are enabled for inbound connections. They are definitions that are available for all zones of the firewalld. What enables or disables a firewalld services is an added or removed rule.
user1@rhel10-vm2:~$ ls /usr/lib/firewalld/services/
0-AD.xml jenkins.xml RH-Satellite-6-capsule.xml
afp.xml kadmin.xml RH-Satellite-6.xml
alvr.xml kdeconnect.xml rootd.xml
amanda-client.xml kerberos.xml rpc-bind.xml
amanda-k5-client.xml kibana.xml rquotad.xml
amqps.xml klogin.xml rsh.xml
amqp.xml kpasswd.xml rsyncd.xml
anno-1602.xml kprop.xml rtsp.xml
anno-1800.xml kshell.xml salt-master.xml
apcupsd.xml kube-apiserver.xml samba-client.xml
aseqnet.xml kube-api.xml samba-dc.xml
audit.xml kube-controller-manager-secure.xml samba.xml
ausweisapp2.xml kube-controller-manager.xml sane.xml
bacula-client.xml kube-control-plane-secure.xml settlers-history-collection.xml
bacula.xml kube-control-plane.xml sips.xml
<---- output omitted ---->
Example of a service file:
user1@rhel10-vm2:~$ cat /usr/lib/firewalld/services/https.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>Secure WWW (HTTPS)</short>
<description>HTTPS is a modified HTTP used to serve Web pages when security is important. Examples are sites that require logins like stores or web mail. This option is not required for viewing pages locally or developing Web pages. You need the httpd package installed for this option to be useful.</description>
<port protocol="tcp" port="443"/>
</service>
user1@rhel10-vm2:~$
There is also the /etc/firewalld/services tree path. This is the directory to place user-defined services (user-defined XML files) in, when I want to shadow a particular firewalld service in /usr/lib/firewalld/services/. Example, I create a ssh.xml service file and place it in /etc/firewalld/services/ to shadow the /usr/lib/firewalld/services/ssh.xml file.
user1@rhel10-vm2:~$ sudo ls /etc/firewalld/services/
[sudo] password for user1:
user1@rhel10-vm2:~$
confusion risk 1#
The file /etc/services contains a definition of services that look similar to firewalld service definition files. But /etc/services serves general use; It defines the services that are called out by name by certain applications. #QA when would firewalld use the /etc/services/?
# /etc/services:
# $Id: services,v 1.49 2017/08/18 12:43:23 ovasik Exp $
#
# Network services, Internet style
# IANA services version: last updated 2021-01-19
#
# Note that it is presently the policy of IANA to assign a single well-known
# port number for both TCP and UDP; hence, most entries here have two entries
# even if the protocol doesn't support UDP operations.
# Updated from RFC 1700, ``Assigned Numbers'' (October 1994). Not all ports
# are included, only the more common ones.
#
# The latest IANA port assignments can be gotten from
# http://www.iana.org/assignments/port-numbers
# The Well Known Ports are those from 0 through 1023.
# The Registered Ports are those from 1024 through 49151
# The Dynamic and/or Private Ports are those from 49152 through 65535
#
# Each line describes one service, and is of the form:
#
# service-name port/protocol [aliases ...] [# comment]
tcpmux 1/tcp # TCP port service multiplexer
tcpmux 1/udp # TCP port service multiplexer
rje 5/tcp # Remote Job Entry
rje 5/udp # Remote Job Entry
echo 7/tcp
echo 7/udp
discard 9/tcp sink null
discard 9/udp sink null
systat 11/tcp users
systat 11/udp users
daytime 13/tcp
<---- output omitted ---->
operations on firewalld services#
A firewalld service is allowed or denied in either the runtime model (the ruleset in memory) aka the in-memory model, or in the permanent in-memory model.
List open services:
user1@rhel10-vm2:~$ sudo firewall-cmd --list-services
[sudo] password for user1:
cockpit dhcpv6-client ssh
user1@rhel10-vm2:~$
Remove a service from the runtime, i.e. after a system reboot the rule is deleted. I removed the SSH service for instance:
user1@rhel10-vm2:~$ sudo firewall-cmd --remove-service=ssh
success
user1@rhel10-vm2:~$ sudo firewall-cmd --list-services
cockpit dhcpv6-client
user1@rhel10-vm2:~$
and proved that the machine can no longer be accessed with SSH:
user1@rhel10-vm1:~$ ping 192.168.122.6
PING 192.168.122.6 (192.168.122.6) 56(84) bytes of data.
64 bytes from 192.168.122.6: icmp_seq=1 ttl=64 time=0.432 ms
64 bytes from 192.168.122.6: icmp_seq=2 ttl=64 time=0.518 ms
^C
--- 192.168.122.6 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1018ms
rtt min/avg/max/mdev = 0.432/0.475/0.518/0.043 ms
user1@rhel10-vm1:~$
user1@rhel10-vm1:~$ ssh user1@192.168.122.6
ssh: connect to host 192.168.122.6 port 22: No route to host
user1@rhel10-vm1:~$
Adding SSH again to the list of open services:
user1@rhel10-vm2:~$ sudo firewall-cmd --add-service=ssh
success
user1@rhel10-vm2:~$
and retrying access via SSH:
user1@rhel10-vm1:~$ ssh user1@192.168.122.6
The authenticity of host '192.168.122.6 (192.168.122.6)' can't be established.
ED25519 key fingerprint is SHA256:vHOUVnOMr0tQamHlOmyd1hkVUXK8yZLUfSkiUHipjEw.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
zones#
A firewalld zone contains the services that are allowed in inbound connections. The services are referenced by name. The service definition is, as explained above, in /usr/lib/firewalld/services/ and /etc/firewalld/services/ for system-based and user-based files respectively.
List the system-defined zones:
user1@rhel10-vm2:~$ ls /usr/lib/firewalld/zones/
block.xml drop.xml home.xml nm-shared.xml trusted.xml
dmz.xml external.xml internal.xml public.xml work.xml
user1@rhel10-vm2:~$ ls -l /usr/lib/firewalld/zones/
total 40
-rw-r--r--. 1 root root 312 Jun 10 2025 block.xml
-rw-r--r--. 1 root root 306 Jun 10 2025 dmz.xml
-rw-r--r--. 1 root root 304 Jun 10 2025 drop.xml
-rw-r--r--. 1 root root 317 Jun 10 2025 external.xml
-rw-r--r--. 1 root root 410 Jun 10 2025 home.xml
-rw-r--r--. 1 root root 425 Jun 10 2025 internal.xml
-rw-r--r--. 1 root root 729 Feb 28 2025 nm-shared.xml
-rw-r--r--. 1 root root 356 Jun 10 2025 public.xml
-rw-r--r--. 1 root root 175 Jun 10 2025 trusted.xml
-rw-r--r--. 1 root root 352 Jun 10 2025 work.xml
user1@rhel10-vm2:~$
List the user-defined zones:
user1@rhel10-vm2:~$ ls -l /etc/firewalld/zones
ls: cannot access '/etc/firewalld/zones': Permission denied
user1@rhel10-vm2:~$ ls -l /etc/firewalld/
ls: cannot open directory '/etc/firewalld/': Permission denied
user1@rhel10-vm2:~$ sudo ls -l /etc/firewalld/zones/
[sudo] password for user1:
total 8
-rw-r--r--. 1 root root 356 Nov 15 2025 public.xml
-rw-r--r--. 1 root root 356 Nov 15 2025 public.xml.old
user1@rhel10-vm2:~$
Get the defaut zone ( #QA what is the default zone for?) and change its value:
user1@rhel10-vm2:~$ firewall-cmd --get-default-zone
public
user1@rhel10-vm2:~$ firewall-cmd --list-zones
usage: 'firewall-cmd --help' for usage information or see firewall-cmd(1) man page
firewall-cmd: error: unrecognized arguments: --list-zones
user1@rhel10-vm2:~$ man firewall-cmd
user1@rhel10-vm2:~$ firewall-cmd --get-zones
block dmz drop external home internal nm-shared public trusted work
user1@rhel10-vm2:~$ sudo firewall-cmd --set-default-zone drop
success
user1@rhel10-vm2:~$ firewall-cmd --get-default-zone
drop
user1@rhel10-vm2:~$
To avoid ambiguity, I dedide to always include the zone name in firewall-cmd command lines. I do not want to rely on convenience and risk mixing rules between zones.