iptables Firewall

iptables cheatsheet — allow/block ports and IPs, NAT rules, forward traffic. iptables -A INPUT -p tcp --dport 80 -j ACCEPT. List, save, restore rules. Full reference.

8 min read

What it is

iptables is a command-line utility for configuring the Linux kernel firewall, allowing you to define rules for filtering and manipulating network packets. You reach for it when you need fine-grained control over network traffic entering, leaving, or passing through your Linux system.

Installation

iptables is typically pre-installed on most Linux distributions. If not:

Debian/Ubuntu:

sudo apt update
sudo apt install iptables

CentOS/RHEL/Fedora:

sudo yum update
sudo yum install iptables

or

sudo dnf update
sudo dnf install iptables

Arch Linux:

sudo pacman -Syu
sudo pacman -S iptables

Windows: iptables is a Linux-specific tool and cannot be directly installed or used on Windows. For Windows firewall management, use the built-in Windows Defender Firewall with Advanced Security or PowerShell cmdlets like New-NetFirewallRule.

Core Concepts

  • Tables: iptables organizes rules into tables. The most common are:
    • filter (default): Used for packet filtering (allowing or denying traffic).
    • nat: Used for Network Address Translation (e.g., masquerading outgoing connections).
    • mangle: Used for altering packet headers (e.g., for Quality of Service).
    • raw: Used for special handling of packets before connection tracking.
  • Chains: Within each table, rules are organized into chains. The built-in chains are:
    • INPUT: For packets destined for the local system.
    • OUTPUT: For packets originating from the local system.
    • FORWARD: For packets passing through the system (routing).
    • PREROUTING: In the nat and mangle tables, for packets before routing decisions.
    • POSTROUTING: In the nat and mangle tables, for packets after routing decisions.
  • Rules: A rule specifies criteria (matches) and a target (action to take).
  • Targets: The action to take when a packet matches a rule. Common targets include:
    • ACCEPT: Allow the packet.
    • DROP: Silently discard the packet.
    • REJECT: Discard the packet and send an error message back to the sender.
    • SNAT: Source Network Address Translation (change source IP).
    • MASQUERADE: A form of SNAT for dynamic IP addresses.
    • DNAT: Destination Network Address Translation (change destination IP).
    • LOG: Log the packet (usually before another target).
  • Policy: The default action for a chain if no rule matches.

Commands / Usage

Listing Rules

  • List all rules in the filter table:
    sudo iptables -L
    
    Shows rules in the INPUT, FORWARD, and OUTPUT chains.
  • List rules with line numbers and verbose output:
    sudo iptables -L -v -n --line-numbers
    
    Useful for identifying specific rules for modification or deletion. -n prevents DNS lookups for IPs.
  • List rules in a specific table:
    sudo iptables -t nat -L -v -n
    
    Lists rules in the nat table.
  • List rules in a specific chain:
    sudo iptables -L INPUT -v -n
    
    Lists rules only in the INPUT chain.

Adding Rules

  • Allow SSH traffic on the INPUT chain:
    sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
    
    Appends a rule to the INPUT chain to accept TCP packets destined for port 22.
  • Drop all incoming traffic on the INPUT chain (default deny):
    sudo iptables -P INPUT DROP
    
    Sets the default policy for the INPUT chain to DROP. Use with extreme caution! Ensure you have allowed essential services first.
  • Allow all outgoing traffic on the OUTPUT chain:
    sudo iptables -A OUTPUT -j ACCEPT
    
    Appends a rule to the OUTPUT chain to accept all outgoing packets.
  • Insert a rule at a specific position:
    sudo iptables -I INPUT 1 -i eth0 -p icmp -j ACCEPT
    
    Inserts a rule at position 1 in the INPUT chain to accept ICMP traffic from the eth0 interface.
  • Allow established and related connections:
    sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
    
    Crucial for allowing return traffic for outgoing connections.
  • Block an IP address from accessing the server:
    sudo iptables -A INPUT -s 192.168.1.100 -j DROP
    
    Drops all incoming packets from the source IP 192.168.1.100.
  • Allow traffic only from a specific internal network:
    sudo iptables -A INPUT -i eth0 -s 192.168.0.0/24 -j ACCEPT
    
    Accepts incoming traffic on interface eth0 from the 192.168.0.0/24 subnet.
  • Allow HTTP and HTTPS traffic:
    sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
    sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
    
  • Masquerade outgoing traffic for a specific interface:
    sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
    
    Changes the source IP address of outgoing packets on eth0 to the IP address of eth0. Essential for sharing internet connections.
  • Forward traffic from one interface to another:
    sudo iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT
    sudo iptables -A FORWARD -i eth1 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
    
    Allows traffic to flow from eth0 to eth1 and the corresponding return traffic. Requires IP forwarding to be enabled (sysctl net.ipv4.ip_forward=1).
  • Log dropped packets (before dropping them):
    sudo iptables -A INPUT -j LOG --log-prefix "IPTables-Dropped: "
    sudo iptables -A INPUT -j DROP
    
    Logs packets that would be dropped, then drops them.

