Table of Contents
- Prerequisites
- Understanding iptables Basics
- 2.1 Chains
- 2.2 Tables
- 2.3 Policies
- 2.4 Rule Structure
- Step 1: Check Current iptables Rules
- Step 2: Backup Existing Rules
- Step 3: Set Default Policies
- Step 4: Add Essential Rules
- 4.1 Allow Loopback Traffic
- 4.2 Allow SSH Access
- 4.3 Allow HTTP/HTTPS (Web Traffic)
- 4.4 Allow ICMP (Ping) (Optional)
- Step 5: Advanced Rule Configuration
- 5.1 Limit SSH Brute-Force Attacks
- 5.2 Port Forwarding (NAT)
- 5.3 Logging Traffic
- 5.4 Rate Limiting
- Step 6: Manage and Modify Rules
- 6.1 Insert, Append, Delete, or Replace Rules
- 6.2 Flush Rules (Reset)
- Step 7: Save Rules Permanently
- 7.1 Debian/Ubuntu Systems
- 7.2 RHEL/CentOS Systems
- 7.3 Generic Method (iptables-save/restore)
- Troubleshooting Common Issues
- Conclusion
- References
Prerequisites
Before diving in, ensure you have:
- A Linux-based system (e.g., Ubuntu, Debian, CentOS, RHEL). iptables is preinstalled on most Linux distributions.
- Root or sudo access: Firewall configuration requires administrative privileges.
- Basic familiarity with the Linux command line.
- A text editor (e.g.,
nano,vim) for editing configuration files (if needed).
Understanding iptables Basics
To use iptables effectively, you first need to grasp its core components:
2.1 Chains
iptables organizes rules into chains—predefined sets of rules that process packets in a specific order. The most common chains are:
- INPUT: Controls incoming traffic destined for the local system.
- OUTPUT: Controls outgoing traffic originating from the local system.
- FORWARD: Controls traffic routed through the system (relevant for routers/gateways).
2.2 Tables
Chains are grouped into tables, each serving a specific purpose:
- filter: The default table for packet filtering (controls INPUT, OUTPUT, FORWARD chains).
- nat: Used for Network Address Translation (e.g., port forwarding, masquerading).
- mangle: Alters packet headers (e.g., changing TTL values).
- raw: Bypasses connection tracking for specific packets (advanced use cases).
For most users, the filter table will be the primary focus.
2.3 Policies
Each chain has a default policy—an action to take if no rule in the chain matches a packet. Common policies:
ACCEPT: Allow the packet.DROP: Silently discard the packet (no response sent to the sender).REJECT: Discard the packet and send a “connection refused” response.
A secure starting point is to set DROP as the default policy for INPUT and FORWARD chains, and ACCEPT for OUTPUT (to allow outgoing traffic).
2.4 Rule Structure
An iptables rule follows this general format:
iptables [-t table] COMMAND chain [match] [-j target]
-t table: Specify the table (default:filter).COMMAND: Action to perform (e.g.,Add,Insert,Delete a rule).chain: The chain to modify (e.g.,INPUT).match: Criteria to filter packets (e.g., protocol-p tcp, port--dport 22).-j target: Action to take if the packet matches (e.g.,ACCEPT,DROP).
Step 1: Check Current iptables Rules
Before making changes, inspect your existing rules to avoid conflicts. Run:
sudo iptables -L
-L: List all rules.- Add
-vfor verbose output (shows packet/byte counts):sudo iptables -vL - Add
-nto display IP addresses/ports numerically (faster, no DNS lookups):sudo iptables -vnL
If no rules exist, you’ll see output like:
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Step 2: Backup Existing Rules
Always back up rules before modifying them—this lets you restore if something breaks (e.g., accidentally locking yourself out).
Save rules to a file:
sudo iptables-save > /path/to/backup.rules
Example:
sudo iptables-save > ~/iptables_backup_$(date +%F).rules
To restore later (if needed):
sudo iptables-restore < /path/to/backup.rules
Step 3: Set Default Policies
Start with a secure baseline by setting restrictive default policies. For a single server (not a router), we’ll focus on INPUT and OUTPUT:
# Set INPUT policy to DROP (block all incoming traffic by default)
sudo iptables -P INPUT DROP
# Set FORWARD policy to DROP (block forwarded traffic; skip if not a router)
sudo iptables -P FORWARD DROP
# Set OUTPUT policy to ACCEPT (allow all outgoing traffic by default)
sudo iptables -P OUTPUT ACCEPT
⚠️ Warning: If you’re connected via SSH, setting INPUT to DROP without first allowing SSH traffic will lock you out! Proceed to Step 4 immediately after setting policies.
Step 4: Add Essential Rules
Now, explicitly allow traffic you need.
4.1 Allow Loopback Traffic
The loopback interface (lo) is critical for local services (e.g., databases, inter-process communication). Allow it with:
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A OUTPUT -o lo -j ACCEPT
-i lo: Matches packets incoming on the loopback interface.-o lo: Matches packets outgoing on the loopback interface.
4.2 Allow SSH Access
To avoid locking yourself out, allow SSH (port 22) traffic. Replace 22 with your SSH port if you’ve customized it (e.g., 2222):
# Allow incoming SSH from any IP (not recommended for production)
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Restrict to a specific IP (more secure; replace 192.168.1.100 with your IP)
sudo iptables -A INPUT -p tcp --dport 22 -s 192.168.1.100 -j ACCEPT
-p tcp: Match TCP protocol.--dport 22: Target destination port 22.-s 192.168.1.100: Restrict to source IP192.168.1.100(optional but recommended).
4.3 Allow HTTP/HTTPS (Web Traffic)
If running a web server, allow HTTP (port 80) and HTTPS (port 443):
# 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.4 Allow ICMP (Ping) (Optional)
To let others ping your server, allow ICMP echo requests:
sudo iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
To block pings (more secure), skip this step (default DROP policy will block it).
Step 5: Advanced Rule Configuration
5.1 Limit SSH Brute-Force Attacks
Use the recent module to block repeated SSH login attempts from the same IP:
# Allow SSH, but block IPs with > 5 attempts in 60 seconds
sudo iptables -A INPUT -p tcp --dport 22 -m recent --name ssh_brute --rcheck --seconds 60 --hitcount 5 -j DROP
sudo iptables -A INPUT -p tcp --dport 22 -m recent --name ssh_brute --set -j ACCEPT
--name ssh_brute: Name the list of tracked IPs.--rcheck: Check if the IP is in the list.--seconds 60: Track attempts over 60 seconds.--hitcount 5: Block after 5 attempts.--set: Add the IP to the list on first attempt.
5.2 Port Forwarding (NAT)
If you need to forward traffic from the server to another device (e.g., a local web server on 192.168.1.5:8080), use the nat table:
# Enable IP forwarding (temporarily; persists after reboot with sysctl)
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
# Forward incoming port 80 to 192.168.1.5:8080
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.1.5:8080
# Allow forwarded traffic
sudo iptables -A FORWARD -p tcp -d 192.168.1.5 --dport 8080 -j ACCEPT
5.3 Logging Traffic
Log denied packets to debug or monitor threats. Use the LOG target before DROP:
# Log dropped INPUT packets (limit to 10 logs/second to avoid flooding)
sudo iptables -A INPUT -m limit --limit 10/min -j LOG --log-prefix "iptables-DROP: " --log-level 4
--log-prefix: Add a label to log entries.--log-level 4: Log at “warning” level (view withtail -f /var/log/syslog).
5.4 Rate Limiting
Limit incoming connections (e.g., to prevent DDoS on a web server):
# Allow HTTP with max 100 connections/IP
sudo iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 100 -j REJECT
Step 6: Manage and Modify Rules
6.1 Insert, Append, Delete, or Replace Rules
-
Append a rule to the end of a chain:
sudo iptables -A INPUT -p udp --dport 53 -j ACCEPT # Allow DNS (UDP port 53) -
Insert a rule at a specific position (e.g., position 1):
sudo iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT # Insert SSH rule at top -
Delete a rule by line number (find line numbers with
iptables -L --line-numbers):sudo iptables -L INPUT --line-numbers # List INPUT rules with line numbers sudo iptables -D INPUT 3 # Delete rule 3 in INPUT chain -
Replace a rule (e.g., replace line 2 in INPUT):
sudo iptables -R INPUT 2 -p tcp --dport 2222 -j ACCEPT # Change SSH port to 2222
6.2 Flush Rules (Reset)
To clear all rules (use with caution!):
sudo iptables -F # Flush all chains in the default table
sudo iptables -t nat -F # Flush nat table (if used)
Step 7: Save Rules Permanently
By default, iptables rules are temporary—they vanish after a reboot. To persist rules:
7.1 Debian/Ubuntu Systems
Use the iptables-persistent package:
# Install the package
sudo apt update && sudo apt install iptables-persistent
# Save rules (runs automatically on install; re-run after changes)
sudo netfilter-persistent save
Rules are stored in /etc/iptables/rules.v4 (IPv4) and /etc/iptables/rules.v6 (IPv6).
7.2 RHEL/CentOS Systems
Use iptables-save and systemd:
# Save rules to /etc/sysconfig/iptables
sudo iptables-save > /etc/sysconfig/iptables
# Enable and start the iptables service
sudo systemctl enable iptables
sudo systemctl start iptables
7.3 Generic Method
For other distros, create a systemd service or add iptables-restore to /etc/rc.local (deprecated in some systems). Example systemd service:
-
Create
/etc/systemd/system/iptables-restore.service:[Unit] Description=Restore iptables rules After=network.target [Service] Type=oneshot ExecStart=/sbin/iptables-restore /path/to/saved.rules RemainAfterExit=yes [Install] WantedBy=multi-user.target -
Enable and start:
sudo systemctl daemon-reload sudo systemctl enable iptables-restore sudo systemctl start iptables-restore
Troubleshooting Common Issues
Locked Out via SSH
If you accidentally blocked SSH, use a local console (physical access or virtual machine console) to restore rules from your backup.
Rules Not Taking Effect
- Check rule order: iptables processes rules top-to-bottom. A
DROPrule above anACCEPTrule will block the traffic. Useiptables -vnLto reorder rules. - Verify interfaces/protocols: Ensure
-i(incoming interface) or-p(protocol) matches the traffic (e.g.,tcpvsudp).
No Logs for Dropped Packets
- Ensure the
LOGrule comes before theDROPrule in the chain.
Testing Rules Safely
Use iptables-apply to test rules without locking yourself out. It reverts changes if you lose connectivity:
sudo iptables-save > test.rules
# Edit test.rules, then apply with a 30-second timeout
sudo iptables-apply test.rules
Conclusion
iptables is a powerful tool for securing Linux systems by controlling network traffic. By following this guide, you’ve learned to:
- Set secure default policies.
- Allow essential traffic (SSH, HTTP, loopback).
- Add advanced rules (logging, rate limiting, brute-force protection).
- Persist rules across reboots.
Remember to regularly review and update your rules as your needs change. For simpler management, consider frontends like ufw (Uncomplicated Firewall) or firewalld, but mastering iptables directly gives you granular control.