
Setting Up a Firewall Using Firewalld on CentOS
Firewalld is the default dynamic firewall management tool for CentOS systems, replacing the traditional iptables service with a more user-friendly and flexible interface. Unlike static firewall configurations, firewalld allows administrators to modify firewall rules on-the-fly without losing existing connections, making it essential for production environments where uptime is critical. This guide will walk you through the complete setup process, from basic installation to advanced zone configurations, while helping you avoid common pitfalls that can leave your server vulnerable or inaccessible.
How Firewalld Works
Firewalld operates as a frontend to the Linux kernel’s netfilter framework, the same underlying technology that powers iptables. However, it introduces several key concepts that make it more manageable for modern server environments.
The core concept revolves around zones, which are predefined sets of rules that define trust levels for network connections. When a connection attempt is made, firewalld determines which zone applies based on the source IP address, incoming interface, or connection characteristics. Each zone has a default behavior and a set of allowed services, ports, and protocols.
Here’s how the main components interact:
- Zones: Security profiles that group rules together (public, internal, dmz, etc.)
- Services: Predefined collections of ports and protocols for common applications
- Runtime vs Permanent: Changes can be temporary (lost on restart) or permanent
- Rich Rules: Complex filtering rules with advanced matching criteria
The daemon continuously monitors for configuration changes and applies them without interrupting existing connections, which is crucial for remote server management.
Step-by-Step Implementation Guide
Installation and Initial Setup
Most CentOS installations include firewalld by default, but let’s ensure it’s properly installed and configured:
# Install firewalld if not present
sudo yum install firewalld
# Start and enable the service
sudo systemctl start firewalld
sudo systemctl enable firewalld
# Verify the service is running
sudo systemctl status firewalld
Check the current configuration to understand your starting point:
# View active zones and their interfaces
sudo firewall-cmd --get-active-zones
# List all available zones
sudo firewall-cmd --get-zones
# Check the default zone
sudo firewall-cmd --get-default-zone
# View current zone configuration
sudo firewall-cmd --list-all
Basic Zone Configuration
The default zone is typically “public” which is restrictive by design. Let’s configure it for a typical web server setup:
# Add essential services to the public zone
sudo firewall-cmd --zone=public --add-service=ssh
sudo firewall-cmd --zone=public --add-service=http
sudo firewall-cmd --zone=public --add-service=https
# Add custom ports if needed
sudo firewall-cmd --zone=public --add-port=8080/tcp
# View the current runtime configuration
sudo firewall-cmd --zone=public --list-all
These changes are temporary by default. To make them permanent:
# Make current runtime configuration permanent
sudo firewall-cmd --runtime-to-permanent
# Or add rules directly as permanent
sudo firewall-cmd --permanent --zone=public --add-service=ssh
sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --permanent --zone=public --add-service=https
# Reload to apply permanent changes
sudo firewall-cmd --reload
Advanced Configuration Examples
For more complex setups, you might need custom services and rich rules:
# Create a custom service definition
sudo firewall-cmd --permanent --new-service=myapp
sudo firewall-cmd --permanent --service=myapp --set-description="My Application"
sudo firewall-cmd --permanent --service=myapp --set-short="MyApp"
sudo firewall-cmd --permanent --service=myapp --add-port=3000/tcp
sudo firewall-cmd --permanent --service=myapp --add-port=3001/tcp
# Apply the new service
sudo firewall-cmd --reload
sudo firewall-cmd --permanent --zone=public --add-service=myapp
Rich rules provide granular control over traffic:
# Allow MySQL access only from specific subnet
sudo firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" service name="mysql" accept'
# Rate limit SSH connections
sudo firewall-cmd --permanent --add-rich-rule='rule service name="ssh" accept limit value="10/m"'
# Block specific IP address
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" drop'
# Allow port forwarding
sudo firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" forward-port port="8080" protocol="tcp" to-port="80"'
Real-World Use Cases and Examples
Web Server Configuration
A typical LAMP stack server requires specific port access while maintaining security:
# Basic web server setup
sudo firewall-cmd --permanent --zone=public --add-service=ssh
sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --permanent --zone=public --add-service=https
# Allow database access from application servers only
sudo firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="10.0.0.0/8" service name="mysql" accept'
# Enable monitoring tools
sudo firewall-cmd --permanent --zone=public --add-port=9090/tcp # Prometheus
sudo firewall-cmd --permanent --zone=public --add-port=3000/tcp # Grafana
sudo firewall-cmd --reload
Multi-Zone Setup for Complex Networks
Large deployments often require different security policies for different network segments:
# Configure internal zone for trusted networks
sudo firewall-cmd --permanent --zone=internal --add-service=ssh
sudo firewall-cmd --permanent --zone=internal --add-service=mysql
sudo firewall-cmd --permanent --zone=internal --add-service=nfs
sudo firewall-cmd --permanent --zone=internal --add-service=samba
# Configure DMZ zone for semi-trusted services
sudo firewall-cmd --permanent --zone=dmz --add-service=ssh
sudo firewall-cmd --permanent --zone=dmz --add-service=http
sudo firewall-cmd --permanent --zone=dmz --add-service=https
# Assign interfaces to zones
sudo firewall-cmd --permanent --zone=internal --change-interface=eth1
sudo firewall-cmd --permanent --zone=dmz --change-interface=eth2
sudo firewall-cmd --permanent --zone=public --change-interface=eth0
Firewalld vs Alternatives Comparison
Feature | Firewalld | UFW | Raw iptables |
---|---|---|---|
Learning Curve | Moderate | Easy | Steep |
Dynamic Rules | Yes | No | Manual |
Zone Support | Native | No | Manual |
GUI Available | Yes | Limited | No |
Performance Impact | Low | Low | Minimal |
Default on CentOS | Yes | No | Yes (kernel) |
Performance Considerations and Best Practices
Firewalld’s performance is generally excellent for most use cases, but there are some considerations for high-traffic servers:
- Rule Order Matters: Place frequently matched rules at the top of rich rule lists
- Use Zones Efficiently: Group similar services in appropriate zones rather than creating complex rich rules
- Monitor Rule Count: Excessive rules can impact performance on high-traffic servers
- Consider Direct Rules: For complex scenarios, direct iptables rules might be more efficient
Performance testing shows firewalld adds approximately 0.1-0.3ms latency per connection on typical hardware, which is negligible for most applications. However, servers handling 10,000+ concurrent connections might benefit from optimization.
Common Pitfalls and Troubleshooting
SSH Lockout Prevention
The most common mistake is accidentally blocking SSH access. Always ensure SSH is allowed before making changes permanent:
# Always verify SSH is allowed
sudo firewall-cmd --list-services | grep ssh
# Test rules before making permanent
sudo firewall-cmd --zone=public --add-service=ssh
# Test your connection, then make permanent
sudo firewall-cmd --permanent --zone=public --add-service=ssh
sudo firewall-cmd --reload
Service vs Port Confusion
Using services is preferred over raw ports, but understanding both is important:
# Check what ports a service uses
sudo firewall-cmd --info-service=http
# List all predefined services
sudo firewall-cmd --get-services
# If no service exists, use ports instead
sudo firewall-cmd --permanent --zone=public --add-port=8080/tcp
Runtime vs Permanent Configuration Sync Issues
Mismatched runtime and permanent configurations cause confusion:
# Check for differences
sudo firewall-cmd --list-all
sudo firewall-cmd --permanent --list-all
# Sync runtime to permanent
sudo firewall-cmd --runtime-to-permanent
# Or reload permanent to runtime
sudo firewall-cmd --reload
Debugging Connection Issues
When connections fail, systematic debugging helps identify the issue:
# Enable logging for denied packets
sudo firewall-cmd --set-log-denied=all
# Check logs for denied connections
sudo journalctl -u firewalld -f
# Test specific ports
sudo firewall-cmd --query-port=8080/tcp --zone=public
# Verify service definitions
sudo firewall-cmd --info-service=servicename
Integration with Management Tools
Firewalld works well with configuration management systems and monitoring tools. For Ansible integration:
- name: Configure firewalld for web server
firewalld:
service: "{{ item }}"
permanent: yes
state: enabled
immediate: yes
loop:
- ssh
- http
- https
notify: reload firewalld
For VPS deployments, firewalld provides an excellent balance between security and manageability. When scaling to multiple servers or dedicated servers, consistent firewall policies become crucial for maintaining security posture.
Advanced users might want to explore firewalld’s D-Bus interface for programmatic control, or integrate with tools like Fail2ban for dynamic IP blocking. The official firewalld documentation provides comprehensive details for complex scenarios, while the Red Hat networking guide offers enterprise-focused configuration patterns.
Remember that firewall configuration is just one layer of security. Combine firewalld with proper system updates, secure service configurations, and monitoring for comprehensive protection. Regular audits of your firewall rules help ensure they remain relevant as your infrastructure evolves.

This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.
This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.