try.directtry.direct

How to Secure Your Server Using Firewalld

The previous article about iptables demonstrated how it can be used to secure your system. Recently, a new firewall called FirewallD was introduced by Red Hat Enterprise Linux 7.0 (RHEL). FirewallD is the default firewall for Red Hat/CentOS/Rocky Linux and the SUSE family.

This tutorial will provide you with a basic understanding of FirewallD and the ways to secure your system using the firewall-cmd command.

FirewallD comes with a Netfilter, a kernel-level framework that checks every packet traveling across the system. It inspects any packages and takes appropriate action on them before they reach the destination.


1. FirewallD vs iptables. What are the advantages of FirewallD?


  • All the changes are applied immediately in the runtime environment. You do not have to restart or reload the FirewallD service or daemon.
  • Using FirewallD, you can specify services by using the name of the service rather than its port and protocol. For example, you can use samba rather than UDP ports 137 and 138, as well as TCP ports 139 and 445.
  • Iptables is based on the rule’s sequence, where the rules are read from top to bottom chain. FirewallD removes this dependency on order by using zone. Thus you no longer need to worry about the rules’ order.
  • You can set multiple firewall configurations in your system, e.g. one configuration for the Wi-Fi interface and another configuration for the LAN interface, etc.
  • FirewallD uses D-Bus API to interact/maintain firewall settings easily.

2. Prerequisites


We have used the below-given testing environment in this tutorial:

  • A server running on Rocky Linux 8.
  • A root password is configured on the server.

In this guide, we have focused on the 'firewall-cmd' command to configure firewall settings.


3. Disable Iptables


Iptables and FirewallD are incompatible with each other. So, make sure the iptables service is not running on your system before you start FirewallD service. If it is running, then stop and mask iptables service using the below command:


systemctl status iptables
systemctl stop iptables
systemctl mask iptables

bash


4. How to install FirewallD and enable it at startup


The FirewallD package is installed by default in RHEL/CentOS 7/8, Fedora, Rocky Linux 8, and OpenSUSE. Otherwise, you can install it manually.

Execute the following command to install FirewallD:


dnf install firewalld -y

bash


Next, start and enable the firewalld service using the below command:


systemctl start firewalld.service
systemctl enable firewalld.service

Now verify the status of firewall service by using the following commands:


firewall-cmd -state

Output:


running

Or


sudo systemctl status firewalld

bash


Output:



[root@rockylinux-8 ~]# sudo systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)
Active: active (running) since Sun 2022-01-02 13:13:23 UTC; 1min 33s ago
Docs: man:firewalld(1)
Main PID: 43464 (firewalld)
Tasks: 2 (limit: 4730)
Memory: 27.1M
CGroup: /system.slice/firewalld.service
└─43464 /usr/libexec/platform-python -s /usr/sbin/firewalld --nofork --nopid

Jan 02 13:13:23 rockylinux-8 systemd[1]: Starting firewalld - dynamic firewall daemon...
Jan 02 13:13:23 rockylinux-8 systemd[1]: Started firewalld - dynamic firewall daemon.


5. Runtime v/s Permanent FirewallD Configurations


FirewallD has two separate configuration modes: runtime configuration and permanent configuration.

The runtime configuration is the default configuration mode. As the name suggests, the runtime configuration is the present and actively running configuration that does not stay constant on rebooting or restarting the FirewallD service. Evaluation and testing can be done in runtime, as the configuration is valid only until you reboot the system.

Essentially, any changes you make are set to runtime configuration by default. You can make changes in the runtime configuration for testing. It can be written later in the permanent configuration after you learn about their authenticity and correctness using the following command:


firewall-cmd --runtime-to-permanent

bash


You can see the changes made in the runtime instantly. While the changes in the permanent configuration will only appear after you reload the FirewallD service or reboot the system.


firewall-cmd --reload

bash


Commands like making changes in the zone target, etc., can be run with permanent configuration. When you run a command that can be applied against permanent configuration only, the below-given message will appear on the screen.


firewall-cmd --zone=dmz --set-target=REJECT

bash


Output:


usage: see firewall-cmd man page
Option can be used only with --permanent.


6. Working with Zones


In iptables, rules are organized into chains, but FirewallD replaced this chain with the zone. You can allow and block any services or ports using a zone. The zone is connected to networking interfaces or assigned to a range of source addresses. Zones can be associated with one or more network interfaces. You manage firewall rules for each zone independently.

For example:

