Log In

Configuring Firewalld on CentOS

Configuring Firewalld on CentOS
Reading time: 9 min
Hostman Team
Technical writer

Firewalld is a firewall management tool that comes pre-installed on most RHEL-based distributions. In this article, we will look at setting up a firewall with firewalld on a CentOS server using the firewall-cmd utility.


To follow this guide, you will need:

  • A cloud server running CentOS

  • A root user or a user with sudo privileges

What is firewall?

A firewall is a program for access control at the network level. Based on the set up rules, the firewall determines which devices can access this or that part of the network, which traffic is allowed and which is blocked. In Linux, these functions are performed by the netfilter program built into the kernel.

So, netfilter works at the kernel level. To configure the firewall, you need tools in user space. ip_tables/nf_tables, implemented as kernel modules, are used as frameworks for managing netfilter. And on top of them, at the user level, either iptables or nft are used.

Experienced system administrators know that manually writing rules for iptables or nft is not so easy, especially when you need to set up a large network or transfer rules to another system. That's where more user-friendly and feature-rich add-ons come into play. For example, in Ubuntu such an add-on is a tool with the self-explanatory name ufw (Uncomplicated Firewall). And in RedHat distributions (CentOS, Alma, Fedora, RHEL, OpenSUSE, SUSE Linux Enterprise), it is firewalld.

Working with firewalld

There are two programs to manage firewalld: firewall-cmd for working in the terminal and firewall-config GUI. 

In this article, we will work with firewall-cmd.


Connect to your server and check the service status:

sudo systemctl status firewalld

Powershell N Um L8 Lgp Pj

As mentioned before, in RHEL-based distributions, firewalld is pre-installed. If you wish to use it on Ubuntu/Debian, you can easily install it manually: 

sudo apt install firewalld
sudo systemctl enable firewalld --now

Don't forget to disable ufw, as using two utilities for iptables/nftables may cause issues.

Active rules

Check the existing active rules by using the command:

sudo firewall-cmd --list-all

Note that you need superuser privileges for this, so log in as root or use sudo/su.

Powershell 6o9 X Iayx Mb

In the command output you can see many different parameters. Let's look at them in order.

Configuring ports

The ports field shows the ports on which connections are allowed. 

To better understand how it works, let's change the listening port of the OpenSSH daemon from 22 to 3333 in the /etc/ssh/sshd_config file:

Port 3333
#AddressFamily any
#ListenAddress ::
sudo systemctl restart sshd

List the ports listened by sshd:

sudo ss -nl4p | grep sshd


tcp LISTEN 0 128 *:3333 *:* users:(("sshd",pid=7602,fd=3))

As you can see, the port 3333 is now listening. The current session has not been interrupted, but if we try to connect again using the standard or new port, we won't be successful:

ssh user1@
ssh: connect to host port 22: Connection refused
ssh user1@ -p 3333
ssh: connect to host port 3333: No route to host

You need to add an allowing rule to firewalld that allows you to connect via 3333/tcp:

sudo firewall-cmd --add-port=3333/tcp


sudo firewall-cmd --add-port=3333/tcp --permanent
sudo firewall-cmd --reload

In the first case, the changes are active only in the current runtime, and when the machine or service is restarted, everything is reset. In the second case, the --permanent flag indicates that we are changing the settings permanently, so you need to restart the firewall (the --reload option).

Let's check which ports are now allowed:

sudo firewall-cmd --list-ports



Now everything works:

ssh user1@ -p 3333
user1@'s password:

You might wonder how we managed to connect via SSH earlier, as at first the ports field in the policy output was empty. The fact is that the settings were specified using service descriptions.

Configuring services

Services in firewalld are service descriptions that make configuration more convenient and centralized. Let's look up the current services and information about them:

sudo firewall-cmd --list-services

Powershell 0 Pyfna Fhsd

sudo firewall-cmd --info-service=ssh

Powershell Ng F3 N8wgg J

