Table of Contents
- What is iptables?
- How iptables Works: Tables, Chains, and Rules
- Prerequisites and Setup
- Interactive Exercise 1: Exploring Existing Rules
- Interactive Exercise 2: Adding and Removing Basic Rules
- Interactive Exercise 3: Setting Default Policies
- Interactive Exercise 4: Allowing Specific Inbound/Outbound Traffic
- Interactive Exercise 5: Blocking Unwanted IPs or Ports
- Interactive Exercise 6: Logging Traffic for Debugging
- Saving and Restoring Rules
- Troubleshooting Common iptables Issues
- Conclusion
- References
What is iptables?
Iptables is not a firewall itself—it is a command-line utility that configures the netfilter framework built into the Linux kernel. netfilter acts as a packet-processing pipeline, inspecting and modifying packets as they traverse the network stack. Iptables lets you define rules to:
- Filter packets (allow or block them based on criteria like IP, port, or protocol).
- Modify packets (e.g., rewrite source/destination IPs for NAT).
- Redirect traffic (e.g., port forwarding).
Nearly all Linux distributions ship with iptables preinstalled, making it a universal tool for network security.
How iptables Works: Tables, Chains, and Rules
To use iptables effectively, you must understand three core concepts: tables, chains, and rules.
Tables: Categories of Rules
Iptables organizes rules into tables, each designed for a specific purpose:
| Table | Purpose |
|---|---|
filter | Default table for packet filtering (allow/block traffic). |
nat | Network Address Translation (e.g., port forwarding, masquerading). |
mangle | Modify packet headers (e.g., TTL, QoS marking). |
raw | Bypass connection tracking for specific packets. |
security | Mandatory Access Control (MAC) rules (e.g., SELinux integration). |
The filter table is the most commonly used for basic firewalling.
Chains: Predefined Packet Paths
Within each table, rules are grouped into chains—predefined paths that packets follow. The filter table, for example, uses three primary chains:
| Chain | When is it triggered? |
|---|---|
INPUT | Packets destined for the local system (e.g., SSH into the server). |
OUTPUT | Packets originating from the local system (e.g., curl a website). |
FORWARD | Packets routed through the system (e.g., a Linux router). |
Other tables have additional chains (e.g., nat uses PREROUTING and POSTROUTING for NAT).
Rules: Conditions and Actions
A rule is a statement that tells iptables how to handle a packet. Each rule has:
- Matching criteria (e.g., “source IP 192.168.1.100”, “destination port 80”).
- Target (action to take if criteria are met:
ACCEPT,DROP,REJECT,LOG, etc.).
Rules are processed in order: the first matching rule determines the packet’s fate. If no rules match, the chain’s default policy (e.g., ACCEPT or DROP) is applied.
Prerequisites and Setup
Before diving into exercises, ensure you have:
- A Linux machine (physical or virtual; Ubuntu, CentOS, Debian, etc.).
- Root access (use
sudofor all iptables commands). - A test environment (avoid production systems—mistakes can lock you out!).
Installing iptables (if missing)
Most Linux systems include iptables by default. If not, install it:
- Debian/Ubuntu:
sudo apt install iptables - CentOS/RHEL:
sudo yum install iptables
Interactive Exercise 1: Exploring Existing Rules
Let’s start by inspecting the current iptables configuration. This helps you understand what rules are already in place (if any).
Step 1: List All Rules
Run the following command to list rules in the default filter table:
sudo iptables -L
Output Explanation:
- Chains (
INPUT,FORWARD,OUTPUT) and their default policies (e.g.,ACCEPT). - Rules (if any), including criteria and targets.
Example empty output:
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: Verbose and Numeric Output
For more details (e.g., packet counts, interface names), use -v (verbose) and -n (numeric IPs/ports instead of DNS names):
sudo iptables -L -v -n
Key Flags:
-v: Shows packet/byte counters for each rule.-n: Speeds up output by avoiding DNS lookups.
Step 3: Explore Other Tables
To view rules in the nat table (used for port forwarding), specify the table with -t:
sudo iptables -t nat -L -n
Exercise Goal: Run these commands and note the default policies and existing rules. If you’re on a fresh system, there may be no rules (default policies are ACCEPT).
Interactive Exercise 2: Adding and Removing Basic Rules
Now, let’s add, insert, and delete rules to modify traffic flow.
Step 1: Append a Rule to Allow HTTP Traffic
Let’s allow inbound HTTP traffic (port 80) on the INPUT chain. Use -A (append) to add the rule to the end of the chain:
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
Breakdown:
-A INPUT: Append the rule to theINPUTchain.-p tcp: Match TCP protocol.--dport 80: Match destination port 80 (HTTP).-j ACCEPT: Jump to theACCEPTtarget (allow the packet).
Step 2: Verify the Rule
List rules again to confirm the new rule exists:
sudo iptables -L INPUT -n
You should see a line like:
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
Step 3: Insert a Rule (Higher Priority)
Rules are processed in order. To add a rule before existing ones (e.g., allow SSH first), use -I (insert):
sudo iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT
Here, -I INPUT 1 inserts the rule at position 1 (top of the chain).
Step 4: Delete a Rule
To remove a rule, use -D (delete). You can specify the chain and rule number (from iptables -L --line-numbers):
sudo iptables -L INPUT --line-numbers # List rules with line numbers
sudo iptables -D INPUT 2 # Delete rule 2 in INPUT chain
Exercise Goal: Add a rule to allow HTTPS (port 443), insert an SSH rule at the top, then delete the HTTP rule.
Interactive Exercise 3: Setting Default Policies
Default policies define what happens to packets that don’t match any rules. They are critical for locking down a system.
Step 1: View Current Policies
Check the default policy for a chain with:
sudo iptables -L INPUT # Look for "policy ACCEPT"
Step 2: Set a Strict Default Policy
A common security practice is to set the INPUT chain to DROP (block all inbound traffic) and explicitly allow only needed services (e.g., SSH).
WARNING: If you set INPUT to DROP without allowing SSH first, you’ll lock yourself out of remote servers!
Safe Workflow:
- Allow SSH first:
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT - Set
INPUTpolicy toDROP:sudo iptables -P INPUT DROP - Test SSH access (open a new terminal to confirm you can still connect).
Step 3: Revert Policies
To restore INPUT to ACCEPT (e.g., for testing):
sudo iptables -P INPUT ACCEPT
Exercise Goal: Set INPUT to DROP, allow SSH, then test access. Revert to ACCEPT when done.
Interactive Exercise 4: Allowing Inbound/Outbound Traffic
Let’s expand to more granular control: allowing traffic from specific IPs, outbound connections, or related/invalid packets.
Allow Traffic from a Specific IP
To allow inbound SSH only from 192.168.1.50:
sudo iptables -A INPUT -s 192.168.1.50 -p tcp --dport 22 -j ACCEPT
Allow Outbound Traffic
By default, OUTPUT policy is ACCEPT, but if set to DROP, explicitly allow outbound traffic (e.g., web browsing):
sudo iptables -P OUTPUT DROP # Strict outbound policy
sudo iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT # Allow HTTP outbound
sudo iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT # Allow HTTPS outbound
Allow Related/Established Connections
To allow responses to outbound requests (e.g., a web server replying to your browser), use the state module:
sudo iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
This ensures existing connections (e.g., after you curl a website) are not blocked.
Exercise Goal: Allow SSH only from your IP, allow outbound DNS (port 53, UDP), and enable RELATED,ESTABLISHED for INPUT.
Interactive Exercise 5: Blocking Unwanted IPs or Ports
Blocking malicious IPs or ports is a common use case.
Block an IP Address
To block all traffic from 203.0.113.45:
sudo iptables -A INPUT -s 203.0.113.45 -j DROP
Block a Port Globally
To block inbound traffic on port 3306 (MySQL) from all IPs:
sudo iptables -A INPUT -p tcp --dport 3306 -j DROP
Reject vs. Drop
DROP: Silently discard the packet (attacker gets no response).REJECT: Send an error response (e.g., “connection refused”).
Example: Reject HTTP with a TCP reset:
sudo iptables -A INPUT -p tcp --dport 80 -j REJECT --reject-with tcp-reset
Exercise Goal: Block a test IP (e.g., 192.168.1.99), then reject port 8080.
Interactive Exercise 6: Logging Traffic for Debugging
The LOG target lets you log packets to the kernel ring buffer (viewable in /var/log/kern.log).
Log SSH Attempts
Log all SSH connection attempts with a custom prefix:
sudo iptables -A INPUT -p tcp --dport 22 -j LOG --log-prefix "SSH ATTEMPT: " --log-level 4
View Logs
Check logs with:
sudo tail -f /var/log/kern.log | grep "SSH ATTEMPT"
Test by attempting an SSH connection from another machine—you’ll see log entries!
Exercise Goal: Log HTTP traffic, then view logs to confirm.
Saving and Restoring Rules
By default, iptables rules are stored in memory and lost on reboot. To persist them:
Save Rules Temporarily
Use iptables-save to export rules to a file:
sudo iptables-save > /etc/iptables/rules.v4
Restore Rules
To reload rules (e.g., after a reboot):
sudo iptables-restore < /etc/iptables/rules.v4
Persistent Saving (Distribution-Specific)
- Debian/Ubuntu: Use
iptables-persistentto auto-save/restore:sudo apt install iptables-persistent sudo netfilter-persistent save # Save current rules - CentOS/RHEL: Use
iptables-service:sudo service iptables save
Exercise Goal: Save your current rules to a file, reboot, then restore them.
Troubleshooting Common iptables Issues
- Locked out of SSH: Reboot the server (rules reset) or use a console (if virtual).
- Rules not working: Use
iptables -L -vto check packet counters (non-zero means rules are matching). - Rules lost on reboot: Always save rules with
iptables-saveor distribution tools. - DNS failures: Ensure outbound UDP port 53 is allowed (DNS uses UDP).
Conclusion
Iptables is a powerful tool for controlling network traffic, but mastery comes with practice. By working through these exercises, you’ve learned to filter traffic, set policies, and troubleshoot common issues. Remember:
- Always test rules in a non-production environment.
- Save rules to persist them across reboots.
- Start with a default
DROPpolicy and explicitly allow only needed traffic.
With these skills, you can secure servers, configure firewalls, and debug network issues like a pro!