PolarSPARC

Introduction to Linux firewalld


Bhaskar S 01/02/2020


Overview

A Firewall is a layer of defense with a set of rules that either allow or deny the passage of traffic through the network system. Both inbound and outbound IP packets are intercepted and inspected by the firewall (also referred to as a Packet Filter) and validated against the rules to either permit or reject the further flow of the packets.

In Linux, the IP packet filtering capability is implemented via the kernel-space Netfilter module.

The user-space iptables command-line utility allows one to configure and manage the packet filtering rules in the kernel-space netfilter module. Many consider the syntax and usage of iptables to be a bit obscure. There was a need for a higher-level tool that was user-friendly and easier to use - this is where firewalld comes into play.

firewalld consists of three components:

Both the command-line utility firewall-cmd and the GUI utility firewall-config interact with the daemon firewalld via the D-BUS (short for Desktop BUS, an inter-process communication channel for programs to communicate with each other on the Linux machine).

The following Figure-1 illustrates the high-level architecture view of firewalld:

Firewalld
Figure-1

Setup

To get our hands dirty with firewalld, we will setup a virtual machine on VirtualBox 6.x running Fedora 31 Workstation. Once the Fedora virtual machine boots-up, login and open a Terminal window.

Ensure the service firewalld is up and running by executing the following command:

$ systemctl status firewalld

The following would be a typical output:

Output.1

* firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2019-12-31 12:20:38 EST; 5min ago
     Docs: man:firewalld(1)
 Main PID: 736 (firewalld)
    Tasks: 2 (limit: 4680)
   Memory: 41.5M
      CPU: 1.003s
   CGroup: /system.slice/firewalld.service
           |--736 /usr/bin/python3 /usr/sbin/firewalld --nofork --nopid

Dec 31 12:20:36 fedora-vm-1 systemd[1]: Starting firewalld - dynamic firewall daemon...
Dec 31 12:20:38 fedora-vm-1 systemd[1]: Started firewalld - dynamic firewall daemon.

Next, we will install the nginx webserver by executing the following command:

$ sudo dnf install nginx

The following would be a typical output:

Output.2

Last metadata expiration check: 2:36:20 ago on Tue 31 Dec 2019 21:11:54 PM EST.
Dependencies resolved.
====================================================================================================================================
 Package                             Architecture              Version                              Repository                 Size
====================================================================================================================================
Installing:
 nginx                               x86_64                    1:1.16.1-1.fc31                      fedora                    564 k
Installing dependencies:
 gperftools-libs                     x86_64                    2.7-6.fc31                           fedora                    322 k
 nginx-filesystem                    noarch                    1:1.16.1-1.fc31                      fedora                     10 k
 nginx-mimetypes                     noarch                    2.1.48-6.fc31                        fedora                     19 k

Transaction Summary
====================================================================================================================================
Install  4 Packages

Total download size: 915 k
Installed size: 3.5 M
Is this ok [y/N]: y
Downloading Packages:
(1/4): nginx-filesystem-1.16.1-1.fc31.noarch.rpm                                                    149 kB/s |  10 kB     00:00    
(2/4): nginx-mimetypes-2.1.48-6.fc31.noarch.rpm                                                     646 kB/s |  19 kB     00:00    
(3/4): gperftools-libs-2.7-6.fc31.x86_64.rpm                                                        1.4 MB/s | 322 kB     00:00    
(4/4): nginx-1.16.1-1.fc31.x86_64.rpm                                                               1.8 MB/s | 564 kB     00:00    
------------------------------------------------------------------------------------------------------------------------------------
Total                                                                                               1.6 MB/s | 915 kB     00:00     
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                                                                            1/1 
  Running scriptlet: nginx-filesystem-1:1.16.1-1.fc31.noarch                                                                    1/4 
  Installing       : nginx-filesystem-1:1.16.1-1.fc31.noarch                                                                    1/4 
  Installing       : nginx-mimetypes-2.1.48-6.fc31.noarch                                                                       2/4 
  Installing       : gperftools-libs-2.7-6.fc31.x86_64                                                                          3/4 
  Installing       : nginx-1:1.16.1-1.fc31.x86_64                                                                               4/4 
  Running scriptlet: nginx-1:1.16.1-1.fc31.x86_64                                                                               4/4 
  Verifying        : gperftools-libs-2.7-6.fc31.x86_64                                                                          1/4 
  Verifying        : nginx-1:1.16.1-1.fc31.x86_64                                                                               2/4 
  Verifying        : nginx-filesystem-1:1.16.1-1.fc31.noarch                                                                    3/4 
  Verifying        : nginx-mimetypes-2.1.48-6.fc31.noarch                                                                       4/4 

