{
    "slug": "linux_iptables_netfilter",
    "term": "iptables and netfilter",
    "category": "linux",
    "difficulty": "advanced",
    "short": "Kernel packet-filtering framework (netfilter) and its classic userspace tool (iptables) for firewalling, NAT, and packet mangling.",
    "long": "netfilter is the in-kernel framework that hooks into the Linux network stack at fixed points, and iptables is the traditional userspace tool that programs its rules. Packets traverse a set of tables, each containing chains of rules evaluated in order. The filter table (chains INPUT, OUTPUT, FORWARD) accepts or drops traffic. The nat table (PREROUTING, POSTROUTING, OUTPUT) rewrites source/destination addresses for SNAT, DNAT, and masquerading. The mangle table alters packet fields like TOS or TTL, and the raw table can mark packets to skip connection tracking. Each chain has a default policy (ACCEPT or DROP) applied when no rule matches. Rules match on interface, protocol, source/destination address and port, connection state, and more, then jump to a target: ACCEPT, DROP, REJECT, LOG, DNAT, SNAT, MASQUERADE, or a user-defined chain. The order of packet flow matters: an incoming packet hits PREROUTING (raw, mangle, nat), then a routing decision sends it to INPUT (for local delivery) or FORWARD (for routing), and outgoing packets traverse OUTPUT and POSTROUTING. Connection tracking (conntrack) lets you write stateful rules with -m state or -m conntrack, so you allow ESTABLISHED,RELATED traffic without opening every return port. Rules are not persistent across reboots unless you save them (iptables-save / iptables-restore, or a service like netfilter-persistent). On modern systems iptables is increasingly a compatibility shim over nftables (the iptables-nft backend), and firewalld or ufw often manage the rules for you. Understanding the table and chain model is essential for debugging dropped connections, building NAT gateways, securing containers, and reasoning about why traffic arrives or vanishes.",
    "aliases": [
        "iptables",
        "netfilter",
        "linux firewall",
        "iptables rules"
    ],
    "tags": [
        "linux",
        "networking",
        "firewall",
        "nat",
        "security",
        "packet-filtering"
    ],
    "misconception": "Adding an ALLOW rule is enough to open a port. In reality rules are evaluated in order and the first match wins, so an earlier DROP or a default DROP policy combined with missing ESTABLISHED,RELATED handling can block your traffic regardless of a later ACCEPT rule.",
    "why_it_matters": "Firewall misconfiguration either locks you out of a server or silently leaves it wide open; understanding chain order and connection state is the difference between a secure host and a broken or exposed one.",
    "common_mistakes": [
        "Setting a default DROP policy on INPUT without first allowing loopback and ESTABLISHED,RELATED traffic, breaking all responses.",
        "Forgetting to save rules, so a carefully built firewall vanishes on reboot.",
        "Putting a broad ACCEPT rule before specific DROP rules, since the first match wins and later rules never run.",
        "Locking yourself out of SSH by applying a DROP policy over a remote session before adding the allow rule.",
        "Confusing the INPUT chain (traffic to the host) with the FORWARD chain (routed traffic), so container or gateway traffic is filtered in the wrong place."
    ],
    "when_to_use": [
        "Building a stateful host firewall on a server where you control the rule order precisely.",
        "Setting up NAT or masquerading on a gateway or router.",
        "Filtering forwarded traffic between network namespaces or containers.",
        "Debugging dropped or rewritten packets where you need to inspect chains, counters, and connection state."
    ],
    "avoid_when": [
        "You only need simple host firewalling and a higher-level tool like ufw or firewalld already manages rules cleanly.",
        "The system uses nftables natively and hand-written iptables rules would conflict with the nft ruleset.",
        "Container or orchestration runtimes (Docker, Kubernetes) are already managing the netfilter rules and manual edits would be overwritten.",
        "You need per-application policy that is better expressed with cgroups, eBPF, or a service mesh."
    ],
    "related": [
        "linux_networking_tools",
        "linux_namespaces",
        "tcp_vs_udp",
        "linux_processes"
    ],
    "prerequisites": [
        "linux_networking_tools",
        "tcp_vs_udp",
        "linux_processes"
    ],
    "refs": [
        "https://www.netfilter.org/documentation/index.html",
        "https://man7.org/linux/man-pages/man8/iptables.8.html",
        "https://wiki.archlinux.org/title/Iptables",
        "https://www.frozentux.net/iptables-tutorial/iptables-tutorial.html"
    ],
    "bad_code": "# Lock yourself out and break everything:\n# Set default DROP first, over an SSH session, with no allow rules yet.\niptables -P INPUT DROP\n# Connection freezes immediately - no loopback, no ESTABLISHED allowed.\n\n# Or: ACCEPT before the DROP, so the DROP never runs.\niptables -A INPUT -p tcp --dport 22 -j ACCEPT\niptables -A INPUT -p tcp -j ACCEPT          # matches everything first\niptables -A INPUT -p tcp --dport 22 -s 10.0.0.5 -j DROP  # never reached\n\n# And rules are gone after reboot because nothing was saved.",
    "good_code": "# Build a stateful firewall in the right order:\n# 1. Allow loopback and existing connections BEFORE any DROP.\niptables -A INPUT -i lo -j ACCEPT\niptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT\n\n# 2. Allow SSH from a trusted subnet (specific rule first).\niptables -A INPUT -p tcp --dport 22 -s 10.0.0.0/24 -j ACCEPT\n\n# 3. Allow HTTP/HTTPS.\niptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT\n\n# 4. Only now set the restrictive default policy.\niptables -P INPUT DROP\niptables -P FORWARD DROP\n\n# 5. Persist across reboots.\niptables-save > /etc/iptables/rules.v4\n# (or: netfilter-persistent save)\n\n# Inspect what is active, with rule numbers and counters:\niptables -L INPUT -n -v --line-numbers",
    "quick_fix": "Always allow loopback and 'conntrack --ctstate ESTABLISHED,RELATED' before setting a DROP policy, order specific rules before broad ones, and save with iptables-save so rules survive reboot.",
    "severity": "high",
    "effort": "medium",
    "created": "2026-06-07",
    "updated": "2026-06-07",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/linux_iptables_netfilter",
        "html_url": "https://codeclaritylab.com/glossary/linux_iptables_netfilter",
        "json_url": "https://codeclaritylab.com/glossary/linux_iptables_netfilter.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[iptables and netfilter](https://codeclaritylab.com/glossary/linux_iptables_netfilter) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/linux_iptables_netfilter"
            }
        }
    }
}