The first networking interface is connected to a public network while the second - to a private network. Hence, you can create two separate zones: public and private.


6.1 Listing all zones in FirewallD


You can get a list of all zones available on your system by executing the below command:


firewall-cmd --get-zones

bash


Output:


block dmz drop external home internal nm-shared public trusted work

In the above output, you can see all the zones provided by FirewallD. Now, let’s consider all these zones according to the trust level of each of them: from untrusted to trusted:

drop: It will drop all the incoming connections without any notification, as only outgoing connections are allowed.

block: All incoming connections are rejected with a notification. Only outgoing connections are possible.

public: The default zone is used for untrusted public networks. Here, you can allow selected incoming connections of your choice.

external: This zone is used for external networks with NAT masquerading enabled when your system acts as a gateway or router. Only selected incoming connections are accepted.

internal: The zone is designed for internal networks when you mostly trust the other computers on the network. Here, only selected incoming connections are accepted.

dmz: This zone is used for systems located in your demilitarized zone with limited access to the rest of your network. Only selected incoming connections are allowed.

work: This zone uses a work environment where you mostly trust the other computers on the network. Only selected incoming connections are accepted.

home: This zone is used for home machines that are most trusted. Only selected incoming connections are accepted.

trusted: All network connections are accepted. This is when you trust all of the computers in the network. It allows all incoming and outgoing requests.


Alternatively, display all zones defined by default in detail:


firewall-cmd --list-all-zones

bash


Output:


block
target: %%REJECT%%
icmp-block-inversion: no
interfaces:
sources:
services:
ports:
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:

dmz
target: default
icmp-block-inversion: no
interfaces:
sources:
services: ssh
ports:
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:

drop
target: DROP
icmp-block-inversion: no
interfaces:
sources:
services:
ports:
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
- - - - - - - - - - - -
- - - - - - - - - - - -


You can also check detailed information for a specific zone:


Syntax:


firewall-cmd --zone=zone-name --list-all

bash


For Example:


firewall-cmd --zone=public --list-allOutput:
public (active)
target: default
icmp-block-inversion: no
interfaces: eth0 eth1
sources:
services: cockpit dhcpv6-client ssh
ports:
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:

You can change the default target as per your requirement. Run the following command to set the target for the public zone:


firewall-cmd --permanent --zone=public --set-target=DROP

bash


Now, reload the FirewallD service and check zone details again by executing the following command:


firewall-cmd --reload

bash


firewall-cmd --zone=public --list-allOutput:
public (active)
target: DROP
icmp-block-inversion: no
interfaces: eth0 eth1
sources:
services: cockpit dhcpv6-client ssh
ports:
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:

Let us understand the above command output in detail:

public (active):- This indicates that a public zone is an active one. An active zone is a zone that has at least one interface or source associated with it.

target: DROP:- Any package that does not match the rules will be dropped.

icmp-block-inversion: no:- It shows that icmp-block-inversion NOT_ENABLED.

Interface: eth0 eth1:- Any package request coming to the interfaces eth0 and eth1 will be checked by this zone’s rules. You can call the eth0 and eth1 the attached interfaces of the zone.

sources:- It shows the IP address attached to this zone.

services:- cockpit dhcpv6-client ssh:- It shows all the services that are allowed through the firewall.

ports:- List of ports allowed through the firewall.

protocols:- List of protocols that are allowed in a firewall. Here, no protocols have been specified. Therefore, it is left blank.

forward: no:- Here, nothing is forwarded.

Masquerade: no:- IP masquerading is disabled. It allows packets to be forwarded when enabled. This is convenient when you are using your system as a router.

Forward-ports:- List of ports that are being forwarded.

source-ports:- List of source ports that shows packages are incoming from specific port addresses.

icmp-blocks:- List of blocked icmp traffic. Currently empty.

rich rules:- List of advanced configurations you can add to a zone. These rich rules will be processed first in a zone.


6.2 List of default FirewallD zone

You can list the default FirewallD zone using the following command:


firewall-cmd --get-default-zone

bash


Output:


public

6.3 List of active FirewallD zone


To check your current FirewallD zone:


firewall-cmd --get-active-zones

bash


Output:


public
interfaces: eth0 eth1

6.4 Changing default zone to the specific one


You can easily change the default zone by executing the below command:


firewall-cmd --set-default-zone=work

bash


Next, verify the new default zone by running the following command:


firewall-cmd --list-all

bash


Output:


