π§° 05-05: iptables Fundamentals¶
π What Is iptables?¶
iptables is the traditional command-line firewall configuration tool on Linux. It's important to be precise about what iptables actually is, because the terminology trips people up:
- Netfilter is the actual packet-filtering framework built into the Linux kernel. It defines a series of "hook points" inside the kernel's networking stack where code can inspect, modify, or drop packets as they pass through.
- iptables is the user-space program administrators use to write rules into Netfilter. It does not do the filtering itself β it just configures the kernel's tables.
- In casual conversation, "iptables" is often used to refer to the whole system (kernel + tool), but technically the enforcement engine in the kernel is Netfilter/Xtables, and iptables is just the control interface to it.
π‘ Think of it like a light switch and the electrical wiring behind the wall: iptables is the switch, Netfilter is the wiring that actually does the work. Modern distros are transitioning to a newer tool called nftables, but iptables remains extremely widely used and is the best starting point for learning the underlying concepts.
ποΈ Tables¶
iptables organizes rules into tables, where each table serves a distinct purpose. This is the top level of the hierarchy β you almost always specify a table before you specify anything else.
| Table | Purpose |
|---|---|
| filter | The default table β decides whether to ACCEPT, DROP, or REJECT packets. This is "the firewall" in the everyday sense. |
| nat | Handles Network Address Translation β rewriting source or destination addresses/ports (used for port forwarding, masquerading internal hosts, etc.) |
| mangle | Used for specialized packet modification β altering TTL, marking packets for later processing (QoS), changing TOS/DSCP fields |
| raw | Used to mark packets that should bypass connection tracking entirely (an advanced/rare use case) |
π‘ If you don't specify -t <table> in an iptables command, it defaults to the filter table.
π Chains¶
Within each table, rules are grouped into chains. A chain is simply an ordered list of rules that gets checked at a specific point in a packet's journey through the kernel.
| Chain | When It's Checked |
|---|---|
| PREROUTING | As soon as a packet arrives, before the kernel decides where to route it |
| INPUT | For packets destined for this local machine |
| FORWARD | For packets passing through this machine to somewhere else (e.g., this machine is acting as a router) |
| OUTPUT | For packets originating from this local machine |
| POSTROUTING | Just before a packet leaves the network interface, after routing has been decided |
Not every chain exists in every table β a table only has the chains relevant to its purpose:
| Table | Available Chains |
|---|---|
| filter | INPUT, FORWARD, OUTPUT |
| nat | PREROUTING, OUTPUT, POSTROUTING |
| mangle | PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING |
| raw | PREROUTING, OUTPUT |
π¦ How a Packet Traverses the Chains¶
This is the single most important mental model for using iptables correctly. Depending on where a packet is going, it passes through a different sequence of chains.
βββββββββββββββ
Packet arrives ββββββββββββββββΆβ PREROUTING β (nat: DNAT happens here)
on a network ββββββββ¬βββββββ
interface β
βΌ
βββββββββββββββββββ
β Routing Decision β
β (is this packet β
β for ME, or to β
β be FORWARDED?) β
βββββββββ¬βββββββββββ
ββββββββββββββββββββ΄βββββββββββββββββββ
βΌ βΌ
βββββββββββββββββ βββββββββββββββββ
β INPUT β β FORWARD β
β (destined for β β (passing β
β this host) β β through) β
βββββββββ¬βββββββββ βββββββββ¬βββββββββ
βΌ β
ββββββββββββββββββββ β
β Local Process / β β
β Application β β
βββββββββββ¬ββββββββββ β
βΌ β
βββββββββββββββββ β
β OUTPUT β β
β (generated by β β
β this host) β β
βββββββββ¬βββββββββ β
ββββββββββββββββββββ¬ββββββββββββββββββββ
βΌ
ββββββββββββββββ
β POSTROUTING β (nat: SNAT/MASQUERADE here)
ββββββββ¬ββββββββ
βΌ
Packet leaves the
network interface
Reading the Diagram¶
- Traffic destined for a service running on this machine (e.g., someone SSHing into this server):
PREROUTING β INPUT - Traffic this machine generates itself (e.g., this machine making an outbound HTTP request):
OUTPUT β POSTROUTING - Traffic this machine is only routing/forwarding for others (e.g., this machine acting as a home router passing traffic from your laptop to the internet):
PREROUTING β FORWARD β POSTROUTINGβ it never touches INPUT or OUTPUT at all - DNAT (destination NAT / port forwarding) rules live in
PREROUTING, because the destination address needs to be rewritten before the routing decision is made - SNAT/MASQUERADE (source NAT) rules live in
POSTROUTING, because the source address should be rewritten after routing, right before the packet leaves the interface
π‘ A very common beginner mistake is writing a rule in the INPUT chain expecting it to affect traffic that's actually being forwarded through the machine (e.g., traffic from a home network out to the internet via a Linux router). That traffic never touches INPUT/OUTPUT β you need FORWARD.
π― Default Policies¶
Every chain in the filter table has a default policy β what to do with a packet that reaches the end of the chain without matching any rule. This is the practical implementation of "default deny vs. default allow" from 05-01: Firewall Concepts & History.
# View current default policies (shown in the "Chain ... (policy ...)" header)
sudo iptables -L
# Set the INPUT chain's default policy to DROP (default-deny)
sudo iptables -P INPUT DROP
# Set the FORWARD chain's default policy to DROP
sudo iptables -P FORWARD DROP
# OUTPUT is often left as ACCEPT for a typical server (be cautious β see 05-08)
sudo iptables -P OUTPUT ACCEPT
β οΈ Important safety note: if you're configuring a remote server over SSH, setting the INPUT policy to DROP before you've added a rule that explicitly allows your SSH connection will instantly lock you out. Always add your allow rules first, then tighten the default policy last.
π Listing and Viewing Rules¶
The single most useful iptables command for a beginner is:
Breaking down the flags:
| Flag | Meaning |
|---|---|
-L |
List the rules in a chain (or all chains, if none specified) |
-v |
Verbose β show packet/byte counters and interface names |
-n |
Numeric β show IP addresses and ports as numbers, not resolved hostnames/service names (much faster, and avoids DNS lookups leaking information) |
Other Useful Viewing Commands¶
# List rules in the nat table specifically
sudo iptables -t nat -L -v -n
# List rules with line numbers (needed to delete a specific rule by position)
sudo iptables -L --line-numbers
# Delete rule number 2 from the INPUT chain
sudo iptables -D INPUT 2
# Flush (delete) all rules in the filter table's chains
sudo iptables -F
# Flush all rules in the nat table
sudo iptables -t nat -F
π‘ iptables rules are not persistent by default β a reboot wipes them unless you save them with a distro-specific tool (e.g., iptables-save / iptables-persistent on Debian/Ubuntu, or a systemd unit that reapplies a saved rule file at boot).
π Key Takeaways¶
- iptables is the user-space tool that configures Netfilter, the actual packet-filtering engine inside the Linux kernel.
- Rules are organized into tables (filter, nat, mangle, raw), each with a distinct purpose; filter is the default and most commonly used.
- Within each table, rules are grouped into chains (PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING) tied to specific points in a packet's journey.
- Which chains a packet passes through depends on whether it's destined for the local machine (INPUT), generated by it (OUTPUT), or merely passing through (FORWARD) β this is the core mental model for writing correct rules.
- DNAT (destination NAT) happens in PREROUTING; SNAT/MASQUERADE (source NAT) happens in POSTROUTING.
- Every chain has a default policy (ACCEPT or DROP) that applies when no rule matches β set your allow rules before tightening the default policy to DROP, especially on a remote machine.
iptables -L -v -nis the essential command for viewing current rules with packet counters and numeric addresses.- iptables rules do not survive a reboot unless explicitly saved β this trips up many beginners in labs and real deployments alike.