Manage Network Security (Firewalld)
Master firewall configuration with firewalld. Learn to manage zones, services, ports, and rich rules for network security. Configure permanent and runtime firewall rules.
📋 Table of Contents
🎯 Introduction to Firewalld
Firewalld is the dynamic firewall manager for RHEL 9. It uses zones to define trust levels and manages firewall rules without requiring restart.
Firewalld Components
| Component | Description |
|---|---|
| firewalld | Dynamic firewall daemon |
| firewall-cmd | Command-line tool |
| Zones | Trust level containers for rules |
| Services | Predefined port/protocol combinations |
Managing Firewalld Service
# Start firewalld
sudo systemctl start firewalld
# Enable at boot
sudo systemctl enable --now firewalld
# Check status
sudo systemctl status firewalld
sudo firewall-cmd --state
# Reload firewall (apply permanent rules)
sudo firewall-cmd --reload
# Stop firewalld (dangerous in production!)
sudo systemctl stop firewalld
Runtime vs Permanent Rules
| Type | Description | Command |
|---|---|---|
| Runtime | Immediate, lost on reload/reboot | firewall-cmd (no option) |
| Permanent | Saved, requires reload | firewall-cmd --permanent |
Always add rules both runtime and permanent, or use --permanent then
--reload:
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload
🛡️ Firewall Zones
Zones define trust levels for network connections. Each interface is assigned to one zone.
Predefined Zones
| Zone | Trust Level | Default Behavior |
|---|---|---|
| drop | None | Drop all incoming, no reply |
| block | None | Reject incoming (sends ICMP reply) |
| public | Low | Default zone, allow SSH & cockpit |
| external | Low | For masquerading (NAT) |
| work | Medium | Trust coworkers |
| home | Medium-High | Trust home network |
| internal | High | Internal network |
| trusted | Full | Allow all traffic |
Managing Zones
# List all zones
sudo firewall-cmd --get-zones
# Show default zone
sudo firewall-cmd --get-default-zone
# Set default zone
sudo firewall-cmd --set-default-zone=public
# Show active zones (with interfaces)
sudo firewall-cmd --get-active-zones
# Show all settings for a zone
sudo firewall-cmd --zone=public --list-all
# Show all zones with details
sudo firewall-cmd --list-all-zones
Assigning Interfaces to Zones
# Change interface zone (runtime)
sudo firewall-cmd --zone=work --change-interface=ens33
# Permanent interface assignment
sudo firewall-cmd --permanent --zone=work --change-interface=ens33
sudo firewall-cmd --reload
# Or use nmcli
sudo nmcli con mod ens33 connection.zone work
sudo nmcli con up ens33
# Show which zone an interface is in
sudo firewall-cmd --get-zone-of-interface=ens33
🔧 Managing Services
Services are predefined sets of ports/protocols for common applications.
Listing Services
# List all available services
sudo firewall-cmd --get-services
# List services in default zone
sudo firewall-cmd --list-services
# List services in specific zone
sudo firewall-cmd --zone=public --list-services
# Show service details
sudo firewall-cmd --info-service=http
sudo firewall-cmd --info-service=ssh
Adding/Removing Services
# Add service (runtime only)
sudo firewall-cmd --add-service=http
# Add service (permanent, requires reload)
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload
# Add service to specific zone
sudo firewall-cmd --zone=public --add-service=https
# Add multiple services
sudo firewall-cmd --permanent --add-service={http,https,smtp}
sudo firewall-cmd --reload
# Remove service
sudo firewall-cmd --remove-service=http
sudo firewall-cmd --permanent --remove-service=http
sudo firewall-cmd --reload
Common Services
| Service | Port | Protocol |
|---|---|---|
| ssh | 22 | TCP |
| http | 80 | TCP |
| https | 443 | TCP |
| nfs | 2049 | TCP |
| mysql | 3306 | TCP |
| smtp | 25 | TCP |
Procedure: Allow HTTP/HTTPS Traffic
- Check current services:
sudo firewall-cmd --list-services - Add HTTP and HTTPS (permanent):
sudo firewall-cmd --permanent --add-service=http sudo firewall-cmd --permanent --add-service=https - Reload firewall:
sudo firewall-cmd --reload - Verify:
sudo firewall-cmd --list-services - Test access:
curl http://localhost curl https://localhost
🔌 Managing Ports
For custom applications or non-standard ports, manage individual ports.
Adding/Removing Ports
# Add port (runtime)
sudo firewall-cmd --add-port=8080/tcp
# Add port (permanent)
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
# Add multiple ports
sudo firewall-cmd --permanent --add-port={8080/tcp,8443/tcp,3000/tcp}
sudo firewall-cmd --reload
# Add port range
sudo firewall-cmd --permanent --add-port=5000-5010/tcp
sudo firewall-cmd --reload
# Add UDP port
sudo firewall-cmd --permanent --add-port=53/udp
sudo firewall-cmd --reload
# Remove port
sudo firewall-cmd --remove-port=8080/tcp
sudo firewall-cmd --permanent --remove-port=8080/tcp
sudo firewall-cmd --reload
Listing Ports
# List open ports in default zone
sudo firewall-cmd --list-ports
# List ports in specific zone
sudo firewall-cmd --zone=public --list-ports
# Show everything (services and ports)
sudo firewall-cmd --list-all
Port vs Service
| Method | When to Use |
|---|---|
| Service | Standard services (http, ssh, nfs) - cleaner, easier to manage |
| Port | Custom apps, non-standard ports (8080, 3000, etc.) |
Procedure: Open Custom Application Port
- Identify required port (e.g., NodeJS on 3000):
ss -tulpn | grep 3000 - Add port permanently:
sudo firewall-cmd --permanent --add-port=3000/tcp - Reload firewall:
sudo firewall-cmd --reload - Verify port is open:
sudo firewall-cmd --list-ports - Test from another machine:
telnet server-ip 3000 # or curl http://server-ip:3000
📜 Rich Rules
Rich rules provide advanced firewall rules with source filtering, logging, and complex conditions.
Rich Rule Syntax
# Basic format:
rule family="ipv4" source address="IP/MASK" [service|port] [accept|reject|drop]
# Example: Allow SSH from specific IP
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" service name="ssh" accept'
# Reload
sudo firewall-cmd --reload
Rich Rule Examples
# Allow HTTP from specific subnet
sudo firewall-cmd --permanent --add-rich-rule='
rule family="ipv4"
source address="192.168.1.0/24"
service name="http"
accept'
# Block specific IP
sudo firewall-cmd --permanent --add-rich-rule='
rule family="ipv4"
source address="10.0.0.50"
reject'
# Allow port from IP with logging
sudo firewall-cmd --permanent --add-rich-rule='
rule family="ipv4"
source address="192.168.1.10"
port port="3306" protocol="tcp"
log prefix="MySQL Access: " level="info"
accept'
# Rate limit SSH connections
sudo firewall-cmd --permanent --add-rich-rule='
rule service name="ssh"
limit value="5/m"
accept'
# Forward port (port forwarding)
sudo firewall-cmd --permanent --add-rich-rule='
rule family="ipv4"
forward-port port="8080" protocol="tcp" to-port="80"'
Managing Rich Rules
# List rich rules
sudo firewall-cmd --list-rich-rules
# List in specific zone
sudo firewall-cmd --zone=public --list-rich-rules
# Remove rich rule
sudo firewall-cmd --permanent --remove-rich-rule='
rule family="ipv4"
source address="192.168.1.100"
service name="ssh"
accept'
# Reload after changes
sudo firewall-cmd --reload
Source-Based Filtering
# Add source to zone (trust specific IP)
sudo firewall-cmd --permanent --zone=trusted --add-source=192.168.1.0/24
sudo firewall-cmd --reload
# Remove source
sudo firewall-cmd --permanent --zone=trusted --remove-source=192.168.1.0/24
# List sources in zone
sudo firewall-cmd --zone=trusted --list-sources
• Allow service only from specific IPs/subnets
• Block malicious IPs
• Log specific traffic
• Rate limit connections
• Port forwarding
• Time-based rules (advanced)
📝 Practice Questions
Question 1: How do you make a firewall rule permanent?
sudo firewall-cmd --permanent --add-service=http then
sudo firewall-cmd --reload. Without --permanent, rules are runtime only
(lost on reload/reboot). Reload activates permanent rules.
Question 2: What's the default firewall zone in RHEL 9?
The public zone is the default, allowing only SSH and cockpit by default. Check with:
firewall-cmd --get-default-zone. Change with:
firewall-cmd --set-default-zone=home
Question 3: What command opens HTTP and HTTPS permanently?
sudo firewall-cmd --permanent --add-service={http,https} then
sudo firewall-cmd --reload. The braces allow multiple services.
Option A works but isn't permanent. Prefer services over ports for standard apps.
Question 4: How do you open a custom port 8080/tcp?
sudo firewall-cmd --permanent --add-port=8080/tcp then
sudo firewall-cmd --reload. Must specify protocol (tcp/udp).
Use --add-port for custom ports, --add-service for predefined services.
Question 5: What zone allows ALL traffic?
The trusted zone accepts all traffic. Use carefully! Assign trusted IPs:
firewall-cmd --permanent --zone=trusted --add-source=192.168.1.10.
drop zone blocks everything (strictest), trusted allows everything (least strict).
Question 6: Rich rule to allow SSH from 192.168.1.100 only?
Correct syntax:
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4"
source address="192.168.1.100" service name="ssh" accept'. Must include family,
full service syntax. Option C would allow SSH from that IP but requires trusted zone.