Firewall ConfigurationLinux Security Guide

Complete Guide: How to Set Up and Secure FirewallD on CentOS 7

FirewallD on CentOS 7 is the modern, dynamic firewall management solution that replaced raw iptables handling and simplifies network security administration. In this guide you'll learn practical, production-ready steps to install, enable, and configure FirewallD, manage zones and services, open ports, forward traffic, and create custom services. This article is written for system administrators and DevOps engineers who want clear, actionable commands and explanations to secure CentOS 7 servers. Follow the examples to implement runtime changes, persist them across reboots, and verify your firewall rules to keep your services reachable while minimizing your attack surface.

Prerequisites

Before you begin, log in as a user with sudo privileges or as root. Ensure your CentOS 7 system has network connectivity and that you understand which services (SSH, HTTP, HTTPS, application-specific ports) must be accessible. Back up any existing firewall rules if you migrated from legacy iptables. We'll demonstrate both runtime and permanent changes so you can test before making rules persistent.

Install and Start FirewallD

If FirewallD is not present, install it using yum and then check its state. Use the runtime versus permanent options carefully: runtime changes are immediate but lost at reboot; permanent changes are loaded on service start or reload.

sudo yum install firewalld -y

Loaded plugins: fastestmirror
Resolving Dependencies
--> Running transaction check
---> Package firewalld.noarch 0:0.5.3-8.el7 will be installed
...
Complete!

This command installs the FirewallD package. The -y flag automatically answers “yes” to prompts. The output shows package resolution, download, and installation completion.

sudo firewall-cmd --state

running

The –state option returns the service state. “running” indicates FirewallD is active; “not running” means it is stopped and must be started.

sudo systemctl start firewalld

● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2025-03-03 10:22:13 UTC; 2s ago
 Main PID: 1234 (firewalld)
   CGroup: /system.slice/firewalld.service
           └─1234 /usr/bin/python2 -Es /usr/sbin/firewalld --nofork --nopid

Starting via systemd shows the service is active. Use systemctl enable to start FirewallD automatically at boot if desired.

sudo systemctl enable firewalld

Created symlink from /etc/systemd/system/multi-user.target.wants/firewalld.service to /usr/lib/systemd/system/firewalld.service

systemctl enable creates the necessary symlink so FirewallD will start on subsequent reboots.

Understand Zones and Active Configuration

FirewallD uses zones (predefined trust levels) and services (predefined sets of ports/protocols) to control traffic. By default, CentOS 7 assigns all interfaces to the ‘public’ zone. Always check active zones and the default zone before making changes.

sudo firewall-cmd --get-default-zone

public

This prints the default zone used for interfaces without an explicit assignment; here it is “public”.

sudo firewall-cmd --get-zones

block dmz drop external home internal public trusted work

The –get-zones output lists all zones available on the system. Choose the zone that best matches the trust level of the interface/network.

sudo firewall-cmd --get-active-zones

public
  interfaces: eth0 eth1

–get-active-zones shows zones currently in use and which network interfaces are bound to them. In this example eth0 and eth1 are both in the public zone.

sudo firewall-cmd --zone=public --list-all

public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0 eth1
  sources:
  services: ssh dhcpv6-client
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

The –list-all flag prints the configuration of a given zone in use. You can see allowed services, bound interfaces, and other options such as masquerading and forwarded ports.

Open a Service or Port

Prefer built-in service names where available because they make rules readable. For services not present, open specific ports or create a custom service XML definition.

sudo firewall-cmd --zone=public --add-service=http

success

This command adds the HTTP service to the public zone in the runtime configuration only. “success” confirms the runtime change. Use –permanent to persist across reboots.

sudo firewall-cmd --zone=public --list-services

ssh dhcpv6-client http

Verify the service is active for the zone with –list-services. The output lists allowed services for that zone.

sudo firewall-cmd --permanent --zone=public --add-service=http

success

Adding the same service with –permanent changes the persistent configuration. It won't take effect in runtime until a reload, unless already added at runtime.

sudo firewall-cmd --reload

success

Reload applies permanent configuration to the running firewall. Use –reload after making multiple persistent changes to avoid inconsistencies.

