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 sudo access
  • The firewalld package 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.