Table of Contents
- Understanding iptables Basics
- Setting Default Policies
- Configuring Essential Chains
- Common Security Rules
- Saving and Persisting Rules
- Advanced Configurations
- Best Practices for iptables Security
- Troubleshooting iptables
- Conclusion
- References
1. Understanding iptables Basics
Before diving into configurations, let’s clarify key concepts:
What is iptables?
iptables is a command-line tool for configuring the Linux kernel firewall (netfilter). It filters network traffic by defining rules within chains, which are grouped into tables based on their purpose.
Key Components:
- Tables: Collections of chains. The most critical for security is the
filtertable (default), which handles packet filtering. Other tables includenat(network address translation),mangle(packet modification), andraw(bypass connection tracking). - Chains: Predefined sequences of rules that process packets. The
filtertable uses three core chains:INPUT: Filters packets destined for the local system.OUTPUT: Filters packets originating from the local system.FORWARD: Filters packets routed through the system (e.g., if the system acts as a router).
- Rules: Conditions that determine how to handle a packet (e.g.,
ACCEPT,DROP,LOG). Rules are processed top to bottom; the first matching rule is applied.
Syntax Overview
Rules follow this structure:
iptables [-t table] COMMAND chain [match] [-j target]
-t table: Specify the table (default:filter).COMMAND: Action (e.g.,-Aappend,-Iinsert,-Ddelete,-Pset default policy).chain: Target chain (e.g.,INPUT,OUTPUT).match: Conditions (e.g., port, IP, protocol).-j target: Action if matched (e.g.,ACCEPT,DROP,LOG).
2. Setting Default Policies
Default policies define how iptables handles packets that don’t match any rule. For security, we recommend denying by default and explicitly allowing only necessary traffic.
Why Deny by Default?
A “deny-all” default policy minimizes your attack surface. If no rules explicitly allow traffic, it is blocked by default.
Configure Default Policies
Set policies for the INPUT, OUTPUT, and FORWARD chains in the filter table:
# Block all incoming traffic by default
sudo iptables -P INPUT DROP
# Block all forwarded traffic (for non-router systems)
sudo iptables -P FORWARD DROP
# Allow all outgoing traffic by default (adjust if stricter control is needed)
sudo iptables -P OUTPUT ACCEPT
⚠️ Critical Note: Setting INPUT to DROP without adding rules for essential services (e.g., SSH) will lock you out of remote systems. Always add allow rules before setting a default DROP policy.
3. Configuring Essential Chains
Now, let’s explicitly allow necessary traffic for each chain.
3.1 INPUT Chain: Allow Critical Incoming Traffic
The INPUT chain controls traffic destined for your system. Allow only what you need:
3.1.1 Allow Loopback Traffic
The loopback interface (lo) is used for local communication (e.g., between services on the same machine). Blocking it can break system functionality:
sudo iptables -A INPUT -i lo -j ACCEPT
3.1.2 Allow Established/Related Connections
Once a connection is initiated (e.g., you visit a website), allow后续 traffic for that connection to avoid blocking legitimate responses:
sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
ESTABLISHED: Packets part of an existing connection.RELATED: Packets related to an existing connection (e.g., FTP data transfer).
3.2 OUTPUT Chain: Restrict Outgoing Traffic (Optional)
By default, we set OUTPUT to ACCEPT, but you can restrict it further (e.g., block outbound traffic to suspicious IPs). For most users, ACCEPT is sufficient, but stricter setups might use:
# Example: Allow outbound HTTP/HTTPS only
sudo iptables -P OUTPUT DROP
sudo iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT # HTTP
sudo iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT # HTTPS
sudo iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
3.3 FORWARD Chain: Block Unneeded Forwarding
Unless your system acts as a router, block all forwarded traffic (already set via FORWARD DROP earlier).
4. Common Security Rules
Add rules to allow specific services while hardening against attacks.
4.1 Allow SSH Access (Critical for Remote Management)
If you use SSH to manage the system, explicitly allow it. For added security, restrict access to trusted IPs.
Example 1: Allow SSH from Any IP (Not Recommended for Public Servers)
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
Example 2: Allow SSH from a Specific IP (Recommended)
Restrict SSH to your management IP (e.g., 192.168.1.100):
sudo iptables -A INPUT -p tcp --dport 22 -s 192.168.1.100 -j ACCEPT
Example 3: Rate-Limit SSH to Prevent Brute-Force Attacks
Use the limit module to restrict repeated SSH login attempts:
sudo iptables -A INPUT -p tcp --dport 22 -m limit --limit 5/min --limit-burst 10 -j ACCEPT
--limit 5/min: Allow 5 connections per minute.--limit-burst 10: Allow 10 initial connections before enforcing the limit.
4.2 Allow Web Traffic (HTTP/HTTPS)
If running a web server, allow inbound traffic on ports 80 (HTTP) and 443 (HTTPS):
# Allow HTTP (port 80)
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
# Allow HTTPS (port 443)
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
4.3 Restrict ICMP (Ping) Traffic
ICMP (Internet Control Message Protocol) is used for ping and network diagnostics. Unrestricted ICMP can expose your system to reconnaissance or DoS attacks.
Option 1: Block All ICMP (Ping)
sudo iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
Option 2: Allow ICMP from Trusted IPs Only
sudo iptables -A INPUT -p icmp --icmp-type echo-request -s 192.168.1.0/24 -j ACCEPT
sudo iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
4.4 Log Dropped Packets
Logging helps monitor suspicious activity. Log dropped packets to /var/log/syslog (or /var/log/messages on RHEL-based systems):
# Log dropped INPUT packets with a prefix
sudo iptables -A INPUT -j LOG --log-prefix "iptables-DROP: " --log-level 4
--log-prefix: Adds a label to log entries for easy filtering.--log-level 4: Sets log severity (4 = “warning”).
5. Saving and Persisting Rules
iptables rules are temporary and reset after a reboot. To make them persistent:
Method 1: Use iptables-save and iptables-restore
Save rules to a file and restore them on boot:
# Save rules to /etc/iptables/rules.v4
sudo iptables-save | sudo tee /etc/iptables/rules.v4
# Restore rules (run on boot via cron, systemd, or rc.local)
sudo iptables-restore < /etc/iptables/rules.v4
Method 2: Use iptables-persistent (Debian/Ubuntu)
Install a tool to auto-save/restore rules:
sudo apt install iptables-persistent
# Save current rules when prompted, or run:
sudo netfilter-persistent save
Method 3: Use firewalld (RHEL/CentOS Stream)
On systems with firewalld (default on RHEL 8+), use firewall-cmd to manage iptables rules persistently. However, for direct iptables control, disable firewalld first:
sudo systemctl stop firewalld
sudo systemctl disable firewalld
6. Advanced Configurations
For enhanced security, implement these advanced rules.
6.1 Stateful Packet Inspection
Leverage the state module to allow only new, legitimate connections. For example, allow SSH only for new connections:
sudo iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT
6.2 Block Specific IPs/Subnets
Block known malicious IPs or entire subnets (e.g., 192.168.2.0/24):
sudo iptables -A INPUT -s 192.168.2.0/24 -j DROP
6.3 Port Forwarding (NAT Table)
If your system acts as a router, forward traffic from a public port to a private service (e.g., forward port 8080 to a local web server on port 80):
# Enable IP forwarding (temporarily)
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
# Add rule to nat table
sudo iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.10:80
6.4 Block Malicious Ports
Block well-known attack ports (e.g., 3389 for RDP, 445 for SMB) if unused:
sudo iptables -A INPUT -p tcp --dport 3389 -j DROP
sudo iptables -A INPUT -p tcp --dport 445 -j DROP
7. Best Practices for iptables Security
Follow these guidelines to maintain a secure firewall:
7.1 Audit Rules Regularly
List rules to review and prune unnecessary entries:
# List rules with details (numeric IPs, no DNS lookup)
sudo iptables -L -v -n
7.2 Minimize Open Ports
Only allow ports required for your use case (e.g., port 22 for SSH, 443 for HTTPS). Close unused ports (e.g., 21 for FTP if not needed).
7.3 Restrict by IP/Subnet
Avoid allowing traffic from 0.0.0.0/0 (all IPs). Use specific IPs or subnets (e.g., 192.168.1.0/24) for sensitive services like SSH.
7.4 Test Rules in Staging
Always test rules in a non-production environment first. Use iptables -L to verify, and temporarily set INPUT to ACCEPT if you lock yourself out.
7.5 Keep Software Updated
Update iptables and the kernel regularly to patch vulnerabilities in netfilter.
8. Troubleshooting iptables
If services fail or traffic is blocked unexpectedly, use these tools:
8.1 List Rules
View all rules with counters and numeric IPs:
sudo iptables -L -v -n --line-numbers
8.2 Check for Conflicts
Ensure no duplicate or conflicting rules (e.g., a DROP rule above an ACCEPT rule for the same port).
8.3 Test Connectivity
Use telnet or nc (netcat) to test if a port is reachable:
telnet your-server-ip 22 # Test SSH port
nc -zv your-server-ip 443 # Test HTTPS port
8.4 Flush Rules (Last Resort)
If rules are misconfigured, flush all rules and reset policies:
sudo iptables -F # Flush all rules
sudo iptables -X # Delete custom chains
sudo iptables -P INPUT ACCEPT # Temporarily allow all input
9. Conclusion
Configuring iptables effectively is critical for securing Linux systems. By following this guide—denying by default, allowing only essential traffic, and implementing advanced rules like rate limiting and logging—you can significantly reduce your exposure to attacks. Remember to test rules, persist them across reboots, and audit regularly to maintain a robust firewall.