The firewall is the first line of defense for any network infrastructure. On Linux systems, packet filtering at the kernel level is handled by Netfilter. Historically, we interacted with Netfilter using iptables, but modern distributions (like RHEL/CentOS/Fedora) use firewalld as a dynamic frontend.
iptables works by matching network traffic against a set of rules. If a packet matches, a Target action is applied (e.g., ACCEPT or DROP).
The golden rule in cybersecurity is "Default Deny": block everything by default and explicitly allow only what is necessary.
# View current rules:
iptables -L -n -v
# 1. ALLOW loopback traffic (localhost)
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# 2. ALLOW established connections (Stateful inspection)
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# 3. SET DEFAULT DROP POLICY (Careful, don't lock yourself out of SSH!)
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
The syntax anatomy is: iptables -[Action] [Chain] -p [Protocol] -s [Source IP] --dport [Dest Port] -j [Target]
# Allow HTTP/HTTPS globally:
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# Allow SSH ONLY from a specific IP:
iptables -A INPUT -p tcp -s 203.0.113.50 --dport 22 -j ACCEPT
# Block (DROP) a malicious IP:
iptables -A INPUT -s 198.51.100.22 -j DROP
# Insert a rule at the top (-I) instead of appending (-A):
iptables -I INPUT 1 -s 185.12.99.0/24 -j DROP
You are under attack. A botnet is trying to brute-force your SSH port. As a sysadmin, you must write the exact iptables command to silently drop the attacker's IP.
# Mitigate SYN Floods:
iptables -A INPUT -p tcp --syn -m limit --limit 20/s --limit-burst 50 -j ACCEPT
iptables -A INPUT -p tcp --syn -j DROP
# Block ICMP (Ping) to avoid basic recon:
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
# Log dropped packets:
iptables -A INPUT -j LOG --log-prefix "Dropped_Packet: " --log-level 4
# Enable IP forwarding:
echo 1 > /proc/sys/net/ipv4/ip_forward
# Redirect port 80 to internal port 8080:
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
firewalld uses Zones and allows applying changes dynamically without dropping active connections.
# Check active zones:
firewall-cmd --get-active-zones
# Allow HTTP permanently:
firewall-cmd --zone=public --add-service=http --permanent
firewall-cmd --reload
# Add a custom port:
firewall-cmd --zone=public --add-port=8443/tcp --permanent
# Allow SSH only from 192.168.1.100:
firewall-cmd --permanent --zone=public \
--add-rich-rule='rule family="ipv4" source address="192.168.1.100" port protocol="tcp" port="22" accept'
firewall-cmd --reload