sudo firewall-cmd --zone=public --add-port=32400/tcp

success

To allow a specific port (for example, Plex on TCP 32400), use –add-port=PORT/PROTO. This adds a runtime rule; add –permanent to persist.

sudo firewall-cmd --zone=public --list-ports

32400/tcp

–list-ports displays explicit port entries allowed in the selected zone.

Create a Custom Service Definition

When a service is not provided by default, place a custom XML file in /etc/firewalld/services. Copy an existing template, edit the port definitions, then reload FirewallD.

cat /etc/firewalld/services/plexmediaserver.xml



  plexmediaserver
  Plex Media Server: streaming and device integration
  
  

The custom service file defines short name, description, and one or more <port> elements. After creating the file, reload FirewallD so it becomes available as a service.

sudo firewall-cmd --reload

success

Reloading makes newly created service files under /etc/firewalld/services available for use in zones.

Port Forwarding and Masquerading

For NAT or reverse-proxy configurations you may need to forward incoming traffic to different ports or internal addresses. Masquerading is required for outbound SNAT from internal networks.

sudo firewall-cmd --zone=external --add-masquerade

success

Enable masquerading on the zone handling external traffic. This allows source NAT for forwarded/masqueraded packets originating from internal networks.

sudo firewall-cmd --zone=external --add-forward-port=port=80:proto=tcp:toport=8080

success

This example forwards incoming TCP port 80 to local port 8080. To forward to another host, include toaddr=IP in the forward-port definition.

sudo firewall-cmd --zone=external --add-forward-port=port=80:proto=tcp:toport=80:toaddr=10.10.10.2

success

Use toaddr= when forwarding traffic to a different internal host. Remember to enable masquerading if performing NAT.

Build a Minimal Web Server Ruleset (Example)

Example scenario: server with one interface eth0, hosting SSH and a public web server (HTTP/HTTPS). Use a restrictive zone (dmz) as default and only open necessary ports.

sudo firewall-cmd --set-default-zone=dmz

Setting the default zone binds unassigned interfaces to the chosen zone. Some versions of firewall-cmd may produce no output on success; verify the change with –get-default-zone.

sudo firewall-cmd --zone=dmz --add-interface=eth0

success

Assigns eth0 explicitly to the dmz zone at runtime. Add –permanent if you want this binding to persist.

sudo firewall-cmd --permanent --zone=dmz --add-service=http

success

Open HTTP in the dmz permanent configuration so the web server remains reachable after reboots. Repeat for HTTPS and SSH as required.

sudo firewall-cmd --permanent --zone=dmz --add-service=https

success

Adding HTTPS ensures TLS traffic is permitted. Always open only what you need; unnecessary ports increase attack surface.

sudo firewall-cmd --reload

success

Reload applies the permanent changes to the runtime. Now verify the zone contents and active ports.

sudo firewall-cmd --zone=dmz --list-all

dmz (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services: ssh http https
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

Verify that the dmz zone is bound to eth0 and that SSH, HTTP, and HTTPS are enabled. Adjust rich rules or source restrictions for finer-grained controls.

Best Practices and Maintenance

1) Test changes in runtime first: use –add-* without –permanent to validate connectivity before persisting. 2) Use service names rather than ports when possible. 3) Keep custom service definitions under /etc/firewalld/services and version them in your configuration management. 4) Regularly export or document the active configuration (firewall-cmd –list-all-zones) and back up /etc/firewalld. 5) For complex rules, consider leveraging rich rules or direct rules only when necessary; they add complexity and reduce readability.

Conclusion

FirewallD on CentOS 7 provides a programmable, zone-based firewall model that simplifies common firewall tasks while keeping powerful features for NAT, forwarding, and custom services. By using runtime changes to validate access and then converting stable rules to permanent with proper reloads, you can maintain uptime while ensuring persistent security. Apply the principles in this guide—limit exposure to required services, prefer service definitions over raw ports, and document changes—to keep your CentOS 7 servers protected and reachable.

One Comment

  1. Really helpful walkthrough of FirewallD on CentOS 7 — could you add a quick section on enabling logging and testing zone rules safely before going to production?

Komentariši

Vaša email adresa neće biti objavljivana. Neophodna polja su označena sa *