work (active)
target: default
icmp-block-inversion: no
interfaces: eth0
sources:
services: cockpit dhcpv6-client ssh
ports:
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:


Get default zone:

firewall-cmd --get-default-zone

bash


Output:


work

6.5 Changing a network interface to a zone


In FirewallD, you can define different sets of rules for different zones and then quickly change the setting by changing the zone for the interface that is being used.

Using the below command, you can assign the eth1 interface to the work zone:


firewall-cmd --zone=work --change-interface=eth0

bash


Verify the changes by typing:


firewall-cmd --get-active-zones

bash


Output:


[root@rockylinux-8 ~]# firewall-cmd --zone=work --change-interface=eth0
success
[root@rockylinux-8 ~]# firewall-cmd --get-active-zones
public
interfaces: eth1
work
interfaces: eth0

6.6 Creating a custom zone


You can create your custom zone. Let's suppose you want to create your own customs zone called demo_zone:


firewall-cmd --permanent --new-zone=demo_zone

bash


Now, reload the FirewallD service.


firewall-cmd --reload

bash


Now, check the new zone by executing the following command:


firewall-cmd --list-all --zone=demo_zone

bash


You can now assign all the rules to this new zone and make your own customized rules.

Here, assign an interface to this newly created zone by running the following command:


firewall-cmd --zone=demo_zone --change-interface=eth0

bash


Next, verify changes:


firewall-cmd --list-all --zone=demo_zone

bash


Output:


[root@rockylinux-8 ~]# firewall-cmd --permanent --new-zone=demo_zone
success
[root@rockylinux-8 ~]# firewall-cmd --reload
success
[root@rockylinux-8 ~]# firewall-cmd --list-all --zone=demo_zone
demo_zone
target: default
icmp-block-inversion: no
interfaces:
sources:
services:
ports:
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:

[root@rockylinux-8 ~]# firewall-cmd --zone=demo_zone --change-interface=eth0
Success

[root@rockylinux-8 ~]# firewall-cmd --list-all --zone=demo_zone
demo_zone (active)
target: default
icmp-block-inversion: no
interfaces: eth0
sources:
services:
ports:
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:

6.7 Creating an IP source zone


Let's take one example where all Office IPs can access SSH from your local LAN. To understand this better, create one zone called ‘office’.


firewall-cmd --permanent --new-zone=office

bash


firewall-cmd --reload

bash


Here, the LAN IP scheme is 192.168.0.0/24. Next, use this 'office' zone as a source zone to control access from your local LAN.


firewall-cmd --zone=office --add-source=192.168.0.0/24

bash


Now, verify the changes:


firewall-cmd --zone=office --list-all

Output:


[root@rockylinux-8 ~]# firewall-cmd --zone=office --list-all
office (active)
  target: default
  icmp-block-inversion: no
  interfaces:
  sources: 192.168.0.0/24
  services:
  ports:
  protocols:
  forward: no
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

bash


Here, you can notice that the office zone is active now because you added a source. Any zone will become active when you assign any source or interface to it.


Next, allow anyone in your local LAN to SSH into your system.


firewall-cmd --zone=office --add-service=ssh

bash


Verify it:


firewall-cmd --zone=office --list-all

bash


Output:


[root@rockylinux-8 ~]# firewall-cmd --zone=office --list-all
office (active)
  target: default
  icmp-block-inversion: no
  interfaces:
  sources: 192.168.0.0/24
  services: ssh
  ports:
  protocols:
  forward: no
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

bash


How to make any runtime changes persistent?


By running the following command, you can save your runtime changes permanently.


firewall-cmd --runtime-to-permanent

bash



7. Services


Services are another powerful feature of FirewallD. Services are one of the best ways to manage the firewall rules. FirewallD has many predefined services which make FirewallD easy to use and configure quickly. Services have predefined rules in which you can get a list of all available services by running the following command:


firewall-cmd --get-services

bash


Output:


RH-Satellite-6 RH-Satellite-6-capsule 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 collectd condor-collector ctdb dhcp dhcpv6 dhcpv6-client distcc dns dns-over-tls docker-registry docker-swarm dropbox-lansync elasticsearch etcd-client etcd-server finger foreman foreman-proxy freeipa-4 freeipa-ldap freeipa-ldaps freeipa-replication freeipa-trust ftp galera 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 kube-apiserver ldap ldaps libvirt libvirt-tls lightning-network llmnr managesieve matrix mdns memcache minidlna mongodb mosh mountd mqtt mqtt-tls ms-wbt mssql murmur mysql nbd 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 rquotad 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