Installed:
  nginx-1:1.16.1-1.fc31.x86_64               gperftools-libs-2.7-6.fc31.x86_64       nginx-filesystem-1:1.16.1-1.fc31.noarch      
  nginx-mimetypes-2.1.48-6.fc31.noarch      

Complete!

Enable the service nginx by executing the following command:

$ sudo systemctl enable nginx

The following would be a typical output:

Output.3

Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.

Start the service nginx by executing the following command:

$ sudo systemctl start nginx

Ensure the service nginx is up and running by executing the following command:

$ systemctl status nginx

The following would be a typical output:

Output.4

* nginx.service - The nginx HTTP and reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
   Active: active (running) since Tue 2019-12-31 21:13:54 EST; 15s ago
  Process: 9913 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
  Process: 9914 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
  Process: 9915 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
 Main PID: 9916 (nginx)
    Tasks: 2 (limit: 4680)
   Memory: 2.5M
      CPU: 35ms
   CGroup: /system.slice/nginx.service
           |--9916 nginx: master process /usr/sbin/nginx
           |--9917 nginx: worker process

Dec 31 21:13:54 fedora-vm-1 systemd[1]: Starting The nginx HTTP and reverse proxy server...
Dec 31 21:13:54 fedora-vm-1 nginx[9914]: nginx: [warn] could not build optimal types_hash, you should increase either types_hash_ma>
Dec 31 21:13:54 fedora-vm-1 nginx[9914]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
Dec 31 21:13:54 fedora-vm-1 nginx[9914]: nginx: configuration file /etc/nginx/nginx.conf test is successful
Dec 31 21:13:54 fedora-vm-1 nginx[9915]: nginx: [warn] could not build optimal types_hash, you should increase either types_hash_ma>
Dec 31 21:13:54 fedora-vm-1 systemd[1]: nginx.service: Failed to parse PID from file /run/nginx.pid: Invalid argument
Dec 31 21:13:54 fedora-vm-1 systemd[1]: Started The nginx HTTP and reverse proxy server.

Hands-on with firewalld

The main configuration file firewalld.conf for firewalld is located in the directory /etc/firewalld.

firewalld uses the following two constructs for defining the filtering rules:

So, how does the firewalld really work ???

At a very high level, when a network packet arrives in the machine, firewalld checks the source address to determine the zone it belongs to. If found, the packet is filtered by the rules of the determined zone. If not found, firewalld checks to determine the zone based on the network interface through which the packet arrived. If found, the packet is filtered by the rules of the determined zone. Again, if not found, the packet is filtered by the rules of the default zone.

To list all the system default service(s), execute the following command:

$ firewall-cmd --get-services

The following would be a typical output:

Output.5

RH-Satellite-6 amanda-client amanda-k5-client amqp amqps apcupsd audit bacula bacula-client bb bgp bitcoin bitcoin-rpc bitcoin-testnet bitcoin-testnet-rpc bittorrent-lsd ceph ceph-mon cfengine cockpit condor-collector ctdb dhcp dhcpv6 dhcpv6-client distcc dns dns-over-tls docker-registry docker-swarm dropbox-lansync elasticsearch etcd-client etcd-server finger freeipa-4 freeipa-ldap freeipa-ldaps freeipa-replication freeipa-trust ftp ganglia-client ganglia-master git grafana gre high-availability http https imap imaps ipp ipp-client ipsec irc ircs iscsi-target isns jenkins kadmin kdeconnect kerberos kibana klogin kpasswd kprop kshell ldap ldaps libvirt libvirt-tls lightning-network llmnr managesieve matrix mdns memcache minidlna mongodb mosh mountd mqtt mqtt-tls ms-wbt mssql murmur mysql nfs nfs3 nmea-0183 nrpe ntp nut openvpn ovirt-imageio ovirt-storageconsole ovirt-vmconsole plex pmcd pmproxy pmwebapi pmwebapis pop3 pop3s postgresql privoxy prometheus proxy-dhcp ptp pulseaudio puppetmaster quassel radius rdp redis redis-sentinel rpc-bind rsh rsyncd rtsp salt-master samba samba-client samba-dc sane sip sips slp smtp smtp-submission smtps snmp snmptrap spideroak-lansync spotify-sync squid ssdp ssh steam-streaming svdrp svn syncthing syncthing-gui synergy syslog syslog-tls telnet tentacle tftp tftp-client tile38 tinc tor-socks transmission-client upnp-client vdsm vnc-server wbem-http wbem-https wsman wsmans xdmcp xmpp-bosh xmpp-client xmpp-local xmpp-server zabbix-agent zabbix-server

