Firewalld is a dynamic firewall application that provides a flexible way of setting up network filtering policies on a server by extending the kernel-based iptables functionality. It provides flexible configuration options, including zone-based firewall management policies that represent a specific level of trust depending on your server's network connections, to protect the system from unauthorized access. This guide walks through setting up firewall policies using Firewalld and configuring sample rules to filter network requests on a Linux server. By the end, you'll have Firewalld installed, zones and rules configured, and panic mode ready as a last-resort lockdown.
Prerequisites
Before you begin:
- A Rocky Linux (or other RHEL-based) server to use as the workstation.
- Access to the server using SSH as a non-root user with sudo privileges.
-
Update the server:
$ sudo dnf update
1. Install Firewalld
Firewalld is available as a default system package on most Red Hat-based server distributions such as CentOS, Rocky Linux, and AlmaLinux. When unavailable, follow the steps below to install and enable Firewalld to set up firewall filtering rules on the server.
1. Install Firewalld:
$ sudo dnf install firewalld
2. Enable the Firewalld application to start at boot time:
$ sudo systemctl enable firewalld
3. Start Firewalld:
$ sudo systemctl start firewalld
4. Verify that the Firewalld service is active and running:
$ sudo firewall-cmd --state
5. Save all runtime changes to the permanent Firewalld configuration:
$ sudo firewall-cmd --runtime-to-permanent
2. Set Up Firewalld Zones
Firewalld zones represent the level of trust for network connections associated with a specific network interface. Each zone includes a different security level and policies that govern the traffic flow on the associated interface. By default, Firewalld runs with the following zones:
-
public: Applies to public-facing interfaces connected to external networks such as the Internet. -
home: Applies to network interfaces associated with home networks or small office environments. -
work: Works with corporate or organization network interfaces with better security over the home zone. -
internal: Works with private interfaces connected to networks such as a VPC. -
external: Applies to external untrusted networks. It's similar to the public zone but applies a higher security level by blocking incoming connection requests while accepting outgoing network connections. -
dmz: Works with network interfaces connected to demilitarized zones partly connected to the Internet and filtered by a firewall. -
block: Blocks all incoming and outgoing network traffic. It's useful when troubleshooting server network interfaces or networking errors.
1. View all available Firewalld zones:
$ sudo firewall-cmd --get-zones
Output:
block dmz drop external home internal nm-shared public trusted work
2. View the default Firewalld zone:
$ sudo firewall-cmd --get-default-zone
Output:
public
3. View the active Firewalld zone and the associated server network interfaces:
$ sudo firewall-cmd --get-active-zones
Output:
public
interfaces: enp1s0
4. View the Firewalld zone assigned to a specific network interface. For example, view the enp8s0 network interface zone:
$ sudo firewall-cmd --get-zone-of-interface=enp8s0
5. Change an interface from one zone to another. For example, change the enp1s0 interface to the external zone:
$ sudo firewall-cmd --zone=home --change-interface=eth0
Output:
success
Switching interfaces between zones sets different firewall rules and policies on the network interface for troubleshooting or testing purposes on the server.
6. View the active zones again to verify that two Firewalld zones are active due to the new interface assignment:
$ sudo firewall-cmd --get-active-zones
Output:
home
interfaces: enp8s0
public
interfaces: enp1s0
7. View all firewall rules associated with the active zone. By default, public:
$ sudo firewall-cmd --list-all
Output:
public (active)
target: default
icmp-block-inversion: no
interfaces: enp1s0 enp8s0
sources:
services: cockpit dhcpv6-client ssh
ports:
protocols:
forward: yes
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
8. Change the active zone depending on your server networking environment. For example, change the Firewalld zone to external:
$ sudo firewall-cmd --change-zone=public
3. Set Up Firewall Policies using Firewalld
Firewalld accepts network ports, system services, and service names across multiple zones depending on your server interfaces. Every Firewalld zone, for example public, applies the set policies and rules to the associated interfaces. Follow the steps below to set up firewall policies using Firewalld on the server.
To delete Firewalld rules, replace the --add option with --remove to delete the rule. For example, delete the FTP port 21 policy in the public zone:
$ sudo firewall-cmd --zone=public --permanent --remove-port=22/tcp
Allow Network Ports
1. Add a new Firewalld rule that allows the SSH TCP port 22 through the public zone:
$ sudo firewall-cmd --zone=public --permanent --add-port=22/tcp
The above rule allows SSH access to the server using port 22 through the public zone. The rule is also permanently saved in the firewall table using the --permanent option.
2. Allow another service port, 80, through the firewall:
$ sudo firewall-cmd --zone=public --permanent --add-port=80/tcp
3. View the active Firewalld zone ports to verify the new rules:
$ sudo firewall-cmd --zone=public --list-ports
Output:
22/tcp 80/tcp
4. Allow a range of ports through the public Firewalld zone. For example, port 4990 to 4999 depending on your internal hosts:
$ sudo firewall-cmd --zone=public --permanent --add-port=4990-4999/udp
Allow System Services
1. View the list of available Firewalld services on your server:
$ sudo firewall-cmd --get-services
Output:
RH-Satellite-6 RH-Satellite-6-capsule afp amanda-client amanda-k5-client amqp amqps apcupsd audit ausweisapp2 bacula bacula-client bb bgp bitcoin bitcoin-rpc bitcoin-testnet bitcoin-testnet-rpc bittorrent-lsd ceph ceph-mon cfengine checkmk-agent cockpit collectd condor-collector cratedb ctdb dhcp dhcpv6 dhcpv6-client distcc dns dns-over-tls docker-registry docker-swarm dropbox-lansync elasticsearch etcd-client etcd-server finger foreman foreman-proxy freeipa-4 freeipa-ldap freeipa-ldaps freeipa-replication freeipa-trust ftp galera ganglia-client ganglia-master git gpsd grafana gre high-availability http http3 https ident imap imaps ipfs ipp ipp-client ipsec irc ircs iscsi-target isns jenkins kadmin kdeconnect kerberos kibana klogin kpasswd kprop kshell kube-api kube-apiserver kube-control-plane kube-control-plane-secure kube-controller-manager kube-controller-manager-secure kube-nodeport-services kube-scheduler kube-scheduler-secure kube-worker kubelet kubelet-readonly kubelet-worker ldap ldaps libvirt libvirt-tls lightning-network llmnr llmnr-tcp llmnr-udp managesieve matrix mdns memcache minidlna mongodb mosh mountd mqtt mqtt-tls ms-wbt mssql murmur mysql nbd netbios-ns netdata-dashboard nfs nfs3 nmea-0183 nrpe ntp nut openvpn ovirt-imageio ovirt-storageconsole ovirt-vmconsole plex pmcd pmproxy pmwebapi pmwebapis pop3 pop3s postgresql privoxy prometheus prometheus-node-exporter proxy-dhcp ps3netsrv ptp pulseaudio puppetmaster quassel radius rdp redis redis-sentinel rpc-bind rquotad rsh rsyncd rtsp salt-master samba samba-client samba-dc sane sip sips slp smtp smtp-submission smtps snmp snmptls snmptls-trap snmptrap spideroak-lansync spotify-sync squid ssdp ssh steam-streaming svdrp svn syncthing syncthing-gui synergy syslog syslog-tls telnet tentacle tftp tile38 tinc tor-socks transmission-client upnp-client vdsm vnc-server wbem-http wbem-https wireguard ws-discovery ws-discovery-client ws-discovery-tcp ws-discovery-udp wsman wsmans xdmcp xmpp-bosh xmpp-client xmpp-local xmpp-server zabbix-agent zabbix-server zerotier
2. Allow a service such as HTTPS for access through the public zone table:
$ sudo firewall-cmd --zone=public --add-service=https --permanent
3. Allow another service, such as FTP, through the public zone:
$ sudo firewall-cmd --zone=public --add-service=ftp --permanent
4. Reload Firewalld to apply the new service changes:
$ sudo firewall-cmd --reload
Output:
cockpit dhcpv6-client ftp http https ssh
Enable Forwarding and IP Address Rules
1. Allow incoming traffic to the SSH port 22 from your public server IP address 192.0.2.100:
$ sudo firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="192.0.2.100" port protocol="tcp" port="80" accept'
2. Forward traffic from one port to another. For example, forward traffic from the internal port 8080 to the destination port 8900 through all IP addresses:
$ sudo firewall-cmd --zone=public --add-forward-port=port=80:proto=tcp:toport=8080:toaddr=0.0.0.0 --permanent
The above rule forwards all incoming requests on port 8080 to 8900 to securely expose a specific resource on different ports.
3. Reload Firewalld to save the zone changes:
$ sudo firewall-cmd --reload
4. Create Custom Firewalld Zones
1. Create a new Firewalld zone with a custom name, such as example-zone:
$ sudo firewall-cmd --permanent --new-zone=example-zone
2. Reload Firewalld to save changes:
$ sudo firewall-cmd --reload
3. View the Firewalld zones and verify that the new custom zone is available:
$ sudo firewall-cmd --permanent --get-zones
Output:
block dmz drop example-zone external home internal nm-shared public trusted work
5. Firewalld Panic Mode
Firewalld panic mode blocks all incoming and outgoing network connections on the server to protect the system in case of security threats. When enabled, the server blocks all connections, including your active SSH session. Follow the steps below to enable panic mode and troubleshoot the system in case of external threats or network failures.
1. View the Firewalld panic mode status:
$ sudo firewall-cmd --query-panic
Output:
no
2. Enable panic mode to block all network connections on the server:
$ sudo firewall-cmd --panic-on
3. View the Firewalld panic mode status and verify that it's active:
$ sudo firewall-cmd --query-panic
Output:
yes
In case Firewalld blocks your SSH session, use your cloud provider's web console to start a new, out-of-band terminal session to the server.
Next Steps
- Audit your zone assignments with
firewall-cmd --get-active-zonesbefore opening any new ports in production. - Replace broad rich rules with tighter source-address scoping once you've confirmed which hosts actually need access.
- Script
firewall-cmd --panic-offinto your incident runbook so panic mode doesn't leave the server unreachable longer than intended. - Explore
/etc/firewallddirectly if you need to version-control your zone and service definitions.
For the full guide with additional tips, visit the original article on Vultr Docs.
Top comments (0)