7.1 List all the available services of a zone


You can list all the services associated with a particular zone by using the following command:


firewall-cmd --zone=public --list-services

bash


Output:


cockpit dhcpv6-client ssh

7.2 Add an existing service to the default zone


You can add any existing service to your default zone using the below command:


firewall-cmd --add-service=samba

bash


The above command will add samba service to the runtime configuration. To add any services permanently use the--permanent' option:


firewall-cmd --permanent --add-service=samba

bash


Note: if you are using the --permanent option, the setting is not added to runtime configuration. You will need to reload the permanent configuration.


firewall-cmd --reload

bash


Now, verify it:


firewall-cmd --list-all

bash


Output:


public (active)
target: DROP
icmp-block-inversion: no
interfaces: eth1
sources:
services: cockpit dhcpv6-client samba ssh
ports:
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:

Likewise, you can remove any service to use through --remove-service instead of the --add-service option.


firewall-cmd --permanent --remove-service=samba

bash


Check allowed services in the runtime configuration by running the following command:


firewall-cmd --list-service

bash


Check allowed services in the permanent configuration using the below command:


firewall-cmd --list-service --permanent

bash


8. Port


Using FirewallD, you can open or close any port directly even if a particular service is not installed on your system. Amazing, right?

For example:You can open or close SSH port 22, even if the SSH service is not installed on your system.


8.1 Open any port


You can open and close any port as shown in the example below:

Open Port in runtime configuration:


firewall-cmd --zone=public --add-port=80/tcp

bash


Open Port permanently using the --permanent flag:


firewall-cmd --zone=public --permanent --add-port=3000/tcp

bash


Likewise, you can specify the port range:


firewall-cmd --zone=public --permanent --add-port=3000-3999/udp

bash



8.2 List Added Ports


You can verify if a port was successfully added by using the --list-ports flag.


firewall-cmd --zone=public --list-ports

bash


Output:


80/tcp

Here, you can use the --permanent flat to change port:


firewall-cmd --zone=public --permanent --list-ports

bash


Output:


3000/tcp

9. Timeout


Timeout is one of the exciting features of FirewallD. This feature helps the administrators to add a rule to runtime configuration. It enables you to add a time limit to a rule. The rule is automatically removed after the specified time has expired. Find below two examples of the efficient usage of this feature:

Suppose you want to download a file through the FTP service, and you know this will take 5 minutes. You set a timer that will automatically stop the service after it is triggered..

When you want to allow a friend to upload a file through FTP, you can grant them access to the same for a limited period. They will lose access after the time runs out.


firewall-cmd --zone=public --add-service=ftp --timeout=5m

bash


Note:

We can specify the timeout in seconds (s), minutes (m) or hours (h).


10. Advanced rule creation


Using FirewallD, you aren't limited to just ‘allow’ or ‘deny’ some port or services, changing the zone, and so on. Here, you can create more complex rules for specific situations. These rules are known as rich rules.

For example: You may want to create a rule to block certain types of traffic from a specific machine.

This rich rule basically consists of two parts.

1. The conditions that must be met for the rule to be applied.

2. Action must be performed once those conditions are met. The action to be executed: accept, drop, or reject.

Let’s understand this with the following example: suppose you want to reject all FTP connections from the machine with IP address 167.99.177.43


firewall-cmd --zone=enable_test --add-rich-rule="rule \
family="ipv4" \
source address=167.99.177.43 \
service name=ftp \
reject \

Here, you can identify most of the options by their name. However, you must start with the keyword rule: the family options. If the family option is left blank, both IPv4 and IPv6 protocol will be used.


11. The panic mode


The panic mode is used in extreme situations where there is a severe problem in the network environment. By turning it on, we will discard all the current connections and drop all the incoming and outgoing packages. You can activate this mode by using the following command:


firewall-cmd --panic-on

bash


To exit panic mode, apply the command:


firewall-cmd --panic-off

bash


To check the smooth running of the panic mode, use the following command.

It’s even possible to query the panic mode status, running:


firewall-cmd --query-panic

bash


The panic mode is only used for troubleshooting purposes, valid only at runtime, and cannot be used with --permanent.

This tutorial introduced you to the basic concepts to kickstart an easy application of FirewallD and the ways to adapt it to your current production server. You are ready to go on your own.



Still have questions ? Join our community discord channel, get help and free consultation!

Need a quick help from the Linux expert ? Click the button below