The Output.5 above lists all the pre-defined system service(s) whose definitions are located in the directory /usr/lib/firewalld/services.

The following table describes some of the pre-defined system services(s) listed in Output.5 above:

Service Description
dhcpv6-client allow traffic for DHCPv6 client service on port 546 (udp)
ipp-client allow traffic for local printing server service on port 631 (udp)
mdns allow traffic for Multicast DNS local link service on port 5353 (udp)
samba-client allow traffic for local Windows files and printer sharing service on port 137 (udp) and 138 (udp)
ssh allow traffic for local SSH Server service on port 22 (tcp)

For example, to display the service definition for ssh, execute the following command:

$ cat /usr/lib/firewalld/services/ssh.xml

The following would be a typical output:

Output.6

<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>SSH</short>
  <description>Secure Shell (SSH) is a protocol for logging into and executing commands on remote machines. It provides secure encrypted communications. If you plan on accessing your machine remotely via SSH over a firewalled interface, enable this option. You need the openssh-server package installed for this option to be useful.</description>
  <port protocol="tcp" port="22"/>
</service>

The Output.6 above defines the ssh network service that uses the tcp protocol on port 22.

Let us look at another example. Display the service definition for dns by executing the following command:

$ cat /usr/lib/firewalld/services/dns.xml

The following would be a typical output:

Output.7

<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>DNS</short>
  <description>The Domain Name System (DNS) is used to provide and request host and domain names. Enable this option, if you plan to provide a domain name service (e.g. with bind).</description>
  <port protocol="tcp" port="53"/>
  <port protocol="udp" port="53"/>
</service>

From the Output.7 above, we see multiple definitions for protocol and port groupings (not just one).

To list all the the system default zone(s), execute the following command:

$ firewall-cmd --get-zones

The following would be a typical output:

Output.8

FedoraServer FedoraWorkstation block dmz drop external home internal libvirt public trusted work

The Output.8 above lists all the pre-defined system zone(s) whose definitions are located in the directory /usr/lib/firewalld/zones.

The following table describes some of the pre-defined system zone(s) listed in Output.5 above:

Zone Description
trusted allows all incoming traffic
home customized for home network. It allows incoming traffic from the following services: ssh, mdns, ipp-client, samba-client and dhcpv6-client
internal similar to home zone but it is customized for internal network. It allows incoming traffic from the following services: ssh, mdns, ipp-client, samba-client and dhcpv6-client
work customized for work network. It allows incoming traffic from the following services: ssh, ipp-client and dhcpv6-client
public customized for public network. It allows incoming traffic from the following services: ssh and dhcpv6-client
external customized for masquerading. It allows incoming traffic from ssh service only
dmz customized to limit the access to internal network. It allows incoming traffic from ssh service only
block rejects all incoming traffic with “icmp-host-prohibited” message for IPv4 and "icmp6-adm-prohibited" for IPv6. Network connections initiated from within the machine are allowed
drop rejects all incoming traffic without sending any error message. Outgoing network connections are allowed

One of the zone(s) is designated as the default active zone.

To find the default zone for the system, execute the following command:

$ firewall-cmd --get-default-zone

The following would be a typical output:

Output.9

FedoraWorkstation

To display the zone definition for FedoraWorkstation, execute the following command:

$ cat /usr/lib/firewalld/zones/FedoraWorkstation.xml

The following would be a typical output:

Output.10

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Fedora Workstation</short>
  <description>Unsolicited incoming network packets are rejected from port 1 to 1024, except for select network services. Incoming packets that are related to outgoing network connections are accepted. Outgoing network connections are allowed.</description>
  <service name="dhcpv6-client"/>
  <service name="ssh"/>
  <service name="samba-client"/>
  <port protocol="udp" port="1025-65535"/>
  <port protocol="tcp" port="1025-65535"/>
</zone>

