Skip to main content

How To Set Up a Firewall Using FirewallD on CentOS 7

Firewalld is a complete firewall management solution available for many Linux distributions that dynamically manages the level of trust on a per-connection and per-interface basis. It offers complete control over what traffic is allowed into and out of the system. It does that by serving as a user interface for the Linux kernel's iptables packet filtering system.

Firewalld service and iptables are both used for packet filtering purposes. Firewalld may have a few advantages over iptables like being able to use zones more dynamically, also no need to reload firewalld service for each configuration change. It can be done in the current session. Also, services, applications, and users can adjust firewall settings using the firewalld D-bus interface. It is used for firewall configuration tools. Since the runtime and permanent configurations are separated.

In this article, we are going explain;

  • Basic concepts of Firewalld
  • Steps for installing firewalld on CentOS 7
  • Basics of managing the firewall using firewall-cmd
  • Adding a port to Firewalld
  • Adding a service to Firewalld
  • Permanently disabling firewalld service
  • Installing problems and troubleshooting

What are the Requirements to Install a Firewall on CentOS 7 with FirewallD?โ€‹

There are two basic requirements for installing Firewall on CentOS 7 with firewalld.

  • A CentOS 7 Linux operating system installed with the firewalld package is required to install a firewall on CentOS 7.
  • A user with sudo privileges is required.

In this guide, we are going to apply commands using the root user. Sudo keyword won't be used. The best practice is to create a user with sudo privileges to prevent users from using unauthorized commands. Also keep in mind that your centos firewall version or your centos configuration may be slightly different than the one used in this guide, but you may also not realize it because it probably won't cause any problems.

What are the Basic Concepts in FirewallD to Understand For Installing a Firewall?โ€‹

The basic concepts in firewalld for installing a firewall mainly are firewalld zones, firewalld services, and firewalld settings. It may be better to have a deeper look at these concepts before diving into the installation and settings of firewalld service on the CentOS 7 operating system.

1. FirewallD Zonesโ€‹

Firewalld service uses zones to customize and apply changes to the firewall in CentOS7. Zones can be considered as a collection of rules. Here are some available firewalld zones:

  • drop: It is the least trusted case. Only outgoing connections are possible when all incoming connections are dropped without response.

  • block: It is a version of the drop option with a response message. Incoming connections are refused with an "icmp-hostprohibited" message for IPv4, and an "icmp6-adm-prohibited "message for IPv6.

  • public: It is used for public places where you can't trust other devices unless you do let some connections in some cases willingly.

  • external: This zone is used notably for routers when you enable masquerading. The firewall is used as your gateway. The internal network is still reachable but private.

  • internal: This zone is used for internal networks. The internal side of the gateway is when the firewall is used as your gateway.

  • DMZ: DMZ is used for publicly accessible devices which have limited access to your internal network.

  • work: This zone is mostly used at places like work. Most of the connected devices are trustworthy. It is optional to add some extra services.

  • home: This zone is mostly used at places like home. Most of the connected devices are trustworthy.

  • trusted: All connections in the network are trusted. This option is the least limited alternative and should be used with caution.

2. FirewallD Servicesโ€‹

Firewalld services are specified as XML files that contain port- and protocol-mappings, as well as optional supplementary information such as subnets and a list of Kernel helper modules. Instead of single changes in ports and protocols, services give the opportunity to keep track of them. HTTP, SSH,and DNS are some examples for services.

3. FirewallD Runtime and Permanent Settingsโ€‹

There are two types of settings while using firewalld: Runtime and permanent settings.

  • Runtime settings remain in that opened session until a reboot.
  • Permanent settings are used by adding the --permanent command to firewalld -cmd commands and making the settings permanent.

It's mostly advised to test changes in that session and make them permanent after solving possible issues.

What are the Steps to Install a Firewall on CentOS 7โ€‹

You can follow the steps given below to install and configure a firewall on your CentOS server with firewalld.

Installing and Enabling Firewalldโ€‹

Most Linux distributions contain firewalld packages including CentOS 7 releases.

In other cases, using the yum install command will solve the problem. Here, it is assumed there is a working yum configuration.

yum install firewalld

After installing the firewalld package, the service can be enabled.

