A properly configured firewall is your Linux server’s first line of defense against unauthorized access and malicious attacks. This comprehensive guide will walk you through installing and configuring the three most popular Linux firewalls: UFW, firewalld, and iptables.
Understanding Linux Firewalls
Linux firewalls work by filtering network traffic based on predefined rules. They control incoming and outgoing connections, allowing legitimate traffic while blocking potentially harmful requests. There are three main firewall solutions for Linux:
- UFW (Uncomplicated Firewall) – Simple, user-friendly, perfect for Ubuntu/Debian systems
- firewalld – Dynamic firewall with zones, ideal for RHEL/CentOS/Fedora systems
- iptables – Powerful, low-level firewall for advanced users
Prerequisites
Before you begin, ensure you have:
- Root or sudo access to your Linux server
- SSH access to your server (or physical/console access)
- Basic knowledge of which services you need to allow
- List of ports your applications use
Part 1: UFW (Uncomplicated Firewall)
UFW is the easiest firewall to configure and is the default on Ubuntu and Debian-based systems.
Installing UFW
On Ubuntu/Debian:
sudo apt update
sudo apt install ufw
Verify installation:
sudo ufw version
Basic UFW Configuration
Step 1: Check UFW Status
sudo ufw status verbose
Step 2: Set Default Policies
Block all incoming traffic and allow all outgoing traffic by default:
sudo ufw default deny incoming
sudo ufw default allow outgoing
Step 3: Allow SSH Access
sudo ufw allow ssh
Or specify the port number if you use a custom SSH port:
sudo ufw allow 2222/tcp
Step 4: Enable UFW
sudo ufw enable
Confirm when prompted. UFW will now start on boot automatically.
Common UFW Rules
Allow HTTP and HTTPS (Web Server):
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
Or use service names:
sudo ufw allow http
sudo ufw allow https
Allow MySQL/MariaDB:
sudo ufw allow 3306/tcp
Allow PostgreSQL:
sudo ufw allow 5432/tcp
Allow FTP:
sudo ufw allow 21/tcp
Allow DNS:
sudo ufw allow 53
Allow Port Range:
sudo ufw allow 6000:6007/tcp
Allow from Specific IP Address:
sudo ufw allow from 192.168.1.100
Allow from IP to Specific Port:
sudo ufw allow from 192.168.1.100 to any port 22
Allow Subnet:
sudo ufw allow from 192.168.1.0/24
Managing UFW Rules
View All Rules with Numbers:
sudo ufw status numbered
Delete a Rule by Number:
sudo ufw delete 3
Delete a Rule by Specification:
sudo ufw delete allow 80/tcp
Deny a Connection:
sudo ufw deny from 203.0.113.100
Reset UFW to Default:
sudo ufw reset
Advanced UFW Configuration
Enable Logging:
sudo ufw logging on
Set logging level (low, medium, high, full):
sudo ufw logging medium
View Logs:
sudo tail -f /var/log/ufw.log
Allow Application Profiles:
View available application profiles:
sudo ufw app list
Allow an application:
sudo ufw allow 'Nginx Full'
sudo ufw allow 'Apache Full'
sudo ufw allow 'OpenSSH'
Part 2: firewalld
firewalld is a dynamic firewall manager used primarily on RHEL, CentOS, Fedora, and Rocky Linux systems. It uses zones to define trust levels for network connections.
Installing firewalld
On RHEL/CentOS/Fedora/Rocky Linux:
sudo dnf install firewalld
Or on older systems:
sudo yum install firewalld
Start and enable firewalld:
sudo systemctl start firewalld
sudo systemctl enable firewalld
Verify status:
sudo systemctl status firewalld
sudo firewall-cmd --state
Understanding firewalld Zones
firewalld uses zones to manage trust levels. Common zones include:
- drop – All incoming connections dropped without reply
- block – All incoming connections rejected with icmp-host-prohibited message
- public – For use in public areas, only selected incoming connections accepted
- external – For external networks with masquerading enabled
- dmz – For computers in DMZ with limited access
- work – For work networks, more services trusted
- home – For home networks, more services trusted
- internal – For internal networks
- trusted – All network connections accepted
Basic firewalld Configuration
Check Default Zone:
sudo firewall-cmd --get-default-zone
Set Default Zone:
sudo firewall-cmd --set-default-zone=public
List Active Zones:
sudo firewall-cmd --get-active-zones
View All Rules in a Zone:
sudo firewall-cmd --zone=public --list-all
Managing Services in firewalld
List Available Services:
sudo firewall-cmd --get-services
Allow SSH:
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload
--permanent flag makes rules persistent across reboots. Always run --reload after adding permanent rules to apply them immediately.
Allow HTTP and HTTPS:
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
Remove a Service:
sudo firewall-cmd --permanent --remove-service=http
sudo firewall-cmd --reload
Managing Ports in firewalld
Open a Port:
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
Open Multiple Ports:
sudo firewall-cmd --permanent --add-port=3000-3005/tcp
sudo firewall-cmd --reload
List Open Ports:
sudo firewall-cmd --list-ports
Remove a Port:
sudo firewall-cmd --permanent --remove-port=8080/tcp
sudo firewall-cmd --reload
Advanced firewalld Configuration
Allow from Specific IP:
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" accept'
sudo firewall-cmd --reload
Allow IP to Specific Port:
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port port="22" protocol="tcp" accept'
sudo firewall-cmd --reload
Block an IP Address:
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.100" reject'
sudo firewall-cmd --reload
View Rich Rules:
sudo firewall-cmd --list-rich-rules
Enable Logging:
sudo firewall-cmd --set-log-denied=all
sudo firewall-cmd --reload
Managing firewalld Zones
Add Interface to Zone:
sudo firewall-cmd --permanent --zone=public --add-interface=eth0
sudo firewall-cmd --reload
Change Zone for Interface:
sudo firewall-cmd --permanent --zone=home --change-interface=eth0
sudo firewall-cmd --reload
Part 3: iptables
iptables is the most powerful and flexible firewall for Linux, but also the most complex. It works at a lower level than UFW or firewalld.
Installing iptables
iptables is usually pre-installed on most Linux distributions. If not:
On Ubuntu/Debian:
sudo apt install iptables iptables-persistent
On RHEL/CentOS/Fedora:
sudo dnf install iptables-services
Disable firewalld:
sudo systemctl stop firewalld
sudo systemctl disable firewalld
Disable UFW:
sudo ufw disable
Understanding iptables Chains
iptables uses three main chains:
- INPUT – Controls incoming connections
- OUTPUT – Controls outgoing connections
- FORWARD – Controls routed/forwarded connections
Basic iptables Commands
View Current Rules:
sudo iptables -L -v -n
View Rules with Line Numbers:
sudo iptables -L --line-numbers
Flush All Rules (Clear Everything):
sudo iptables -F
Setting Default Policies
Set default policies to drop all traffic:
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT
Allow Loopback Traffic
Always allow localhost connections:
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A OUTPUT -o lo -j ACCEPT
Allow Established Connections
Allow established and related incoming connections:
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Common iptables Rules
Allow SSH:
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
Allow HTTP and HTTPS:
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
Allow from Specific IP:
sudo iptables -A INPUT -s 192.168.1.100 -j ACCEPT
Allow from Subnet:
sudo iptables -A INPUT -s 192.168.1.0/24 -j ACCEPT
Block an IP Address:
sudo iptables -A INPUT -s 203.0.113.100 -j DROP
Allow Port Range:
sudo iptables -A INPUT -p tcp --dport 6000:6007 -j ACCEPT
Allow Ping (ICMP):
sudo iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
Deleting iptables Rules
Delete by Line Number:
sudo iptables -D INPUT 3
Delete by Specification:
sudo iptables -D INPUT -p tcp --dport 80 -j ACCEPT
Saving iptables Rules
Rules are lost on reboot unless saved.
On Ubuntu/Debian (with iptables-persistent):
sudo netfilter-persistent save
Or manually:
sudo iptables-save | sudo tee /etc/iptables/rules.v4
On RHEL/CentOS:
sudo service iptables save
Or:
sudo iptables-save | sudo tee /etc/sysconfig/iptables
Restoring iptables Rules
On Ubuntu/Debian:
sudo iptables-restore < /etc/iptables/rules.v4
On RHEL/CentOS:
sudo iptables-restore < /etc/sysconfig/iptables
Complete iptables Configuration Example
Here's a complete basic firewall setup:
#!/bin/bash
# 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 loopback
sudo iptables -A INPUT -i lo -j ACCEPT
# Allow established connections
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Allow SSH
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Allow HTTP and 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
# Save rules
sudo netfilter-persistent save
Firewall Security Best Practices
1. Principle of Least Privilege
Only open ports that are absolutely necessary. If a service isn't being used, don't allow its port through the firewall.
2. Use Specific Rules
Instead of allowing all traffic from an IP, allow specific ports:
# Better
sudo ufw allow from 192.168.1.100 to any port 22
# Avoid
sudo ufw allow from 192.168.1.100
3. Implement Rate Limiting
UFW Rate Limiting:
sudo ufw limit ssh
iptables Rate Limiting:
sudo iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set
sudo iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP
4. Regular Audits
Regularly review your firewall rules and remove unnecessary ones:
sudo ufw status numbered
sudo firewall-cmd --list-all
sudo iptables -L -v -n
5. Enable Logging
Enable firewall logging to monitor suspicious activity and troubleshoot issues.
6. Keep Firewall Updated
Regularly update your firewall software:
sudo apt update && sudo apt upgrade # Debian/Ubuntu
sudo dnf update # RHEL/Fedora
7. Test Before Deploying
Always test firewall rules in a safe environment before applying to production servers.
Common Firewall Scenarios
Web Server (Apache/Nginx)
UFW:
sudo ufw allow 'Nginx Full'
sudo ufw allow ssh
sudo ufw enable
firewalld:
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload
Database Server (MySQL/PostgreSQL)
Only allow from application server IP:
UFW:
sudo ufw allow from 192.168.1.50 to any port 3306
sudo ufw allow ssh
sudo ufw enable
firewalld:
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.50" port port="3306" protocol="tcp" accept'
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload
Mail Server
UFW:
sudo ufw allow 25/tcp # SMTP
sudo ufw allow 587/tcp # Submission
sudo ufw allow 993/tcp # IMAPS
sudo ufw allow 995/tcp # POP3S
sudo ufw allow ssh
sudo ufw enable
Docker Host
Docker manipulates iptables directly. If using UFW:
# Edit /etc/ufw/after.rules and add Docker rules
# Or edit /etc/default/ufw
DEFAULT_FORWARD_POLICY="ACCEPT"
Troubleshooting Firewall Issues
Issue: Locked Out After Enabling Firewall
Solution: If you have console access (physical or cloud console), log in and disable the firewall:
sudo ufw disable
sudo systemctl stop firewalld
Then reconfigure with proper SSH access rules.
Issue: Service Not Accessible After Opening Port
Check if service is listening:
sudo netstat -tulpn | grep :80
sudo ss -tulpn | grep :80
Check if firewall rule is active:
sudo ufw status | grep 80
sudo firewall-cmd --list-ports
sudo iptables -L -n | grep 80
Check service logs:
sudo journalctl -u nginx -n 50
sudo tail -f /var/log/apache2/error.log
Issue: Rules Not Persisting After Reboot
UFW: UFW should persist automatically. Check if enabled:
sudo ufw status
firewalld: Ensure you used --permanent flag:
sudo firewall-cmd --permanent --list-all
iptables: Ensure rules are saved:
sudo netfilter-persistent save # Debian/Ubuntu
sudo service iptables save # RHEL/CentOS
Testing Your Firewall
Test Open Ports
From another machine, test if ports are open:
telnet your_server_ip 80
nc -zv your_server_ip 443
Or use nmap:
nmap -p 22,80,443 your_server_ip
Test from the Server
curl -I http://localhost
curl -I https://localhost
Online Port Scanners
Use online tools to scan your public IP:
- https://www.yougetsignal.com/tools/open-ports/
- https://pentest-tools.com/network-vulnerability-scanning/tcp-port-scanner-online-nmap
Firewall Comparison Chart
| Feature | UFW | firewalld | iptables |
|---|---|---|---|
| Ease of Use | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐ |
| Flexibility | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| Default On | Ubuntu/Debian | RHEL/CentOS/Fedora | None (manual) |
| Dynamic Rules | No | Yes | No |
| Zone Support | No | Yes | No |
| Best For | Beginners, Simple setups | Enterprise, Complex networks | Advanced users, Custom configs |
Quick Reference Commands
UFW Quick Reference
# Status and management
sudo ufw status verbose
sudo ufw enable
sudo ufw disable
sudo ufw reload
# Allow/deny rules
sudo ufw allow 80/tcp
sudo ufw deny 8080/tcp
sudo ufw allow from 192.168.1.100
sudo ufw delete allow 80/tcp
# Application profiles
sudo ufw app list
sudo ufw allow 'Nginx Full'
# Logging
sudo ufw logging on
firewalld Quick Reference
# Status and management
sudo systemctl status firewalld
sudo firewall-cmd --state
sudo firewall-cmd --reload
# Services
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --remove-service=http
sudo firewall-cmd --list-services
# Ports
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --permanent --remove-port=8080/tcp
sudo firewall-cmd --list-ports
# Zones
sudo firewall-cmd --get-default-zone
sudo firewall-cmd --set-default-zone=public
sudo firewall-cmd --zone=public --list-all
# Rich rules
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" accept'
sudo firewall-cmd --list-rich-rules
iptables Quick Reference
# View rules
sudo iptables -L -v -n
sudo iptables -L --line-numbers
# Add rules
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -s 192.168.1.100 -j ACCEPT
# Delete rules
sudo iptables -D INPUT 3
sudo iptables -F # Flush all rules
# Default policies
sudo iptables -P INPUT DROP
sudo iptables -P OUTPUT ACCEPT
# Save rules
sudo netfilter-persistent save # Debian/Ubuntu
sudo service iptables save # RHEL/CentOS
Conclusion
Configuring a firewall is essential for securing your Linux server. Whether you choose UFW for its simplicity, firewalld for its dynamic zone-based approach, or iptables for maximum control, the key is to implement the principle of least privilege: only allow what's necessary and block everything else.
- Always allow SSH before enabling your firewall
- Test rules before disconnecting from your server
- Use specific rules rather than blanket allows
- Enable logging to monitor suspicious activity
- Regularly audit and update your firewall rules
- Combine firewall protection with other security measures
Remember that a firewall is just one layer of your security strategy. Combine it with regular updates, strong passwords or SSH keys, fail2ban, intrusion detection systems, and security monitoring for comprehensive server protection.
Additional Security Recommendations
To further enhance your server security beyond the firewall:
- Install Fail2Ban: Automatically ban IPs that show malicious signs
- Use SSH Keys: Disable password authentication entirely
- Enable Two-Factor Authentication: Add an extra layer of security
- Regular Updates: Keep your system and packages up to date
- Security Auditing: Use tools like Lynis or OpenSCAP for security audits
- Intrusion Detection: Install AIDE or Tripwire to monitor file integrity
- Log Monitoring: Regularly review system logs for suspicious activity
Common Ports Reference
| Service | Port | Protocol |
|---|---|---|
| SSH | 22 | TCP |
| FTP | 21 | TCP |
| SFTP | 22 | TCP |
| HTTP | 80 | TCP |
| HTTPS | 443 | TCP |
| SMTP | 25 | TCP |
| SMTP Submission | 587 | TCP |
| SMTPS | 465 | TCP |
| IMAP | 143 | TCP |
| IMAPS | 993 | TCP |
| POP3 | 110 | TCP |
| POP3S | 995 | TCP |
| MySQL/MariaDB | 3306 | TCP |
| PostgreSQL | 5432 | TCP |
| MongoDB | 27017 | TCP |
| Redis | 6379 | TCP |
| DNS | 53 | TCP/UDP |
| NTP | 123 | UDP |
| RDP | 3389 | TCP |
| Docker | 2375-2376 | TCP |