firewalld 101
20 November 2015
firewalld provides a dynamically managed firewall with support for network/firewall zones to define the trust level of network connections or interfaces. It has support for IPv4, IPv6 firewall settings and for ethernet bridges and has a separation of runtime and permanent configuration options. It also supports an interface for services or applications to add firewall rules directly.
The two important concepts of firewalld is zones and services.
A zone defines the trust level of the interface used for a connection. There are several pre-defined zones provided by firewalld.zone.
A service can be a list of local ports and destinations and additionally also a list of firewall helper modules automatically loaded if a service is enabled. Service configuration options and generic information about services are described in firewalld.service. The use of predefined services makes it easier for the user to enable and disable access to a service.
$ firewall-cmd --get-zones
block dmz drop external home internal public trusted work
In order from least trusted to most trusted, the pre-defined zones within firewalld are:
Zone | Definition |
---|---|
drop | The lowest level of trust. All incoming connections are dropped without reply and only outgoing connections are possible |
block | Similar to the above, but instead of simply dropping connections, incoming requests are rejected with an icmp-host-prohibited or icmp6-adm-prohibited message |
public | Represents public, untrusted networks. You don't trust other computers but may allow selected incoming connections on a case-by-case basis |
external | External networks in the event that you are using the firewall as your gateway. It is configured for NAT masquerading so that your internal network remains private but reachable |
internal | The other side of the external zone, used for the internal portion of a gateway. The computers are fairly trustworthy and some additional services are available |
dmz | Used for computers located in a DMZ (isolated computers that will not have access to the rest of your network). Only certain incoming connections are allowed |
work | work: Used for work machines. Trust most of the computers in the network. A few more services might be allowed |
home | A home environment. It generally implies that you trust most of the other computers and that a few more services will be accepted |
trusted | Trust all of the machines in the network. The most open of the available options and should be used sparingly |
Changing the zone of your interface permanently
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.
$ firewall-cmd --list-all
public (default, active)
interfaces: enp0s3
sources:
services: dhcpv6-client ssh
ports:
masquerade: no
forward-ports:
icmp-blocks:
rich rules:
You will see from the output that I have a public zone applied to enp0s3. I will then open /etc/sysconfig/network-scripts/ifcfg-enp0s3 to add zone at the bottom.
TYPE="Ethernet"
BOOTPROTO="dhcp"
DEFROUTE="yes"
PEERDNS="yes"
PEERROUTES="yes"
IPV4_FAILURE_FATAL="no"
IPV6INIT="yes"
IPV6_AUTOCONF="yes"
IPV6_DEFROUTE="yes"
IPV6_PEERDNS="yes"
IPV6_PEERROUTES="yes"
IPV6_FAILURE_FATAL="no"
NAME="enp0s3"
UUID="d51651b7-8f3a-4ee0-bee4-3b58f9e356b7"
DEVICE="enp0s3"
ONBOOT="yes"
ZONE=home
To implement your changes, you'll have to restart the network service, followed by the firewall service:
$ sudo systemctl restart network.service
$ sudo systemctl restart firewalld.service
Adjusting the Default Zone
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.
$ sudo firewall-cmd --set-default-zone=home
success
$ firewall-cmd --list-all
home (default, active)
interfaces: enp0s3
sources:
services: dhcpv6-client ipp-client mdns samba-client ssh
ports:
masquerade: no
forward-ports:
icmp-blocks:
rich rules:
Adding a Service to your Zones
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.
$ 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
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.
$ sudo firewall-cmd --zone=home --add-service=http
success
$ firewall-cmd --zone=home --list-services
dhcpv6-client http ipp-client mdns samba-client ssh
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.
$ sudo firewall-cmd --zone=home --permanent --add-service=http
success
$ sudo firewall-cmd --zone=home --permanent --list-services
dhcpv6-client http ipp-client mdns samba-client ssh
Opening a Port for your Zones
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 4000 and uses TCP, we could add this to the "home" zone for this session using the --add-port= parameter. Protocols can be either tcp or udp.
$ sudo firewall-cmd --zone=home --add-port=4000/tcp
After testing, you would likely want to add these to the permanent firewall.
$ sudo firewall-cmd --zone=home --permanent --add-port=4000/tcp
success
$ sudo firewall-cmd --zone=home --permanent --list-ports
4000/tcp
Defining a Service
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 /usr/lib/firewalld/services
to the /etc/firewalld/services
directory
where the firewall looks for non-standard definitions.
$ sudo cp /usr/lib/firewalld/services/http.xml /etc/firewalld/services/webrick.xml
$ sudo vi /etc/firewalld/services/webrick.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>webrick</short>
<description>Ruby's default HTTP server.This is single threaded which means can only process single request at a time.</description>
<port protocol="tcp" port="4000"/>
</service>
$ sudo firewall-cmd --reload
success
$ 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 webrick
Creating Your Own Zones
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.
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, I could create a zone by typing
$ sudo firewall-cmd --permanent --new-zone=
success
$ sudo firewall-cmd --permanent --get-zones
block dmz drop external home internal public publicweb trusted work