Chapter 15 ⏱️ 50 min read 📚 Advanced

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.

🎯 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
💡 Best Practice

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

  1. Check current services:
    sudo firewall-cmd --list-services
  2. Add HTTP and HTTPS (permanent):
    sudo firewall-cmd --permanent --add-service=http
    sudo firewall-cmd --permanent --add-service=https
  3. Reload firewall:
    sudo firewall-cmd --reload
  4. Verify:
    sudo firewall-cmd --list-services
  5. 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

  1. Identify required port (e.g., NodeJS on 3000):
    ss -tulpn | grep 3000
  2. Add port permanently:
    sudo firewall-cmd --permanent --add-port=3000/tcp
  3. Reload firewall:
    sudo firewall-cmd --reload
  4. Verify port is open:
    sudo firewall-cmd --list-ports
  5. 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
📘 Rich Rule Use Cases

• 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?

  • A) Use --permanent flag then --reload
  • B) Rules are permanent by default
  • C) Run firewall-cmd --save
  • D) Restart firewalld
Answer: A) Use --permanent flag then --reload
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?

  • A) trusted
  • B) home
  • C) public
  • D) work
Answer: C) public
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?

  • A) firewall-cmd --add-service=http,https
  • B) firewall-cmd --permanent --add-service={http,https}
  • C) firewall-cmd --add-port=80,443/tcp
  • D) firewall-cmd --open http https
Answer: B)
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?

  • A) firewall-cmd --permanent --add-port=8080/tcp
  • B) firewall-cmd --permanent --add-service=8080
  • C) firewall-cmd --permanent --open-port=8080
  • D) firewall-cmd --port 8080 --allow
Answer: A)
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?

  • A) public
  • B) home
  • C) trusted
  • D) internal
Answer: C) trusted
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?

  • A) --add-rich-rule='rule source address="192.168.1.100" service="ssh" accept'
  • B) --add-rich-rule='rule family="ipv4" source address="192.168.1.100" service name="ssh" accept'
  • C) --add-source=192.168.1.100 --add-service=ssh
  • D) Both B and C
Answer: B)
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.