Configure CentOS 8 Firewall with firewalld and firewall-cmd
A firewall is one of the most fundamental ways to monitor and filter incoming and outgoing traffic. A set of inbound and outbound rules defined within firewall settings, determine which traffic to allow or block.
On CentOS and other Linux distros, firewalld is the default firewall management software. In the following tutorial, we will start by discussing the basic firewalld concepts, and then use it to configure a firewall on CentOS 8.
Get to know firewalld
Before we start playing around with firewalld, let’s first get to know it better.
Zones in firewalld
Firewalld has a set of predefined rules, known as zones, which help you define the level of trust you have in a particular network. Associating a network interface with a zone determines the nature of allowed behavior. To understand this a bit better, let’s look at a few default firewalld zones:
- Trusted: Highest level of trust. Allow incoming and outgoing traffic to all the machines in this network.
- Home: For home networks. Trust all the other machines on the network. Allow only a few incoming connections.
- Work: For work environments. Trust all machines, and allow only approved incoming connections.
- External: Configured when using firewall as a gateway. NAT masquerading is used to ensure that the internal network topology is hidden, but the servers are still reachable.
- Public: Trust no-one by default. Allow a handful of incoming connections, based on need.
- Drop: Lowest trust level. Drop every incoming packet without replying. Only allow outgoing traffic.
Firewall-cmd
Firewall-cmd is the command-line utility for the firewalld daemon. It’s used to define or change the firewalld configurations.
Services in firewalld
Services are a set of existing rules that can be applied within a zone. They are a great way to apply different rules, all at once. We will explore these in more detail in later sections.
Runtime vs permanent settings in firewalld
Firewalld allows you to define two kinds of settings: runtime and permanent. Runtime is the currently running configuration, which is reverted to the permanent configuration-set upon reboot.
By default, when you use firewall-cmd to configure your firewall, the changes are made to the runtime configuration set. To make changes permanent, you can add the --permanent
option to the command.
Configure firewalld on CentOS 8
Now that we are somewhat acquainted with firewalld, let’s start configuring it on a CentOS 8 machine.
Prerequisites
- A CentOS 8 server.
- A user with
sudo
privileges.
Install and enable firewalld
Firewalld comes pre-installed in most Linux distributions, including CentOS 8. To confirm, run:
sudo yum list installed | grep firewalld
If firewalld is installed on your machine, you should get some output like below.
firewalld.noarch 0.8.0-4.el8 @anaconda firewalld-filesystem.noarch 0.8.0-4.el8 @anaconda
If you don’t get anything, then run the following command to install firewalld:
sudo yum install firewalld
The next step is to enable firewalld and make it start at boot. To do so, run:
sudo systemctl enable firewalld
Finally, reboot your machine:
reboot
Once your server reboots, use the following command to verify that firewalld is indeed running:
sudo firewall-cmd –state
You should see the server output running
.
Get to know the defaults
Now, let’s try to explore the currently active firewalld configurations.
To see the default zone:
sudo firewall-cmd --get-default-zone
You should see that public
is set.
To see the active zones:
sudo firewall-cmd --get-active-zones
Since we haven’t set any other zone yet, this should also give us public
.
Output public interfaces: ens3
We can also see that our only network interface on the server ens3
is currently being managed in the public zone.
To see all the rules applicable to the pubic zone, run:
sudo firewall-cmd --list-all
Output public (active) target: default icmp-block-inversion: no interfaces: ens3 sources: services: cockpit dhcpv6-client ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
We can see, among other things, that the rules allow for direct SSH into the machine via the ens3 interface.
To see the other available zones, run:
sudo firewall-cmd --get-zones
block dmz drop external home internal public trusted work
You can also see the default rules for each zone. E.g., to view all the rules for the zone home:
sudo firewall-cmd --zone=home --list-all
Output home target: default icmp-block-inversion: no interfaces: sources: services: cockpit dhcpv6-client mdns samba-client ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
Change the default zone
The default zone applies to everything that’s not explicitly assigned to any zone. E.g., if there is a source, network interface, or connection that can’t be bound to any configured zones, firewalld will use the default zone rules for it.
To change the default zone:
sudo firewall-cmd --set-default-zone=home
Output success
Check:
sudo firewall-cmd --get-default-zone
Output home
Change the zone for an interface
To change the zone for an interface:
sudo firewall-cmd --zone=internal --change-interface=ens3
The above command will activate the zone internal
for the interface ens3
.
Output success
Change a zone’s target
A zone’s target defines its default behaviour, when dealing with incoming traffic that can’t be categorized, according to any specified rule. A target can either be DROP, ACCEPT, REJECT, or default.
To change a zone’s target, you could use the following command:
sudo firewall-cmd --zone=internal --set-target=DROP
This will set the target for the internal zone to DROP
.
Create a custom zone
Firewalld also gives you the flexibility to define your own zone. This comes in very handy while defining application-specific rules.
To create a new zone named redis:
sudo firewall-cmd --new-zone=redis --permanent
We will also open a TCP port and allow access from only one source IP. Both these rules will be made permanent.
sudo firewall-cmd --zone=redis --add-port=10003/tcp --permanent
sudo firewall-cmd --zone=redis --add-source=192.168.123.1/32 --permanent
Finally, restart the firewalld daemon to apply the changes:
sudo firewall-cmd reload
Output for all 4 above commands success
Apply services to a zone
Services allow us to apply a set of rules within a zone. Just like zones, there are some default services that you can use. To see them all:
sudo firewall-cmd --get-services
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 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 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
To view more information about the services, you can read the respective xml configuration files present in the /usr/lib/firewalld/services
directory using less
and appending directory with a filename (listed below)
less /usr/lib/firewalld/services/filename.xml
Example command
sudo less /usr/lib/firewalld/services/grafana.xml
To view the full list of files below, run
sudo ls /usr/lib/firewalld/services
Ouput amanda-client.xml grafana.xml mysql.xml slp.xml amanda-k5-client.xml gre.xml new-service.xml smtp-submission.xml amqps.xml high-availability.xml nfs3.xml smtps.xml amqp.xml https.xml nfs.xml smtp.xml apcupsd.xml http.xml nmea-0183.xml snmptrap.xml audit.xml imaps.xml nrpe.xml snmp.xml bacula-client.xml imap.xml ntp.xml spideroak-lansync.xml bacula.xml ipp-client.xml nut.xml spotify-sync.xml bb.xml ipp.xml openvpn.xml squid.xml bgp.xml ipsec.xml ovirt-imageio.xml ssdp.xml bitcoin-rpc.xml ircs.xml ovirt-storageconsole.xml ssh.xml bitcoin-testnet-rpc.xml irc.xml ovirt-vmconsole.xml steam-streaming.xml bitcoin-testnet.xml iscsi-target.xml plex.xml svdrp.xml bitcoin.xml isns.xml pmcd.xml svn.xml bittorrent-lsd.xml jenkins.xml pmproxy.xml syncthing-gui.xml ceph-mon.xml kadmin.xml pmwebapis.xml syncthing.xml ceph.xml kdeconnect.xml pmwebapi.xml synergy.xml cfengine.xml kerberos.xml pop3s.xml syslog-tls.xml cockpit.xml kibana.xml pop3.xml syslog.xml condor-collector.xml klogin.xml postgresql.xml telnet.xml ctdb.xml kpasswd.xml privoxy.xml tentacle.xml dhcpv6-client.xml kprop.xml prometheus.xml tftp-client.xml dhcpv6.xml kshell.xml proxy-dhcp.xml tftp.xml dhcp.xml kube-apiserver.xml ptp.xml tile38.xml distcc.xml ldaps.xml pulseaudio.xml tinc.xml dns-over-tls.xml ldap.xml puppetmaster.xml tor-socks.xml dns.xml libvirt-tls.xml quassel.xml transmission-client.xml docker-registry.xml libvirt.xml radius.xml upnp-client.xml docker-swarm.xml lightning-network.xml rdp.xml vdsm.xml dropbox-lansync.xml llmnr.xml redis-sentinel.xml vnc-server.xml elasticsearch.xml managesieve.xml redis.xml wbem-https.xml etcd-client.xml matrix.xml RH-Satellite-6.xml wbem-http.xml etcd-server.xml mdns.xml rpc-bind.xml wsmans.xml finger.xml memcache.xml rsh.xml wsman.xml freeipa-4.xml minidlna.xml rsyncd.xml xdmcp.xml freeipa-ldaps.xml mongodb.xml rtsp.xml xmpp-bosh.xml freeipa-ldap.xml mosh.xml salt-master.xml xmpp-client.xml freeipa-replication.xml mountd.xml samba-client.xml xmpp-local.xml freeipa-trust.xml mqtt-tls.xml samba-dc.xml xmpp-server.xml ftp.xml mqtt.xml samba.xml zabbix-agent.xml ganglia-client.xml mssql.xml sane.xml zabbix-server.xml ganglia-master.xml ms-wbt.xml sips.xml git.xml murmur.xml sip.xml
To add a service to a zone, use:
sudo firewall-cmd --zone=internal --add-service=http
Output success
Above command will allow http traffic on all the interfaces in the internal
zone.
Similarly, if you are planning to use your server as a DNS, you can add the DNS service:
sudo firewall-cmd --zone=internal --add-service=dns
Output success
Create a custom service
Just like you can create a custom zone, you can also create a custom service. Here are the steps:
- Create a new XML file in the
/usr/lib/firewalld/services
directory.sudo touch /usr/lib/firewalld/services/new-service.xml
- Enter the relevant details in the XML file and save.
- Reload the firewalld daemon so that it notices the newly created service.
sudo firewall-cmd reload
You should now be able to apply the new service, just like any other.
Open IPs and ports
To enable all incoming traffic from an IP address or range, within a zone, without having to create a new service:
sudo firewall-cmd --zone=internal --add-source=192.168.123.1 --permanent
To remove the IP, just replace --add-source
with --remove-source
.
sudo firewall-cmd --zone=internal --remove-source=192.168.123.1 --permanent
Similarly, if you want to allow all incoming traffic on a specific port:
sudo firewall-cmd --zone=internal --add-port=8081/tcp --permanent
and to remove the port:
sudo firewall-cmd --zone=internal --remove-port=8081/tcp --permanent
Output success
Save runtime configurations permanently
If at any time you wish to persist your runtime settings, before a reboot washes them away, you can use the following command:
sudo firewall-cmd --runtime-to-permanent
Output success