funwithlinux guide

A Step-by-Step Guide to Setting Up iptables

In the world of Linux security, **iptables** stands as a cornerstone tool for managing network traffic. As a user-space utility, it interfaces with the Linux kernel’s `netfilter` framework to enforce rules that control incoming, outgoing, and forwarded network packets. Whether you’re securing a personal server, a home network, or a production environment, understanding iptables is critical to safeguarding your system from unauthorized access, malware, and other cyber threats. This guide will walk you through everything you need to know to set up and configure iptables from scratch. We’ll start with foundational concepts, move to practical rule creation, and cover advanced topics like persistence, logging, and troubleshooting. By the end, you’ll have a robust firewall tailored to your needs.

Table of Contents

  1. Prerequisites
  2. Understanding iptables Basics
    • 2.1 Chains
    • 2.2 Tables
    • 2.3 Policies
    • 2.4 Rule Structure
  3. Step 1: Check Current iptables Rules
  4. Step 2: Backup Existing Rules
  5. Step 3: Set Default Policies
  6. 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)
  7. 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
  8. Step 6: Manage and Modify Rules
    • 6.1 Insert, Append, Delete, or Replace Rules
    • 6.2 Flush Rules (Reset)
  9. Step 7: Save Rules Permanently
    • 7.1 Debian/Ubuntu Systems
    • 7.2 RHEL/CentOS Systems
    • 7.3 Generic Method (iptables-save/restore)
  10. Troubleshooting Common Issues
  11. Conclusion
  12. 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 -v for verbose output (shows packet/byte counts):
    sudo iptables -vL  
  • Add -n to 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 IP 192.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 with tail -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:

  1. 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  
  2. 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 DROP rule above an ACCEPT rule will block the traffic. Use iptables -vnL to reorder rules.
  • Verify interfaces/protocols: Ensure -i (incoming interface) or -p (protocol) matches the traffic (e.g., tcp vs udp).

No Logs for Dropped Packets

  • Ensure the LOG rule comes before the DROP rule 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.

References