How to Configure the Firewall on RHEL 7
Red Hat Enterprise Linux 7 ships with firewalld as its default firewall management solution. Unlike its predecessor iptables, which required you to manage chains and rules as a flat list, firewalld introduces the concept of zones — named trust levels that you assign to network interfaces and traffic sources. This zone-based model makes firewall management more intuitive and flexible, especially on servers with multiple network interfaces serving different purposes. This guide covers every essential skill: understanding zones, allowing services and ports, writing rich rules, and auditing your active configuration.
Prerequisites
- RHEL 7 system with root or
sudoaccess - The
firewalldpackage installed (included by default on RHEL 7 server installations) - Basic understanding of TCP/IP ports and network services
Step 1: Verify and Start firewalld
Before making any changes, confirm that firewalld is installed, running, and enabled to start at boot:
systemctl status firewalld
If the service is not running, start it and enable it:
systemctl start firewalld
systemctl enable firewalld
Confirm the firewall is actively blocking traffic by checking its state:
firewall-cmd --state
The output should be running. Also verify that iptables is not installed and conflicting — on RHEL 7 you should use one or the other, not both:
systemctl status iptables
If iptables is active and you intend to use firewalld, disable it:
systemctl stop iptables
systemctl disable iptables
systemctl mask iptables
Step 2: Understanding Zones
A zone is a named trust level applied to traffic. Every active network interface is assigned to exactly one zone. RHEL 7 ships with several predefined zones, each with a different default policy:
- drop — all incoming packets are silently dropped; only outgoing connections are allowed
- block — incoming connections are rejected with an icmp-host-prohibited response
- public — suitable for untrusted public networks; only selected services are accepted (default for new interfaces)
- external — for use with masquerading/NAT; intended for the external side of a router
- dmz — for servers in a demilitarized zone; limited inbound access
- work — reasonably trusted work environment; more services allowed than public
- home — for home networks where other machines are mostly trusted
- internal — for internal network interfaces; similar to home
- trusted — all network connections are accepted; use only for fully trusted sources
List all available zones:
firewall-cmd --get-zones
Show which zone is currently the default:
firewall-cmd --get-default-zone
Show which interfaces are assigned to each zone:
firewall-cmd --get-active-zones
Change the default zone:
firewall-cmd --set-default-zone=public
Step 3: Allowing Services by Name
firewalld ships with over 50 predefined service definitions stored in /usr/lib/firewalld/services/. Each XML file defines the ports associated with a named service, so you can allow traffic by name rather than having to remember port numbers.
List all predefined services:
firewall-cmd --get-services
Allow a service in the default zone for the current runtime (lost on firewall reload or system reboot):
firewall-cmd --add-service=http
Add the --permanent flag to write the rule to the on-disk configuration so it survives reboots:
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --permanent --add-service=ssh
After adding permanent rules, reload to apply them to the running configuration:
firewall-cmd --reload
To apply a rule to a specific zone rather than the default, use the --zone flag:
firewall-cmd --permanent --zone=dmz --add-service=http
Remove a service:
firewall-cmd --permanent --remove-service=telnet
firewall-cmd --reload
Step 4: Allowing Traffic by Port Number
When you need to open a port that does not have a predefined service definition, use --add-port:
# Allow a single TCP port permanently:
firewall-cmd --permanent --add-port=8080/tcp
# Allow a UDP port:
firewall-cmd --permanent --add-port=161/udp
# Allow a range of ports:
firewall-cmd --permanent --add-port=10000-10100/tcp
firewall-cmd --reload
List all currently open ports in the default zone:
firewall-cmd --list-ports
Step 5: Working with Rich Rules
Rich rules give you fine-grained control beyond what simple service and port rules provide. They allow you to match on source IP addresses, log traffic, limit connection rates, and more.
Allow SSH from a specific IP address only:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" service name="ssh" accept'
Block all traffic from a specific subnet:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.0/8" reject'
Allow HTTP traffic but log and limit connections to 25 per minute:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" service name="http" limit value="25/m" accept'
Allow a specific port from a trusted source and log it:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.10.0.0/24" port port="5432" protocol="tcp" log prefix="PGSQL-ALLOW" level="info" accept'
After adding rich rules, always reload:
firewall-cmd --reload
List all rich rules in the active zone:
firewall-cmd --list-rich-rules
Step 6: Assigning an Interface to a Zone
On multi-homed servers (multiple network interfaces), you can assign different interfaces to different zones to apply tailored policies to each:
# Assign eth0 to the public zone:
firewall-cmd --permanent --zone=public --change-interface=eth0
# Assign eth1 (internal network) to the internal zone:
firewall-cmd --permanent --zone=internal --change-interface=eth1
firewall-cmd --reload
Step 7: Listing and Auditing Active Rules
Always verify your configuration after making changes. The most comprehensive view is provided by --list-all:
# View all rules in the default zone:
firewall-cmd --list-all
# View all rules in a specific zone:
firewall-cmd --zone=dmz --list-all
# View all zones and their rules at once:
firewall-cmd --list-all-zones
Example output of firewall-cmd --list-all on a typical web server:
public (active)
target: default
icmp-block-inversion: no
interfaces: eth0
sources:
services: ssh dhcpv6-client http https
ports: 8080/tcp
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
rule family="ipv4" source address="192.168.1.100" service name="ssh" accept
Mastering firewalld on RHEL 7 gives you a powerful, zone-aware firewall that can be managed entirely at the command line. By combining predefined services, specific port rules, and rich rules for fine-grained matching, you can build a precise security perimeter tailored to exactly the traffic your server needs to accept. Always apply changes with --permanent and follow up with firewall-cmd --reload, and regularly audit your rules with --list-all to keep your configuration clean and intentional.