Overview
By the end of this article you should be able to answer the following questions:
Announcement
You can find all my latest posts on medium.$ systemctl status firewalld
$ firewall-cmd –-get-zones
$ firewall-cmd –-get-default-zone
$ firewall-cmd –-get-active-zones
$ firewall-cmd –-zone=public –-list-all
$ firewall-cmd –-zone=public –-add-source=192.168.50.0/24 –-permanent
# then restart the firewalld service to load in the change
$ systemctl restart firewalld
$ firewall-cmd –-get-services
$ firewall-cmd –-add-service=http –-zone=public –-permanent
$ systemctl restart firewalld # load in the new change
$ firewall-cmd –-add-port=80/tcp –-permanent –-zone=public
$ systemctl restart firewalld
$ firewall-cmd –-list-all
/usr/lib/firewalld/services/
/etc/firewalld/services
$ firewall-config
A firewall is a software that controls what network traffic is allowed to pass through. CentOS 7 comes with a firewall software called firewalld, which is installed by default on a standard CentOS 7 machine. However just in case it isn’t installed, then you can install it by running:
$ yum install firewalld firewall-config
firewall-config is optional and it is gui interface for configuring firewalld. Firewalld itself is fully configurable by it’s command line utility, which is called firewall-cmd.
Firewalld runs in the form of a service:
$ systemctl status firewalld firewalld.service - firewalld - dynamic firewall daemon Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled) Active: active (running) since Sat 2015-06-20 07:20:30 BST; 1 day 7h ago Main PID: 611 (firewalld) CGroup: /system.slice/firewalld.service └─611 /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid Jun 20 07:20:26 localhost.localdomain systemd[1]: Starting firewalld - dynamic firewall daemon... Jun 20 07:20:30 localhost.localdomain systemd[1]: Started firewalld - dynamic firewall daemon.
The main way to manage and configure firewalld is via the firewall-cmd command, more about firewall-cmd later on.
Firewalld isn’t just a firewall software, it also has a few network routing related features too. Here are the main firewalld features:
- Allow data packets into and out of a system.
- Reject data packets that fails to satisfy the allow rules
- Drop data packets without sending a response message to the source device
- Can do port forwarding – i.e. can associate a port to a specific device on the network, so that network traffic is routed to/from that device, if source device is trying to interact with the given port
- Can act as a router to forward data packets between 2 or more local networks (more about this in the RHCE course). This means it can perform the function of Network Address Translation (NAT). In Firewalld, NAT is referred to as masquarading
When it comes to firewalld, it’s quite common to regularly change the firewalld’s settings. For example let’s say you have a CentOS 7 laptop with firewalld is running on it. You might want to change the firewalld settings when at your workplace, then change it again when you’re using the laptop at home, then change it again when you are connecting to a public wifi, e.g. at a coffee shop. Manually changing the firewalld settings this frequently can get really tedious, especially considering that the firewalld settings are written in xml format. That’s why firewalld comes equipped with the ability to have multiple versions of these xml files, and you can tell firewalld which version of xml file to load in. Therefore firewalld essentially let’s you switch between one firewalld mode to another. In firewalld, these modes are referred to as ‘zones’.
Firewalld comes included with a list of generic zones. You can list these zones using firewall-cmd:
$ firewall-cmd --get-zones | sed 's/ /\n/g' work drop internal external trusted home dmz public block
Note: I piped it the sed command to makes it easier to read.
The underlying xml files for each of these zones can be found here:
$ pwd /usr/lib/firewalld/zones $ ll total 36 -rw-r--r--. 1 root root 299 May 25 20:21 block.xml -rw-r--r--. 1 root root 293 May 25 20:21 dmz.xml -rw-r--r--. 1 root root 291 May 25 20:21 drop.xml -rw-r--r--. 1 root root 304 May 25 20:21 external.xml -rw-r--r--. 1 root root 369 May 25 20:21 home.xml -rw-r--r--. 1 root root 384 May 25 20:21 internal.xml -rw-r--r--. 1 root root 315 May 25 20:21 public.xml -rw-r--r--. 1 root root 162 May 25 20:21 trusted.xml -rw-r--r--. 1 root root 311 May 25 20:21 work.xml
To find out which zone is currently active, we run:
$ firewall-cmd --get-active-zones public interfaces: enp0s3 enp0s8 enp0s9
This shows that that the zone ‘public’ is active and that this firewall zone is controlling the network traffic that are passing through the enp0s3, enp0s8, and enp0s9 interfaces. The cool thing with the concept of zones is that you can have multiple active zones. for example each zone being attached to a specific interface or whitelist a particular ip range. Also to make a zone active, you simply needs to populate one of the following zone settings:
- interface (e.g. firewall-cmd –zone=trusted –add-interface=enp0s8)
- source (e.g. firewall-cmd –zone=dmz –add-source=10.0.0.0/24)
To get the full details of a given zone’s settings, we run:
$ firewall-cmd --zone=public --list-all public (active) target: default icmp-block-inversion: no interfaces: enp0s3 enp0s8 enp0s9 sources: services: dhcpv6-client ssh ports: protocols: masquerade: no forward-ports: sourceports: icmp-blocks: rich rules:
The –list-all option gives an overview of the entire zone, i.e. which interfaces is being controlled by this zone, what services are allowed to send+receive data in this zone.
Note that the public zone shown above is also the default zone, you can see this more clearly by running:
$ firewall-cmd --get-default-zone public
Changing Firewalld settings
You can configure a zone’s settings using firewall-cmd. firewall-cmd can either persistent and non-persistent changes.
However note, when making persistent changes with firewall-cmd, it effectively just makes changes to the firewalld internal config files but doesn’t load them in. So to activate a persistent change, you need to restart the firewalld service, so that it loads in the newly changed config files.
Here’s the “home” zone’s info:
[root@routingvm zones]# firewall-cmd --zone=home --list-all home target: default icmp-block-inversion: no interfaces: sources: services: dhcpv6-client mdns samba-client ssh ports: protocols: masquerade: no forward-ports: sourceports: icmp-blocks: rich rules:
In both the “home” and the “public” zones shown above, there isn’t any ip address restriction, however we can add one, like this:
$ firewall-cmd --zone=public --add-source=192.168.50.0/24 success
Now let’s check that an ip range restriction has now been applied:
$ firewall-cmd --zone=public --list-all public (active) target: default icmp-block-inversion: no interfaces: enp0s3 enp0s8 enp0s9 sources: 192.168.50.0/24 services: dhcpv6-client ssh ports: protocols: masquerade: no forward-ports: sourceports: icmp-blocks: rich rules:
However this change isn’t persistent, and is reverted when the the firewalld service is restarted:
$ systemctl restart firewalld.service $ firewall-cmd --list-all --zone=public public (default, active) interfaces: enp0s3 sources: services: dhcpv6-client ssh ports: masquerade: no forward-ports: icmp-blocks: rich rules:
To make this change persistant, you need to use the “–permenant” flag:
$ firewall-cmd --zone=public --add-source=192.168.50.0/24 --permanent success
However this change will take affect after a firewalld service restart:
$ firewall-cmd --list-all --zone=public public (default, active) interfaces: enp0s3 sources: services: dhcpv6-client ssh ports: masquerade: no forward-ports: icmp-blocks: rich rules: $ systemctl restart firewalld.service $ $ firewall-cmd --list-all --zone=public public (default, active) interfaces: enp0s3 sources: 192.168.50.0/24 services: dhcpv6-client ssh ports: masquerade: no forward-ports: icmp-blocks: rich rules:
Hence, using the “–permenant” setting is a bit like how systemctl’s “enable”, i.e. it only takes affect after a service restart. Therefore if you want to make a persistant change that also is active in the current firewalld.session, then you will need run the same firewall-cmd command twice, one without the –permenant option, and one with.
Notice above that the httpd service is not currently permitted in this zone. This means that we’ll get a connection timeout message when you try to open a web browser and access the vm’s web server’s homepage.
To fix this issue, we need to add the appropriate services to the zone. Let’s first see what services we have available:
$ firewall-cmd --get-services RH-Satellite-6 amanda-client bacula bacula-client dhcp dhcpv6 dhcpv6-client dns ftp high-availability http https imaps ipp ipp-client ipsec kerberos kpasswd ldap ldaps libvirt libvirt-tls mdns mountd ms-wbt mysql nfs ntp openvpn pmcd pmproxy pmwebapi pmwebapis pop3s postgresql proxy-dhcp radius rpc-bind samba samba-client smtp ssh telnet tftp tftp-client transmission-client vnc-server wbem-https
Now let’s add the httpd related services to the zone:
$ firewall-cmd --add-service=http --zone=public
success
$ firewall-cmd --add-service=http --zone=public --permanent
success
$ firewall-cmd --add-service=https
success
$ firewall-cmd --add-service=https --zone=public --permanent
success
$ firewall-cmd --list-all --zone=public
public (default, active)
interfaces: enp0s3
sources: 192.168.50.0/24
services: dhcpv6-client http https ssh
ports:
masquerade: no
forward-ports:
icmp-blocks:
rich rules:
After that you should now be able to access the websites.
Also instead of adding the http and https services to the zone, we could have added the ports, i.e.:
$ firewall-cmd --add-port=80/tcp --permanent --zone=public success $ firewall-cmd --add-port=443/tcp --zone=public success $ firewall-cmd --add-port=80/tcp --permanent --zone=public success $ firewall-cmd --add-port=443/tcp --permanent --zone=public success $ firewall-cmd --list-all public (default) interfaces: sources: services: dhcpv6-client ssh ports: 443/tcp 80/tcp masquerade: no forward-ports: icmp-blocks: rich rules:
Now in the context of firewalld, a service is something that is associated to a protocol and port, and it is not the traditional services such as httpd, sshd,…etc. Due to this new definition, a service can essentially be represented in the form of a an xml file. You can view a list of the default services by looking in the following directory:
$ ls /usr/lib/firewalld/services/ amanda-client.xml ftp.xml ipsec.xml mdns.xml pmcd.xml radius.xml tftp-client.xml bacula-client.xml high-availability.xml kerberos.xml mountd.xml pmproxy.xml rpc-bind.xml tftp.xml bacula.xml https.xml kpasswd.xml ms-wbt.xml pmwebapis.xml samba-client.xml transmission-client.xml dhcpv6-client.xml http.xml ldaps.xml mysql.xml pmwebapi.xml samba.xml vnc-server.xml dhcpv6.xml imaps.xml ldap.xml nfs.xml pop3s.xml smtp.xml wbem-https.xml dhcp.xml ipp-client.xml libvirt-tls.xml ntp.xml postgresql.xml ssh.xml dns.xml ipp.xml libvirt.xml openvpn.xml proxy-dhcp.xml telnet.xml
You can use one of these xml files as a template to create your own custom services (i.e. xml file), however your service does not go inside the above folder, instead it has to be placed in /etc/firewalld/services
folder. Here’s an example of what one of these xml files looks like:
$ cat /usr/lib/firewalld/services/ssh.xmlSSH 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.
In the world of firewalld, this xml file is referred to as a “service” because it associates a name (which in this case is name, ssh) to a protocol and a port number.
Using firewall-config
Finally you can do all of the above using the firewall-config GUI tool. From the terminal we run:
$ firewall-config
Useful Tip: you can make the changes using firewall-cmd, and then check whether the changes are what you expected by viewing the firewall-config gui.
See also: