iptables is the classic Linux user-space tool for defining packet filtering, network address translation and packet mangling rules that the kernel enforces through the Netfilter framework. In Linux networking, it is the interface through which administrators tell the kernel which packets to accept, drop, forward or rewrite, organized into tables, chains and rules.
For about two decades, iptables was the standard Linux firewall. Modern distributions have moved to nftables as the kernel backend, but the iptables command remains widespread, often running as iptables-nft, a compatibility layer that translates the familiar syntax into nftables rules.
How the Netfilter rule system works
Netfilter places hooks at fixed points in the kernel’s packet path. iptables attaches chains to those hooks, and each chain is an ordered list of rules. A rule consists of match criteria, such as protocol, address, port or connection state, and a target that says what to do when the packet matches.
Rules are evaluated from top to bottom, and the first rule with a terminating target, such as ACCEPT or DROP, ends the evaluation for that chain. If no rule matches, the chain’s default policy applies. This first-match ordering is the single most important property to understand, because a broad rule placed too early silently overrides every specific rule below it.
The conntrack subsystem gives iptables its stateful behavior. It tracks each connection and labels packets as NEW, ESTABLISHED, RELATED or INVALID, so a rule such as -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT lets return traffic in without opening ports for unsolicited connections.
Tables, chains and targets
iptables groups chains into tables by purpose. The filter table is used when no table is named, and most firewall work happens there. The table below shows which built-in chains each table offers and what it is for.
| Table | Built-in chains | Purpose |
|---|---|---|
| filter | INPUT, FORWARD, OUTPUT | Accept or block packets |
| nat | PREROUTING, INPUT, OUTPUT, POSTROUTING | Rewrite source or destination addresses |
| mangle | All five chains | Alter packet headers and marks |
| raw | PREROUTING, OUTPUT | Exempt traffic from connection tracking |
| security | INPUT, FORWARD, OUTPUT | Apply SELinux security labels |
The chain a packet traverses depends on its direction. Packets for the local host pass PREROUTING then INPUT, locally generated packets pass OUTPUT then POSTROUTING, and routed packets pass PREROUTING, FORWARD and POSTROUTING. Administrators can also create user-defined chains and jump to them to keep large rule sets readable.
| Target | Effect | Typical use |
|---|---|---|
| ACCEPT | Lets the packet continue | Allow SSH on port 22 |
| DROP | Discards the packet silently | Block scans without a reply |
| REJECT | Discards and sends an error | Fail fast for internal clients |
| LOG | Writes to the kernel log, then continues | Audit dropped traffic |
| MASQUERADE | Source NAT to the outgoing interface address | Share a dynamic public IP |
| DNAT | Rewrites the destination address | Port forwarding to an internal server |
Comparison with nftables, UFW and firewalld
iptables is one layer in a family of Linux firewall tools, and confusion often comes from mixing them. nftables is the newer kernel framework and language, while UFW and firewalld are higher-level managers that generate rules for whichever backend is present.
| Tool | Level | Strengths | Limitations |
|---|---|---|---|
| iptables | Rule tool for Netfilter | Mature, universally documented | Separate tools per protocol family |
| nftables | Successor framework and tool | Sets, maps, atomic updates | Different syntax to learn |
| UFW | Front end | Very simple host firewall | Limited for complex routing |
| firewalld | Zone-based daemon | Runtime changes via D-Bus | Abstraction hides details |
A key technical difference is that legacy iptables needs separate binaries for each family: iptables for IPv4, ip6tables for IPv6, arptables and ebtables for ARP and bridging. nftables unifies them and replaces linear rule lists with sets and maps that scale far better when thousands of addresses must be matched. Running iptables-legacy and nftables rules at the same time on one host is a frequent source of puzzling behavior.
Building and persisting an iptables rule set
A sound host firewall follows a default-deny pattern: allow loopback traffic, allow established connections, open the specific services the host provides and drop the rest. The order matters, and the SSH rule must exist before the policy changes to DROP on a remote machine.
iptables -A INPUT -i lo -j ACCEPTallows loopback traffic.iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPTallows replies.iptables -A INPUT -p tcp --dport 22 -j ACCEPTkeeps SSH reachable.iptables -P INPUT DROPsets the default deny policy.
Rules created this way live only in kernel memory and vanish at reboot. iptables-save writes the current rule set to a file, and iptables-restore loads it atomically, which is also safer than applying many single commands on a busy system. Distributions persist rules with packages such as iptables-persistent or the iptables service unit. Inspecting rules with iptables -L -n -v --line-numbers shows packet and byte counters per rule, which quickly reveals whether a rule ever matches.
Common iptables mistakes
Many firewall incidents stem from a small set of recurring errors. The most dramatic is locking oneself out of a remote server, but subtler mistakes leave services exposed while the administrator believes they are protected.
| Mistake | Symptom | Fix |
|---|---|---|
| Setting DROP policy before allowing SSH | Remote lockout | Allow SSH first or schedule an automatic rollback |
| Filtering only IPv4 | Services open over IPv6 | Mirror the rules with ip6tables |
| Appending allow rules after a DROP rule | New rule never matches | Insert with -I at the right position |
| Docker or Kubernetes rules ignored | Published ports bypass INPUT | Filter in the DOCKER-USER chain |
| Mixing legacy and nft backends | Rules appear to vanish | Use one backend consistently |
The simple explanation
Think of iptables as a list of instructions for a building’s security guard. Every visitor, which in networking is a data packet, is checked against the list from the top. The first instruction that fits decides what happens: let the visitor in, turn them away quietly, or send them to a different door.
If nothing on the list fits, the guard follows a default rule, such as refusing everyone not expected. The power and the danger of iptables both come from the order of that list, because one careless line near the top can let in or shut out far more than intended.
How it is used in practice
A small office runs a Linux router with one public IP address and an internal web server at 192.168.10.20. The administrator adds a MASQUERADE rule in the nat table’s POSTROUTING chain so that all office computers can reach the internet through the single public address.
To publish the internal web server, a DNAT rule in PREROUTING forwards incoming TCP port 443 to 192.168.10.20, and a matching FORWARD rule allows that traffic while the FORWARD policy stays DROP. After testing, iptables-save stores the rule set, and the router loads it at boot. The outcome is shared internet access and one exposed service, with everything else blocked by default.