Note that SSH still has port 22. The fact is that the daemons' own parameters are in no way related to their descriptions in firewalld. Let's try to remove the standard port and add 3333 to the ssh service description (don't forget to remove port 3333/tcp from the policies):

sudo firewall-cmd --service=ssh --remove-port=22/tcp --permanent
sudo firewall-cmd --remove-port=3333/tcp --permanent
sudo firewall-cmd --service=ssh --add-port=3333/tcp --permanent
sudo firewall-cmd --reload

Now let's check again:

sudo firewall-cmd --info-service=ssh

Powershell K7ic Fy Rfc V

Let's try to remove and add a service:

sudo firewall-cmd --remove-service=dhcpv6-client
sudo firewall-cmd --add-service=mysql
sudo firewall-cmd --runtime-to-permanent

Check the list of services:

sudo firewall-cmd --list-services

Powershell S Tmd2b C Hwe

The --runtime-to-permanent option makes the runtime permanent. You don't have to specify --permanent after each command, but execute a set of commands and only after that make the settings permanent (please note that it does not always work since some commands require the --permanent option).

Files with predefined services are located at /lib/firewalld/services. Let's list them:

sudo firewall-cmd --get-services

Powershell Y Bm A5x Ag Vw

You can create your own services. To do this, create an .xml file in the /etc/firewalld/services directory. For convenience, you can copy a configuration from /etc/firewalld/services and make the necessary changes. Then restart the firewall with the --reload flag.

ICMP, protocols and targets

The output of --list-all has the following fields:

sudo firewall-cmd --list-all | grep -E '(target|icmp|protocols)'

Powershell 07vm U Q0 Ps F

In firewalld, you can configure not only services and ports, but also protocols. Let's say we set up a firewall on a router. It makes sense to indicate a list of allowed protocols. To illustrate, let's enable the OSPF dynamic routing protocol:

sudo firewall-cmd --add-protocol=ospf
sudo firewall-cmd --list-protocols

Powershell Avm Hg1ws Md

The icmp-blocks and icmp-blocks-inversion fields contain parameters for the ICMP protocol used for network testing and error notifications. It is used by ping and traceroute utilities.

Using icmp-blocks you can block specific ICMP messages. The icmp-blocks-inversion inverts the logic, as in the listed message types become allowed and the rest are blocked. This functionality can be used to hide network information since many scanning engines use ICMP. Let's test the blocking using the ping utility.

Prohibit all types of ICMP messages (since nothing is listed in icmp-block, all messages become prohibited):

sudo firewall-cmd --add-icmp-block-inversion

Now let's try to ping the server:

ping -c 3

PING ( 56(84) bytes of data.
From icmp_seq=1 Destination Host Prohibited
From icmp_seq=2 Destination Host Prohibited
From icmp_seq=3 Destination Host Prohibited
--- ping statistics ---
3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2004ms

The machine does not respond to ping. This method is often used by providers to hide router addresses. However, it is clear from the errors that the packets on the target devices are being filtered by the firewall. To hide your computer, you need to use targets.

A target is an action that needs to be done with the package if any of the rules are triggered. The most used are DROP, ACCEPT, REJECT. In the example above, the target was REJECT, i.e. returning the reason for the error. To drop a packet without sending anything, you need to use DROP:

sudo firewall-cmd --set-target=DROP --permanent
sudo firewall-cmd --reload

Let's ping the server again:

ping -c 3

PING ( 56(84) bytes of data.
--- ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2050ms


When working with firewalld, zones are often used. A machine may have multiple interfaces: one for Internet, another for LAN, and third for dmz. Different networks have different levels of trust, and traffic coming from them must be controlled by different firewall rules. To achieve this, firewalld uses zones, sets of rules that apply to different parts of the network.

All the firewall rules we configured above were applied for the public zone (by default):

sudo firewall-cmd --get-default-zone

Powershell X Yulv Drold

Firewalld initially contains several zones. However, you can create your own zones. Let's display a list of available zones:

sudo firewall-cmd --get-zones

Powershell Yz Br2hhl Ab

The --zone option allows you to set and view rules for a specific zone (without it, everything is applied to the default zone). Let's look at the policies for the drop zone:

sudo firewall-cmd --list-all --zone=drop

Powershell Ytud0 Cbp6b

In our case, the interface eth0, which provides access to the Internet, is in the public zone. This means that the policies of the public zone are applied to incoming traffic. To add the interface to another zone, use the --change-interface switch. Let's move our eth0 to the home zone:

sudo firewall-cmd --change-interface=eth0 --zone=home
sudo firewall-cmd --list-interfaces --zone=home

Powershell G Ci Nn Boz Qj

Sometimes, you may need to configure traffic rules for a specific address. It's done like this:

sudo firewall-cmd --zone=drop --add-source=

Now check:

sudo firewall-cmd --zone=drop --list-all

Powershell Zub P Gwku3 K

Now, even if packets from the address arrive on the eth0 interface, the rules will be applied not for the zone in which the interface is located, but for the zone we manually specified (drop). 

NAT setup

NAT stands for Network Address Translation. There are two types of NAT: source and destination. In the first case, the router replaces home IP addresses with its external ones, i.e. changing the sender's (source) address. In Linux, this is called masquerade. In the second case, the recipient address is replaced (port forwarding). For example, a packet arrives at the router port, and the router forwards the packet to some other port.

Let's say you need to configure a firewall on a router. Enable masquerading:

sudo firewall-cmd --add-masquerade

Run --list-all:

sudo firewall-cmd --list-all

Powershell T Wy Iyouc B6

Enable port forwarding:

sudo firewall-cmd --add-forward-port=port=3333:proto=tcp:toport=22
sudo firewall-cmd --list-all

Powershell M Q7 Yo4 Vt Sl

You may also notice the source-ports option. Firewalld can allow specific outgoing ports, but this is rarely used since dynamic 5-digit ports are usually used as source ports.

Rich rules

We looked at how to use different firewalld rules for different network areas (interfaces, IP addresses). But sometimes you need to create very distinctive rules, like allowing connections from a specific address to a specific port, using such and such protocols, etc. Of course, you can create your own zone, but it may be better to use rich-rules.

Rich-rules in firewalld have a different syntax which you can find in the manual:

man firewalld.richlanguage

It also provides many examples.

And that's how you add a rich-rule manually:

sudo firewall-cmd --add-rich-rule=’rule'


A properly functioning firewall greatly improves network security. In this article, we looked at the basics of working in firewalld, which are necessary for proper configuration. Firewalld allows you to easily divide your network into sections and set your own security policies for each section.