From the Output.10 above, we see the FedoraWorkstation system zone allows traffic for the system service(s) such as dhcpv6-client, ssh, samba-client, OR any tcp / udp traffic for ports in the range 1025 through 65535.

In other words, each of the pre-defined zone(s) allow only a set of pre-defined service(s) to pass through while denying others.

Each network interface is associated with a zone so one can control what network traffic would be allowed for that interface.

To find the network interface(s) associated with the different active zone for the system, execute the following command:

$ firewall-cmd --get-active-zones

The following would be a typical output:

Output.11

FedoraWorkstation
  interfaces: enp0s3
libvirt
  interfaces: virbr0

To display all the pertinent information for FedoraWorkstation in one go, the current default active zone, execute the following command:

$ firewall-cmd --list-all --zone="FedoraWorkstation"

The following would be a typical output:

Output.12

FedoraWorkstation (active)
  target: default
  icmp-block-inversion: no
  interfaces: enp0s3
  sources: 
  services: dhcpv6-client mdns samba-client ssh
  ports: 1025-65535/udp 1025-65535/tcp
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

To display all the permitted service(s) on the machine, execute the following command:

$ firewall-cmd --list-services

The following would be a typical output:

Output.13

dhcpv6-client mdns samba-client ssh

To display all the port(s) through which traffic is permitted on the machine, execute the following command:

$ firewall-cmd --list-ports

The following would be a typical output:

Output.14

1025-65535/udp 1025-65535/tcp

From both the outputs Output.13 and Output.14, we see neither the service called http nor the tcp port 80 enabled. This means access to the nginx webserver will be DENIED !!!

To determine the ip address for the network interface enp0s3 of the virtual machine, execute the following command:

$ ip addr show enp0s3

The following would be a typical output:

Output.15

2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:ba:dc:6c brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.237/24 brd 192.168.1.255 scope global dynamic noprefixroute enp0s3
       valid_lft 65094sec preferred_lft 65094sec
    inet6 fe80::7ccc:eac8:6297:cfef/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

From the Output.15 above, we see the ip address as 192.168.1.237.

To access the nginx webserver running on the address 192.168.1.237, execute the following command:

$ curl http://192.168.1.237

The following would be a typical output:

Output.16

curl: (7) Failed to connect to 192.168.1.237 port 80: No route to host

From the Output.16 above, we see access to the nginx webserver is DENIED !!!

Let us display the service definition for http by executing the following command:

$ cat /usr/lib/firewalld/services/http.xml

The following would be a typical output:

Output.17

<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>WWW (HTTP)</short>
  <description>HTTP is the protocol used to serve Web pages. If you plan to make your Web server publicly available, enable this option. This option is not required for viewing pages locally or developing Web pages.</description>
  <port protocol="tcp" port="80"/>
</service>

To enable the service for http on the active zone (FedoraWorkstation), execute the following command:

$ sudo firewall-cmd --zone=FedoraWorkstation --add-service=http

The following would be a typical output:

Output.18

success

Once again, to access the nginx webserver running on the address 192.168.1.237 , execute the following command:

$ curl http://192.168.1.237

The following would be a typical output:

Output.19

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <title>Test Page for the HTTP Server on Fedora</title>
  <meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
  <style type="text/css">
    /*<![CDATA[*/
    body {
      background-color: #fff;
      color: #000;
      font-size: 0.9em;
      font-family: sans-serif,helvetica;
      margin: 0;
      padding: 0;
    }
    :link {
      color: #c00;
    }
    :visited {
      color: #c00;
    }
    a:hover {
      color: #f50;
    }
    h1 {
      text-align: center;
      margin: 0;
      padding: 0.6em 2em 0.4em;
      background-color: #22437f;
      color: #fff;
      font-weight: normal;
      font-size: 1.75em;
      border-bottom: 2px solid #000;
    }
    h1 strong {
      font-weight: bold;
    }
    h2 {
      font-size: 1.1em;
      font-weight: bold;
    }
    hr {
      display: none;
    }
    .content {
      padding: 1em 5em;
    }
    .content-columns {
      /* Setting relative positioning allows for absolute positioning for sub-classes */
      position: relative;
      padding-top: 1em;
    }
    .content-column-left {
      /* Value for IE/Win; will be overwritten for other browsers */
      width: 47%;
      padding-right: 3%;
      float: left;
      padding-bottom: 2em;
    }
    .content-column-left hr {
      display: none;
    }
    .content-column-right {
      /* Values for IE/Win; will be overwritten for other browsers */
      width: 47%;
      padding-left: 3%;
      float: left;
      padding-bottom: 2em;
    }
    .content-columns>.content-column-left, .content-columns>.content-column-right {
      /* Non-IE/Win */
    }
    img {
      border: 2px solid #fff;
      padding: 2px;
      margin: 2px;
    }
    a:hover img {
      border: 2px solid #f50;
    }
    /*]]>*/
  </style>
