firewalld vs iptables: Linux Firewall Comparison and Setup
Comparing firewalld and iptables for Linux firewall management, including configuration examples, migration guidance, and when to use each.
Introduction
Linux firewall management has evolved from raw iptables commands to more user-friendly tools like firewalld. Understanding when to use each, and how they relate to the underlying netfilter kernel framework, is essential for Linux system administration. This post compares firewalld and iptables, explains their differences, and provides practical configuration examples.
Environment
The examples use firewalld 1.2.3 on Rocky Linux 9 and iptables 1.8.8 on Ubuntu 22.04 LTS. Both systems are configured as web servers with SSH access.
# Rocky Linux 9
firewall-cmd --version
# 1.2.3
# Ubuntu 22.04
iptables --version
# iptables v1.8.8 (nf_tables)Problem
You need to configure firewall rules on a Linux server. The choice between firewalld and iptables depends on:
- The Linux distribution
- Whether you need dynamic rule changes
- The complexity of your firewall policy
- Team familiarity with the tools
Analysis
iptables characteristics:
- Low-level, direct netfilter interface
- Stateless rule management
- Manual rule persistence
- Available on all Linux distributions
- Powerful but verbose
firewalld characteristics:
- High-level abstraction over netfilter
- Zone-based policy model
- Dynamic rule changes without restart
- D-Bus API for programmatic control
- Default on RHEL/CentOS/Fedora
Key differences:
| Feature | iptables | firewalld |
|---|---|---|
| Rule storage | Manual scripts | XML configuration |
| Dynamic changes | Require flush/reload | Instant via firewall-cmd |
| Zones | Not supported | Built-in zone model |
| IPv4/IPv6 | Separate commands | Unified management |
| Programmatic API | Limited | D-Bus API |
Solution
1. Basic iptables configuration
# Flush existing rules
sudo iptables -F
sudo iptables -X
# Set default policies
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT
# Allow established connections
sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow loopback
sudo iptables -A INPUT -i lo -j ACCEPT
# Allow SSH
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Allow HTTP/HTTPS
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# Allow ping
sudo iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
# Log dropped packets
sudo iptables -A INPUT -j LOG --log-prefix "IPTables-Dropped: "
# Save rules
sudo iptables-save > /etc/iptables/rules.v42. Basic firewalld configuration
# Check default zone
firewall-cmd --get-default-zone
# public
# List allowed services
firewall-cmd --list-services
# cockpit dhcpv6-client ssh
# Add HTTP service
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
# Add SSH (if not already allowed)
sudo firewall-cmd --permanent --add-service=ssh
# Reload to apply
sudo firewall-cmd --reload3. firewalld zone-based configuration
# List available zones
firewall-cmd --get-zones
# block dmz drop external home internal public trusted work
# Set up different zones for different interfaces
sudo firewall-cmd --permanent --zone=internal --add-interface=eth1
sudo firewall-cmd --permanent --zone=public --add-interface=eth0
# Configure internal zone
sudo firewall-cmd --permanent --zone=internal --add-service=ssh
sudo firewall-cmd --permanent --zone=internal --add-service=http
sudo firewall-cmd --permanent --zone=internal --add-source=192.168.1.0/24
# Configure public zone
sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --permanent --zone=public --add-service=https
sudo firewall-cmd --reload4. iptables with persistence
# Install iptables-persistent
sudo apt-get install iptables-persistent
# Save current rules
sudo netfilter-persistent save
# Rules are automatically loaded on boot
sudo netfilter-persistent reload5. firewalld rich rules
# Allow SSH only from specific IP
sudo firewall-cmd --permanent --add-rich-rule='
rule family="ipv4"
source address="192.168.1.100"
port protocol="tcp" port="22"
accept'
# Rate limit SSH connections
sudo firewall-cmd --permanent --add-rich-rule='
rule family="ipv4"
service name="ssh"
accept
limit value="5/m"'
# Block a specific IP
sudo firewall-cmd --permanent --add-rich-rule='
rule family="ipv4"
source address="10.0.0.50"
drop'
sudo firewall-cmd --reload6. iptables with logging
# Create a custom chain for logging
sudo iptables -N LOGGING
sudo iptables -A INPUT -j LOGGING
sudo iptables -A LOGGING -m limit --limit 2/min -j LOG --log-prefix "IPTables-Dropped: " --log-level 4
sudo iptables -A LOGGING -j DROP7. firewalld port forwarding
# Forward port 8080 to internal port 80
sudo firewall-cmd --permanent --add-forward-port=port=8080:proto=tcp:toport=80
# Forward to a different host
sudo firewall-cmd --permanent --add-forward-port=port=2222:proto=tcp:toport=22:toaddr=192.168.1.100
sudo firewall-cmd --reload8. iptables with NAT
# Enable IP forwarding
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
# SNAT for outgoing traffic
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# DNAT for incoming traffic
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.100:809. Migration from iptables to firewalld
# On RHEL/CentOS
sudo systemctl stop iptables
sudo systemctl disable iptables
sudo systemctl start firewalld
sudo systemctl enable firewalld
# Convert iptables rules to firewalld
# 1. Document existing iptables rules
sudo iptables -L -n -v
# 2. Map to firewalld services/ports
# iptables -A INPUT -p tcp --dport 22 -j ACCEPT → firewall-cmd --add-service=ssh
# 3. Test incrementally
sudo firewall-cmd --add-service=ssh --permanent
sudo firewall-cmd --reload10. Monitor firewall activity
# iptables: Count rules
sudo iptables -L -n -v
# firewalld: Check denied packets
sudo firewall-cmd --list-rich-rules
# Check kernel log for dropped packets
sudo dmesg | grep "IPTables"Lessons Learned
firewalld is the better choice for dynamic environments where rules change frequently. iptables is more suitable for static, complex rule sets or when you need fine-grained control. Both tools ultimately configure netfilter, so the choice is about management ergonomics. For new deployments, firewalld offers a cleaner abstraction. For existing iptables deployments, migration can be done incrementally.
This blog does not accept any external sponsorships, affiliate marketing, or ad revenue.