Deleting Rules

  • Delete a rule by its number:
    sudo iptables -D INPUT 3
    
    Deletes the 3rd rule in the INPUT chain. Use iptables -L --line-numbers to find numbers.
  • Delete a rule by specifying the exact rule:
    sudo iptables -D INPUT -p tcp --dport 80 -j ACCEPT
    
    Deletes the exact rule that accepts TCP traffic on port 80.
  • Flush all rules from a chain:
    sudo iptables -F INPUT
    
    Removes all rules from the INPUT chain.
  • Flush all rules from all chains in a table:
    sudo iptables -t nat -F
    
    Removes all rules from all chains in the nat table.
  • Flush all rules from all chains in all tables:
    sudo iptables -P INPUT ACCEPT && sudo iptables -P FORWARD ACCEPT && sudo iptables -P OUTPUT ACCEPT
    sudo iptables -F
    sudo iptables -t nat -F
    sudo iptables -t mangle -F
    sudo iptables -t raw -F
    
    Resets the firewall to a permissive state. Use with extreme caution!

Modifying Rules

  • Replace a rule:
    sudo iptables -R INPUT 2 -s 10.0.0.5 -j ACCEPT
    
    Replaces the 2nd rule in the INPUT chain with a new rule allowing traffic from 10.0.0.5.

Other Commands

  • Zero packet and byte counters:
    sudo iptables -Z
    
    Resets the counters for all rules.
  • Zero counters for a specific chain:
    sudo iptables -Z INPUT
    
  • Save current rules (distribution dependent):
    • Debian/Ubuntu (using iptables-persistent):
      sudo apt install iptables-persistent
      sudo netfilter-persistent save
      
    • CentOS/RHEL/Fedora:
      sudo service iptables save
      
      or
      sudo /sbin/iptables-save > /etc/sysconfig/iptables
      
  • Restore saved rules (distribution dependent):
    • Debian/Ubuntu: Rules are usually restored automatically on boot if iptables-persistent is installed.
    • CentOS/RHEL/Fedora:
      sudo service iptables restore
      
      or
      sudo /sbin/iptables-restore < /etc/sysconfig/iptables
      

Common Patterns

  • Basic Server Firewall (Allow SSH, HTTP, HTTPS, deny all else):
    # Flush existing rules
    sudo iptables -F
    sudo iptables -X
    sudo iptables -t nat -F
    sudo iptables -t nat -X
    
    # Set default policies to DROP
    sudo iptables -P INPUT DROP
    sudo iptables -P FORWARD DROP
    sudo iptables -P OUTPUT ACCEPT
    
    # Allow loopback traffic
    sudo iptables -A INPUT -i lo -j ACCEPT
    
    # Allow established and related connections
    sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
    
    # Allow SSH
    sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
    
    # Allow HTTP
    sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
    
    # Allow HTTPS
    sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
    
    # Log and drop everything else (optional, for debugging)
    # sudo iptables -A INPUT -j LOG --log-prefix "IPTables-Denied: "
    # sudo iptables -A INPUT -j DROP
    
  • Internet Connection Sharing (Masquerading):
    # Assuming eth0 is the WAN interface and eth1 is the LAN interface
    # Enable IP forwarding
    echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
    
    # Allow FORWARD traffic
    sudo iptables -P FORWARD ACCEPT
    
    # Masquerade outgoing traffic from LAN
    sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
    
    # Allow established/related traffic back in
    sudo iptables -A FORWARD -i eth0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
    sudo iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
    
  • Blocking a range of IPs:
    # Block IPs from 192.168.1.100 to 192.168.1.150
    sudo iptables -A INPUT -s 192.168.1.100/27 -j DROP
    
    (Note: /27 covers 32 IPs, adjust CIDR as needed).
  • Rate limiting connections to prevent DoS:
    sudo iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 100 -j DROP
    
    Drops connections if more than 100 simultaneous connections are established to port 80.

Gotchas

  • Order Matters: Rules are processed sequentially. The first matching rule determines the packet’s fate. Place more specific rules before general ones.
  • Default Policies: Setting default policies to DROP is secure but dangerous if not done carefully. Always ensure you have rules to ACCEPT essential services (like SSH) before setting the policy to DROP, or you’ll lock yourself out.
  • Stateful Firewalling: Always include rules for ESTABLISHED,RELATED connections. Without them, return packets for your own outgoing connections will be blocked.
  • Saving Rules: iptables rules are volatile and disappear on reboot by default. You must use a mechanism like iptables-persistent (Debian/Ubuntu) or service iptables save (CentOS/RHEL) to make them permanent.
  • Interface Specificity: Using -i <interface> (input interface) and -o <interface> (output interface) makes rules more precise and prevents unintended matches.
  • REJECT vs DROP: DROP silently discards packets, making your system appear non-existent to probes. REJECT sends an ICMP error back, which can be useful for internal networks but can also provide information to potential attackers.
  • IPv6: iptables only manages IPv4 traffic. For IPv6, use ip6tables with similar syntax.
  • iptables vs nftables: Modern Linux systems are transitioning to nftables, which aims to replace iptables, ip6tables, arptables, and ebtables with a single, more flexible tool. While iptables commands often still work via a compatibility layer, understanding nftables is recommended for new configurations.
  • Logging Overhead: Excessive logging can impact performance. Use logging strategically, especially for dropped packets.
  • User vs. Root: All iptables commands require root privileges (sudo).