</head>

<body>
  <h1>Fedora Webserver <strong>Test Page</strong></h1>

  <div class="content">
    <div class="content-middle">
      <p>This page is used to test the proper operation of the
      Fedora HTTP server after it has been installed. If you can
      read this page, it means that the web server installed at
      this site is working properly, but has not yet been
      configured.</p>
    </div>
    <hr />

    <div class="content-columns">
      <div class="content-column-left">
        <h2>If you are a member of the general public:</h2>

        <p>The fact that you are seeing this page indicates that
        the website you just visited is either experiencing
        problems or undergoing routine maintenance.</p>

        <p>If you would like to let the administrators of this
        website know that you've seen this page instead of the page
        you expected, you should send them e-mail. In general, mail
        sent to the name "webmaster" and directed to the website's
        domain should reach the appropriate person.</p>

        <p>For example, if you experienced problems while visiting
        www.example.com, you should send e-mail to "webmaster@example.com".</p>

        <p>Fedora is a distribution of Linux, a popular computer
        operating system. It is commonly used by hosting companies
        because it is free, and includes free web server software.
        Many times, they do not set up their web server correctly,
        and it displays this "test page" instead of the expected
        website.</p>

        <p>Accordingly, please keep these facts in mind:</p>

        <ul>
          <li>Neither the Fedora Project or Red Hat has any
          affiliation with any website or content hosted from this
          server (unless otherwise explicitly stated).</li>

          <li>Neither the Fedora Project or Red Hat has "hacked"
          this webserver, this test page is an included component
          of the Fedora webserver software.</li>
        </ul>

        <p>For more information about Fedora, please visit the
        <a href="https://getfedora.org/">Fedora Project website</a>.</p>
        <hr />
      </div>

      <div class="content-column-right">
        <h2>If you are the website administrator:</h2>

        <p>You may now add content to the webroot directory. Note
        that until you do so, people visiting your website will see
        this page, and not your content.</p>

        <p>For systems using
        <a href="https://docs.fedoraproject.org/en-US/quick-docs/getting-started-with-apache-http-server/index.html"> <strong>Apache Webserver</strong></a>:
        You may now add content to the directory <code>/var/www/html/</code>.
        Note that until you do so, people visiting your website will see
        this page, and not your content. To prevent this page from
        ever being used, follow the instructions in the file
        <code>/etc/httpd/conf.d/welcome.conf</code>.</p>

        <p>For systems using
        <a href="https://fedoraproject.org/wiki/Nginx"><strong>Nginx</strong></a>:
        You should now put your content in a location of your
        choice and edit the <code>root</code> configuration directive
        in the <strong>nginx</strong> configuration file
        <code>/etc/nginx/nginx.conf</code>.</p>
      </div>

      <div class="logos">
        <a href="https://getfedora.org/"><img src= "/icons/poweredby.png" alt="[ Powered by Fedora ]" /></a> <!-- Fedora -->
        <img src="poweredby.png" /></a> <!-- webserver -->
      </div>
    </div>
  </div>
</body>
</html>

BINGO !!! The traffic from tcp port 80 is now ALLOWED !!!

NOTE :: the added service for http is temporary meaning it will be removed if the virtual machine reboots.

To permanently add the service for http on the current active zone (FedoraWorkstation), execute the following command:

$ sudo firewall-cmd --zone=FedoraWorkstation --permanent --add-service=http

The following would be a typical output:

Output.20

success

To reload the updated firewalld rules, execute the following command:

$ sudo firewall-cmd --reload

The following would be a typical output:

Output.21

success

To permanently remove the service for http on the current active zone (FedoraWorkstation), execute the following command:

$ sudo firewall-cmd --zone=FedoraWorkstation --permanent --remove-service=http

The following would be a typical output:

Output.22

success

The firewalld rules need to be reloaded after the updated.

References

Firewalld Documentation



© PolarSPARC