Firewalld is a complete firewall solution available by default on CentOS 7 servers. In this guide, we will cover how to set up a firewall for your server and show you the basics of managing the firewall with thefirewall-cmd
administrative tool (if you'd rather use iptables
with CentOS, follow this guide).
Before we begin talking about how to actually use the firewall-cmd
utility to manage your firewall configuration, we should get familiar with a few basic concepts that the tool introduces.
The firewalld
daemon manages groups of rules using entities called "zones". Zones are basically sets of rules dictating what traffic should be allowed depending on the level of trust you have in the networks your computer is connected to. Network interfaces are assigned a zone to dictate the behavior that the firewall should allow.
For computers that might move between networks frequently (like laptops), this kind of flexibility provides a good method of changing your rules depending on your environment. You may have strict rules in place prohibiting most traffic when operating on a public WiFi network, while allowing more relaxed restrictions when connected to your home network. For a server, these zones are not as immediately important because the network environment rarely, if ever, changes.
Regardless of how dymaic your network environment may be, it is still useful to be familiar with the general idea behind each of the pre-defined zones for firewalld
. In order from least trusted to most trusted, the pre-defined zones within firewalld
are:
icmp-host-prohibited
or icmp6-adm-prohibited
message.To use the firewall, we can create rules and alter the properties of our zones and then assign our network interfaces to whichever zones are most appropriate.
In firewalld, rules can be designated as either permanent or immediate. If a rule is added or modified, by default, the behavior of the currently running firewall is modified. At the next boot, the old rules will be reverted.
Most firewall-cmd
operations can take the --permanent
flag to indicate that the non-ephemeral firewall should be targeted. This will affect the rule set that is reloaded upon boot. This separation means that you can test rules in your active firewall instance and then reload if there are problems. You can also use the --permanent
flag to build out an entire set of rules over time that will all be applied at once when the reload command is issued.
Before we can begin to create our firewall rules, we need to actually turn the daemon on. The systemd
unit file is called firewalld.service
. We can start the daemon for this session by typing:
We can verify that the service is running and reachable by typing:
This indicates that our firewall is up and running with the default configuration.
At this point, we will not enable
the service. Enabling the service would cause the firewall to start up at boot. We should wait until we have created our firewall rules and had an opportunity to test them before configuring this behavior. This can help us avoid being locked out of the machine if something goes wrong.
Before we begin to make modifications, we should familiarize ourselves with the default environment and rules provided by the daemon.
We can see which zone is currently selected as the default by typing:
Since we haven't given firewalld
any commands to deviate from the default zone, and none of our interfaces are configured to bind to another zone, that zone will also be the only "active" zone (the zone that is controlling the traffic for our interfaces). We can verify that by typing:
Here, we can see that we have two network interfaces being controlled by the firewall (eth0
and eth1
). They are both currently being managed according to the rules defined for the public zone.
How do we know what rules are associated with the public zone though? We can print out the default zone's configuration by typing:
We can tell from the output that this zone is both the default and active and that the eth0
and eth1
interfaces are associated with this zone (we already knew all of this from our previous inquiries). However, we can also see that this zone allows for the normal operations associated with a DHCP client (for IP address assignment) and SSH (for remote administration).
Now we have a good idea about the configuration for the default and active zone. We can find out information about other zones as well.
To get a list of the available zones, type:
We can see the specific configuration associated with a zone by including the --zone=
parameter in our--list-all
command:
You can output all of the zone definitions by using the --list-all-zones
option. You will probably want to pipe the output into a pager for easier viewing:
Unless you have configured your network interfaces otherwise, each interface will be put in the default zone when the firewall is booted.
You can transition an interface between zones during a session by using the --zone=
parameter in combination with the --change-interface=
parameter. As with all commands that modify the firewall, you will need to use sudo
.
For instance, we can transition our eth0
interface to the "home" zone by typing this:
We can verify that this was successful by asking for the active zones again:
If the firewall is completely restarted, the interface will revert to the default zone:
Interfaces will always revert to the default zone if they do not have an alternative zone defined within their configuration. On CentOS, these configurations are defined within the /etc/sysconfig/network-scripts
directory with files of the format ifcfg-interface
.
To define a zone for the interface, open up the file associated with the interface you'd like to modify. We'll demonstrate making the change we showed above permanent:
At the bottom of the file, set the ZONE=
variable to the zone you wish to associate with the interface. In our case, this would be the "home" interface:
. . .
DNS1=2001:4860:4860::8844
DNS2=2001:4860:4860::8888
DNS3=8.8.8.8
ZONE=home
Save and close the file.
To implement your changes, you'll have to restart the network service, followed by the firewall service:
After your firewall restarts, you can see that your eth0
interface is automatically placed in the "home" zone:
Make sure to revert these changes if this is not the actual zone you'd like to use for this interface.
If all of your interfaces can best be handled by a single zone, it's probably easier to just select the best default zone and then use that for your configuration.
You can change the default zone with the --set-default-zone=
parameter. This will immediately change any interface that had fallen back on the default to the new zone:
The basic way of defining firewall exceptions for the services you wish to make available is easy. We'll run through the basic idea here.
The easiest method is to add the services or ports you need to the zones you are using. Again, you can get a list of the available services with the --get-services
option:
You can get more details about each of these services by looking at their associated .xml
file within the /usr/lib/firewalld/services
directory. For instance, the SSH service is defined like this:
SSH
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.
You can enable a service for a zone using the --add-service=
parameter. The operation will target the default zone or whatever zone is specified by the --zone=
parameter. By default, this will only adjust the current firewall session. You can adjust the permanent firewall configuration by including the --permanent
flag.
For instance, if we are running a web server serving conventional HTTP traffic, we can allow this traffic for interfaces in our "public" zone for this session by typing:
You can leave out the --zone=
if you wish to modify the default zone. We can verify the operation was successful by using the --list-all
or --list-services
operations:
Once you have tested that everything is working as it should, you will probably want to modify the permanent firewall rules so that your service will still be available after a reboot. We can make our "public" zone change permanent by typing:
You can verify that this was successful by adding the --permanent
flag to the --list-services
operation. You need to use sudo
for any --permanent
operations:
Your "public" zone will now allow HTTP web traffic on port 80. If your web server is configured to use SSL/TLS, you'll also want to add the https
service. We can add that to the current session and the permanent rule-set by typing:
The firewall services that are included with the firewalld installation represent many of the most common requirements for applications that you may wish to allow access to. However, there will likely be scenarios where these services do not fit your requirements.
In this situation, you have two options.
The easiest way to add support for your specific application is to open up the ports that it uses in the appropriate zone(s). This is as easy as specifying the port or port range, and the associated protocol for the ports you need to open.
For instance, if our application runs on port 5000 and uses TCP, we could add this to the "public" zone for this session using the --add-port=
parameter. Protocols can be either tcp
or udp
:
We can verify that this was successful using the --list-ports
operation:
It is also possible to specify a sequential range of ports by separating the beginning and ending port in the range with a dash. For instance, if our application uses UDP ports 4990 to 4999, we could open these up on "public" by typing:
After testing, we would likely want to add these to the permanent firewall. You can do that by typing:
Opening ports for your zones is easy, but it can be difficult to keep track of what each one is for. If you ever decommission a service on your server, you may have a hard time remembering which ports that have been opened are still required. To avoid this situation, it is possible to define a service.
Services are simply collections of ports with an associated name and description. Using services is easier to administer than ports, but requires a bit of upfront work. The easiest way to start is to copy an existing script (found in /usr/lib/firewalld/services
) to the /etc/firewalld/services
directory where the firewall looks for non-standard definitions.
For instance, we could copy the SSH service definition to use for our "example" service definition like this. The filename minus the .xml
suffix will dictate the name of the service within the firewall services list:
Now, you can adjust the definition found in the file you copied:
sudo nano /etc/firewalld/services/example.xml
To start, the file will contain the SSH definition that you copied:
SSH
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.
The majority of this definition is actually metadata. You will want to change the short name for the service within the
tags. This is a human-readable name for your service. You should also add a description so that you have more information if you ever need to audit the service. The only configuration you need to make that actually affects the functionality of the service will likely be the port definition where you identify the port number and protocol you wish to open. This can be specified multiple times.
For our "example" service, imagine that we need to open up port 7777 for TCP and 8888 for UDP. We could modify the existing definition with something like this:
Example Service
This is just an example service. It probably shouldn't be used on a real system.
tcp" port="7777"/>
udp" port="8888"/>
Save and close the file.
Reload your firewall to get access to your new service:
You can see that it is now among the list of available services:
You can now use this service in your zones as you normally would.
While the predefined zones will probably be more than enough for most users, it can be helpful to define your own zones that are more descriptive of their function.
For instance, you might want to create a zone for your web server, called "publicweb". However, you might want to have another zone configured for the DNS service you provide on your private network. You might want a zone called "privateDNS" for that.
When adding a zone, you must add it to the permanent firewall configuration. You can then reload to bring the configuration into your running session. For instance, we could create the two zones we discussed above by typing:
You can verify that these are present in your permanent configuration by typing:
As stated before, these won't be available in the current instance of the firewall yet:
Reload the firewall to bring these new zones into the active configuration:
Now, you can begin assigning the appropriate services and ports to your zones. It's usually a good idea to adjust the active instance and then transfer those changes to the permanent configuration after testing. For instance, for the "publicweb" zone, you might want to add the SSH, HTTP, and HTTPS services:
Likewise, we can add the DNS service to our "privateDNS" zone:
We could then change our interfaces over to these new zones to test them out:
At this point, you have the opportunity to test your configuration. If these values work for you, you will want to add the same rules to the permanent configuration. You can do that by re-applying the rules with the --permanent
flag:
You can then modify your network interfaces to automatically select the correct zones.
We can associate the eth0
interface with the "publicweb" zone:
[label /etc/sysconfig/network-scripts/ifcfg-eth0
. . .
IPV6_AUTOCONF=no
DNS1=2001:4860:4860::8844
DNS2=2001:4860:4860::8888
DNS3=8.8.8.8
ZONE=publicweb
And we can associate the eth1
interface with "privateDNS":
. . .
NETMASK=255.255.0.0
DEFROUTE='no'
NM_CONTROLLED='yes'
ZONE=privateDNS
Afterwards, you can restart your network and firewall services:
Validate that the correct zones were assigned:
And validate that the appropriate services are available for both of the zones:
You have successfully set up your own zones. If you want to make one of these zones the default for other interfaces, remember to configure that behavior with the --set-default-zone=
parameter:
sudo firewall-cmd --set-default-zone=publicweb
At the beginning of the guide, we started our firewalld service, but we did not enable it. If you are happy with your current configuration and have tested that it is functional when you restart the service, you can safely enable the service.
To configure your firewall to start at boot, type:
When the server restarts, your firewall should be brought up, your network interfaces should be put into the zones you configured (or fall back to the configured default zone), and the rules associated with the zone(s) will be applied to the associated interfaces.
You should now have a fairly good understanding of how to administer the firewalld service on your CentOS system for day-to-day use.
The firewalld service allows you to configure maintainable rules and rule-sets that take into consideration your network environment. It allows you to seamlessly transition between different firewall policies through the use of zones and gives administrators the ability to abstract the port management into more friendly service definitions. Acquiring a working knowledge of this system will allow you to take advantage of the flexibility and power that this tool provides.