iptables
iptables is the user-space command-line tool for configuring the Linux kernel's netfilter packet filtering framework. It organises rules into tables (filter, nat, mangle) and chains (INPUT, OUTPUT, FORWARD) that evaluate every network packet passing through the system.
Understanding iptables
What Is iptables in Simple Terms
iptables is the traditional way to write firewall rules on Linux. It talks directly to the kernel's netfilter system and gives you precise control over exactly what happens to every network packet. Modern tools like ufw and firewalld are frontends that write iptables rules for you — but understanding iptables directly is essential for debugging, for working with Docker, and for production systems where the automatic tools create unexpected rules.
How It Works
+------------------------------------------+| Tables and Chains || || filter table (default -- allow/block) || INPUT -- packets destined for host || OUTPUT -- packets from host || FORWARD -- packets routed through host || || nat table (address translation) || PREROUTING -- before routing decision || POSTROUTING -- after routing decision || || mangle table (packet modification) |+------------------------------------------+Rule anatomy:
iptables -A INPUT -p tcp --dport 22 -s 10.0.0.0/8 -j ACCEPT| | | | | |tool chain protocol dest port source IP action Actions: ACCEPT -- allow the packet DROP -- silently discard REJECT -- discard and send ICMP error back LOG -- log to syslog and continuePractical Commands
## View current rulessudo iptables -L -n -v## -L list -n numeric (no DNS lookup) -v verbose (packet counts) ## View with line numbers (needed for deletion)sudo iptables -L INPUT -n -v --line-numbers ## Basic production ruleset -- apply in order## 1. Allow established connections (stateful -- critical for performance)sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT ## 2. Allow loopbacksudo iptables -A INPUT -i lo -j ACCEPT ## 3. Allow SSH from internal network onlysudo iptables -A INPUT -p tcp --dport 22 -s 10.0.0.0/8 -j ACCEPT ## 4. Allow HTTPS from anywheresudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT ## 5. Set default policy to DROPsudo iptables -P INPUT DROPsudo iptables -P FORWARD DROPsudo iptables -P OUTPUT ACCEPT ## Delete a rule by line numbersudo iptables -D INPUT 3 ## Flush all rules (CAREFUL -- removes all rules)sudo iptables -F ## Save rules so they survive rebootsudo apt install iptables-persistentsudo iptables-save > /etc/iptables/rules.v4 ## Restore rulessudo iptables-restore < /etc/iptables/rules.v4 ## See what Docker addedsudo iptables -L DOCKER -n -vsudo iptables -L DOCKER-USER -n -v ## add your rules here to affect DockerTroubleshooting
| Symptom | Command | What to Check |
|---|---|---|
| All traffic blocked | sudo iptables -L -n |
Default policy is DROP with no allow rules |
| Rules lost on reboot | sudo iptables-save > /etc/iptables/rules.v4 |
Rules not persisted |
| Docker bypassing rules | sudo iptables -L DOCKER-USER |
Add rules to DOCKER-USER chain |
| Connection tracking full | `sudo conntrack -L | wc -l` |
TipAdd custom rules that affect Docker-exposed ports to the
DOCKER-USERchain, not theINPUTchain. Docker inserts its rules beforeINPUT, soINPUTrules do not affect Docker-managed ports. TheDOCKER-USERchain is evaluated before Docker's own rules.
Rememberiptables rules are ephemeral by default — they are lost on reboot. Always save rules with
iptables-saveafter confirming they work correctly. Useiptables-persistenton Debian/Ubuntu to automate restoration at boot.
Frequently Asked Questions
How do iptables chains and tables actually work together to process a packet?
Tables group rules by purpose — `filter` for allow/deny decisions, `nat` for address translation, `mangle` for packet header modification — and each table contains chains representing points in the packet's journey: INPUT (destined for this host), OUTPUT (originating here), and FORWARD (passing through, e.g. on a router). A packet traverses the relevant chains in order, and the first matching rule's target (ACCEPT, DROP, REJECT) decides its fate unless it's a chain with no match, which falls through to the chain's default policy.
What's a classic iptables mistake that locks admins out of a remote server?
Setting the INPUT chain's default policy to DROP before adding an explicit ACCEPT rule for SSH (port 22) — the moment that policy change applies, the remote session used to make it is cut off with no way back in except console/out-of-band access. Always add and verify the allow rules first, test connectivity from a second session, and only then set restrictive default policies — or use a tool like `ufw`/`firewalld` that applies changes more safely.