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:
firewalld :: a daemon that acts as the front-end controller for iptables
firewall-cmd :: a command-line utility to interact with the firewalld daemon
firewall-config :: a GUI utility to interact with the firewalld daemon
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:
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:
* 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:
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:
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:
* 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:
service(s) :: is a grouping for ports and protocols and is used for managing filtering rules
zone(s) :: used for categorizing the incoming traffic based on the network interface and source address. They are used for grouping and managing a set of packet filtering rules using a set of service(s)
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:
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:
<?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:
<?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:
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:
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:
<?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:
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:
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:
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:
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:
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:
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:
<?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:
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:
<!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:
success
To reload the updated firewalld rules, execute the following command:
$ sudo firewall-cmd --reload
The following would be a typical output:
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:
success
The firewalld rules need to be reloaded after the updated.
References