The thing to consider here is, firewalld will be active after the reboot.

At this stage, testing zone configurations and the current zone settings may be good to avoid possible unwanted problems. If running, disabling iptables service is also advised before enabling firewalld service.

systemctl enable firewalld
reboot

The state of the service can be checked by the following command.

firewall-cmd --state

You should see the output similar to this:

Running

Note that we didn't make any changes yet so it is in the default zone. But before diving into details of firewalld zones, let's have a quick look at firewalld managing commands in order to be familiar with them and also being able to use them while working with zones and services etc.

Enable firewalldโ€‹

This ensures that firewalld is started automatically when the server boots up.

systemctl enable firewalld

Start firewalldโ€‹

After you've enabled the firewalld service, you'll need to manually start it for the first time. If firewalld isn't currently operating, this is how you'd start it manually.

systemctl start firewalld

Stop firewalldโ€‹

You may need to temporarily stop the firewalld service while fixing rules and connection difficulties. With the following command, you can stop the service.

systemctl stop firewalld

Restart firewalldโ€‹

If restarting the service is needed for any reason, systemctl restart command can be used.

systemctl restart firewalld

Firewalld statusโ€‹

The status of the service, such as enabled, running or failed, can be seen using this command.

systemctl status firewalld

Work with firewalld zonesโ€‹

Before making changes to rules it may be better to take a look and be familiar with some commands.

The following command is used to see which zone is currently the default zone.

firewall-cmd --get-default-zone

You should see the output similar to this:

public

As we haven't made any changes to our zones yet, our default zone will also be the active zone. It can be checked by the following command:

firewall-cmd --get-active-zones

You should see the output similar to this:

public

interfaces eth0 eth1

Looking at the output, we can see that our eth0 and eth1 interfaces are being controlled by the public zone and its default settings.

To see which zone is currently the default zone we type the following command.

firewall-cmd --list-all

You should see the output similar to this:

public (default, active)

target: default

icmp-block-inversion: no
interfaces: eth0 eth1
sources:
services: ssh dhcpv6-client
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:

Set Rules For Your Applicationsโ€‹

The best way to set rules for your applications is to add currently available services. Before that, to see available services we can use the following command:

firewall-cmd --get-services

You should see the output similar to this:

RH-Satellite-6 amanda-client amanda-k5-client ...

To see details about these services we have to see the associated .xml file under path

/usr/lib/firewalld/services/*.xml.

The prototype above can be copied to /etc/firewalld/services/test_service.xml and be modified by running the following command:

cp /usr/lib/firewalld/services/http.xml /etc/firewalld/services/test_service.xml

Here is an example for HTTP service.

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

<?xml version="1.0" encoding="utf-8"?>

<service>

<short>WWW (HTTP)</short>

<description>๏ฟฝ(Description of http service and where it is used is mentioned.)๏ฟฝ</description>

<port protocol="tcp" port="80"/>

</service>

If this XML file is modified for our settings, it can be added to the rule sets of our zone. Here is an example of our test_service.

/etc/firewalld/services/test_service.xml

<?xml version="1.0" encoding="utf-8"?>

<service>

<short>test_service<short>

<description>This service is defined for test purposes.</description>

<port protocol="tcp" port="2000"/>

</service>

After the new service file is saved, it will be accessible after reloading the firewall.

firewall-cmd --reload

Now we can see our new service in the output list using the following command line.

firewall-cmd --get-services

You should see the output similar to this:

RH-Satellite-6 amanda-client amanda-k5-client test_service ...

To add a service to a zone we use the --add-service parameter. If no zone is specified, the command is going to affect the default zone. To add the service to a specific zone we have to add the --zone= parameter.

Like in previous cases, the command is going to be limited by our current session. To make the changes permanent, --permanent parameter can be used.

For instance, if our application or server needs HTTP service, it can be added like below:

firewall-cmd --add-service=http

The command above is going to add the HTTP service to our current default zone. If we want to specify it, we can add the zone information to the command.

firewall-cmd --zone=public --add-service=http

To see the changes, we can use --list-all or --list-services parameters:

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

You should see the output similar to this:

dhcpv6-client http ssh

After testing our service working properly, we can make the changes permanent by using the following lines to make the changes work after a reboot.

firewall-cmd --zone=public --permanent --add-service=http

You should see the output similar to this:

success

By using the --permanent flag with the --list-services operation, you can confirm that this was successful. --permanent operations is going to need sudo privileges:

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

You should see the output similar to this:

dhcpv6-client HTTP ssh

If your web server is configured to use SSL, HTTPS service can be added too. It can be added to the current session with the permanent setting.

firewall-cmd --zone=public --add-service=https

firewall-cmd --zone=public --permanent --add-service=https

Create your zonesโ€‹

Although working with current zones will be enough in most cases, we may need to create our own zones. It can be done by following commands.

firewall-cmd --permanent --new-zone=publicServ

firewall-cmd --permanent --new-zone=privateNet

At this point we won't be able to see our new zones in our current session, even if they are created, as we can see below.

firewall-cmd --get-zones

You should see the output similar to this:

block dmz drop external home internal public trusted work

To see our new zones we add --permanent keyword and run the command again.

sudo firewall-cmd --permanent --get-zones

You should see the output similar to this:

block dmz drop external home internal privateNet public publicServ trusted work

To be able to apply the changes to the current session, we have to reload our session.

firewall-cmd --reload

firewall-cmd --get-zones

You should see the output similar to this:

block dmz drop external home internal privateNet public publicServ trusted work

Change the zone of an interfaceโ€‹

If we want to change the zone of an interface while using firewalld service, we use the following commands. We can use the newly created zones for eth0 and eth1 interfaces.

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

firewall-cmd --zone=privateDNS --change-interface=eth1

After running commands above, the interfaces will start to use the rules we set in our new zones.

One thing to be aware of at this point is; While using CentOS 7 firewall commands like change interface, we have to check the rules of the zone we want to transfer. For instance, HTTP or SSH services may be closed in that zone which can cause some problems like dropping the session. To see and check the settings before changing zones, firewalld list rules commands which we discussed in the following parts of this guide can be used.

Change the default zoneโ€‹

In some cases, we may need to create new zones and add custom rules and add some ports and services and make that zone our default zone. Here is the command we type to make a zone our default zone:

firewall-cmd --set-default-zone=home

or

firewall-cmd --set-default-zone=publicServ

FirewallD FTP ruleโ€‹

To allow incoming FTP connections, you must allow port 20 and port 21 by entering the following commands:

firewall-cmd --permanent --add-port=20/tcp

firewall-cmd --permanent --add-port=21/tcp

And finally, apply firewall changes:

firewall-cmd --reload

Firewalld Allow MySQLโ€‹

Enter the following command from the command line to enable the MySQL database service for FirewallD:

firewall-cmd --zone=public --add-service=mysql

Open OpenVPN Service Port (1194/UDP)โ€‹

To allow VPN client connections to your OpenVPN server, run the following command:

firewall-cmd --add-service openvpn --zone=public
firewall-cmd --permanent --add-service openvpn --zone=public

Open WireGuard Service Port(51820/UDP)โ€‹

To allow VPN client connections to your OpenVPN server, run the following command:

firewall-cmd --permanent --add-service=wireguard --zone=public

Allow and Block ICMP Packetsโ€‹

Blocking icmp packets is usually suggested to secure a server. Echo reply and echo request are two different forms of ICMP packets. It's useful to know what type to block, and the --get-icmptypes option makes this feasible.

$ firewall-cmd --get-icmptypes

Output:

address-unreachable bad-header communication-prohibited destination-unreachable echo-reply echo-request fragmentation-needed host-precedence-violation host-prohibited host-redirect host-unknown host-unreachable
....

With the --add-icmp-block= option, you may now specify the kind of packet to block.

$ firewall-cmd --permanent --zone=external --add-icmp-block=echo-reply

Output:

Success

Then reload the rule and check the zone to see what happened.

$ firewall-cmd --zone=external --list-all | grep icmp

Output:

icmp-block-inversion: no
icmp-blocks: echo-reply

Port Forwardingโ€‹

You may need to pass inbound packets from one port to another specific one for a zone in the network policy.

You must activate masquerading for the zone in firewalld to do this. Check if masquerading is already enable:

firewall-cmd --zone=external --query-masquerade

Output:

yes

If that isn't in your situation, then go ahead and do it. You have the option of making the modification permanent.

firewall-cmd --permanent --zone=external --add-masquerade

Output:

Success

Assume that traffic for port 143/tcp will be forwarded to port 4545/tcp at a new address.

firewall-cmd --permanent --zone=external --add-forward-port=port=143:proto=tcp:toport=4545:toaddr=192.1.0.20

Output:

Success

You can double-check the zone information after the reload.

firewall-cmd --reload

firewall-cmd --zone=external --list-all | grep forward

Output:

Forward-ports: port=143:proto=tcp:toport=4545:toaddr=192.1.0.20

You may get rid of the forwarding by using:

firewall-cmd --permanent --zone=external --remove-forward-port=port=143:proto=tcp:toport=4545:toaddr=192.1.0.20

Output:

Success
firewall-cmd --reload
firewall-cmd --zone=external --list-all | grep forward

Output:

Forward-ports:

Open Port for Specific IP Address in Firewalldโ€‹

The best way to deal with this is to use a firewalld zone. As a result, you'll need to build a new zone to store the updated configurations (or you can use any of the secure default zones available).

Create a suitable zone name first (in our case, we have used mariadb-access to allow access to the MySQL database server).

$firewall-cmd --new-zone=mariadb-access --permanent

To implement the new modification, reload the firewalld settings.

firewall-cmd --zone=mariadb-access --add-source=remoteCLIENT_IP --permanent

firewall-cmd --zone=mariadb-access --add-port=3306/tcp --permanent

firewall-cmd --reload

To check the result:

$ firewall-cmd --zone=mariadb-access --list-all

Whitelisting an IP addressโ€‹

Execute the following command to enable a single IP address, such as 22.33.44.55, to get through the firewall:

sudo firewall-cmd --permanent --add-source=22.33.44.55

Blocking an IP addressโ€‹

'Rich rules' are used to block an IP address. For example to block the IP 192.168.2.80 run the command:

firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='192.168.2.80' reject"
firewall-cmd --reload

Remove the FirewallD ruleโ€‹

If you are familiar with iptables earlier and wish to combine your understanding of iptables with the features of firewalld, direct rules can assist you with this. To begin with, if we wish to apply a rule on the INPUT chain, we can use the following command to verify the existing settings:

warning

If you are unfamiliar with iptables, it is risky to utilize the direct interface since you may mistakenly penetrate the firewall.

firewall-cmd --direct --get-rules ipv4 filter INPUT

If no rules are added previously, the output should be empty. Let's add a new rule with zero priority for test purposes.

firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -p tcp --dport 3128 -j ACCEPT
firewall-cmd --reload
tip

The /etc/firewalld/direct.xml file contains all of the firewalld direct rules. We may also delete the rules by editing this file.

The major purpose of rules is to control the traffic that is permitted. We may also set rules that are temporary or permanent. Let's look at how we can remove the rules out of firewalld now.

To delete a firewall rule temporarily, the following syntax can be used:

firewall-cmd --direct --remove-rule
firewall-cmd --permanent --direct --remove-rule ipv4 filter INPUT 0 -p tcp --dport 3128 -j ACCEPT

To remove the rules permanently, run the next command:

firewall-cmd [--permanent] --direct --remove-rules { ipv4 | ipv6 | eb } table chain
firewall-cmd --permanent --direct --remove-rule ipv4 filter INPUT 0 -p tcp --dport 3128 -j ACCEPT

How Do I Add a Port to FirewallDโ€‹

Although the general configuration and services are mostly enough for most of the cases, we may need to add some ports when the defined services are not enough and also when we are seeking a quick and easy solution. Firewalld allows us to change the status of a port even if the related service is not enabled.

For instance, if we want to add port 3000 while using TCP protocol, we may type the following command:

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

You should see the output similar to this:

Success

And to check the changes we use, run the next command:

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

You should see the output similar to this:

3000/tcp

Another case can be adding multiple sequential ports at a time, using firewall-cmd add port command. For instance, if we need to open ports 2000 to 2005 while using UDP protocol, we have to type;

firewall-cmd --zone=public --add-port=2000-2005/udp

We'll probably want to add these to the permanent firewall when we've tested them. You can do so by typing the following:

firewall-cmd --zone=public --permanent --add-port=3000/tcp
firewall-cmd --zone=public --permanent --add-port=2000-20005/udp
firewall-cmd --zone=public --permanent --list-ports

You should see the output similar to this:

3000/tcp 2000-2005/udp

We can add some known ports like SSH and HTTP ports etc. Here is how we add the ssh port to firewalld without adding a service:

In case we don't know the SSH port, we can check the ssh.xml file following /usr/lib/firewalld/services/ path and see the related line <port protocol="tcp" port="22"/>.

Now we can add the ssh port to our public zone:

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

firewall-cmd --reload
warning

For security reasons, it is not advised to make the SSH service publicly available. You should restrict it only accessible by trusted IP addresses.

If we follow the same steps for HTTP port we can add HTTP port to our zone without adding http service.

We will see that the HTTP port is 80 in our related http.xml file. <port protocol="tcp" port="80"/>

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

firewall-cmd --reload

At this point, we used this method for an easy and quick solution. Keep in mind that using this method can make it harder to keep track of changes, in case a lot of them are made. For that reason, using services may be a better solution most of the time.

How Do I Permanently Disable the Firewall in CentOS 7โ€‹

It is mostly recommended to keep Firewalld service enabled except for some testing purposes. In that case, it may be stopped and disabled. In this part, we are going to show how to disable Firewalld on CentOS 7.

The first step is to check the status of the firewall.

firewall-cmd --state

You should see the output similar to this:

Running

The second step is going to stop the Firewall temporarily. It means it is going to be effective for the current session. It will be enabled following a reboot.

systemctl stop firewalld

Follow the instructions below to permanently disable the firewall on your CentOS 7 system:

systemctl disable firewalld

You should see the output similar to this:

Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.

Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.Copy

To prevent FirewallD service from being started by other services, we mask the firewalld service.

systemctl mask --now firewalld

The mask command simply creates a symlink from the firewalld service to /dev/null, as shown in the output:

Created symlink from /etc/systemd/system/firewalld.service to /dev/null.Copy

What are the Problems and Solutions While Installing a Firewall on CentOS 7?โ€‹

Here we will give some troubleshooting tips for firewalld installation.

Failed to start firewalld.serviceโ€‹

One common problem is while starting or enabling firewalld service, mostly happens when you try to enable firewalld which is installed before but disabled and later.

systemctl enable firewalld

You may see the output similar to this:

Failed to execute operation: Cannot send after transport endpoint shutdown
systemctl start firewalld

You may see the output similar to this:

Failed to start firewalld.service: Unit is masked.

The first thing to do is to check if the service is masked, using the command:

systemctl unmask firewalld

You should see the output similar to this:

Removed symlink /etc/systemd/system/firewalld.service

The above command will probably solve the problem in most cases. Now we can start the firewalld service again.

systemctl start firewalld

To check if the service started and running we type:

systemctl list-units --type=service|grep firewalld

firewalld.serv?ce loaded active running firewalld - dynamic firewall daemon

From the output we see that firewalld service has started. If the service hasn't started, the result of the command above will return empty. It means your firewalld service is not invoked yet. In that case, unmasking can be repeated.

systemctl unmask firewalld

If the mask symbolic link is broken, an error message may be raised. If so, trying to mask the link manually may be helpful. To do so:

ln -s /etc/systemd/system/firewalld.service /dev/null

Unmasking should be tried again after solving the symlink problem.

Disable iptables service before setting firewalld service upโ€‹

Another issue to face may be trying to use firewalld service while iptables service is in use. Iptables service can be disabled before setting firewalld service up. Here are the commands to stop iptables service and disable.

systemctl stop iptables
systemctl disable iptables

Conclusionโ€‹

In this article, we covered how to set the firewall using firewalld on CentOS 7 Linux, even though there may be slight differences between releases of the operating system.

We tried to use the flexibility advantage of firewalld. Managing a firewall seems more comfortable compared to iptables. We tried to set rules for our zones and assign them to interfaces. You are familiar with basic concepts and settings about firewalld service on CentOS 7 by now.