2026
Linux iptables: How Packet Filtering Actually Works
A practical breakdown of iptables. Tables, chains, targets and the default policy that ties it all together.
Every Linux server you touch has a firewall built directly into the kernel. It has been there since the early 2000s. Most people interact with it indirectly through tools like ufw or cloud security groups without ever knowing what is underneath. That underlying system is called netfilter. The tool you use to configure it is iptables.
Understanding iptables properly changes how you think about network traffic on Linux. Once you see the mental model it is hard to unsee. Things that once felt like magic become straightforward steps through a chain of logic. Port forwarding, NAT, firewall rules all click into place.
What iptables actually does
Every packet that enters or leaves your machine passes through the netfilter system in the kernel. iptables is your interface for telling that system what to do with those packets.
Think of it as a bouncer checking IDs at the door. Each packet arrives with a source address, a destination address, a protocol and a port number. The bouncer checks the list and decides whether to let it through, redirect it somewhere else, or turn it away entirely.
The three tables
iptables organises its rules into tables. Each table has a specific purpose. You specify which table you are working with using the -t flag. If you omit it, you are working with filter by default.
The table you will use for almost everything. Decides whether to accept or drop packets. All your everyday firewall rules live here.
Handles Network Address Translation. Rewrites the source or destination address of a packet. Port forwarding lives in this table.
For specialized packet alteration like tweaking TTL values or marking packets for routing decisions. Rarely needed unless you are doing something non-standard.
Chains: where rules actually live
Within each table there are chains. A chain is an ordered list of rules. When a packet arrives it walks down the chain from top to bottom until it hits a rule that matches. The filter table has three built-in chains:
INPUT
Packets destined for the local machine itself. Anything arriving at a port your system is listening on passes through here.
OUTPUT
Packets originating from the local machine. Outbound traffic from your own processes goes through this chain.
FORWARD
Packets passing through the machine on their way somewhere else. This chain matters when your box is acting as a router.
Anatomy of a rule
Here is a basic rule that allows incoming SSH traffic:
iptables -A INPUT -p tcp --dport 22 -j ACCEPT-A INPUT-p tcp--dport 22-j ACCEPTTo drop traffic instead of accepting it, swap ACCEPT for DROP. The rest of the rule stays the same.
Jump targets
The -j flag specifies what happens when a rule matches. These are the four you will encounter most often:
Let the packet through. The most common target for rules you actually want to allow.
Silently discard the packet. The sender gets no response and has no way to tell whether the port is closed or just filtered.
Discard the packet but send an error back to the sender. More polite than DROP. Useful on internal networks.
Write a message to the kernel log without stopping the packet. Chain LOG before a DROP to get visibility into what is being blocked.
The default policy
Each chain has a policy that fires when no rule matches. You set it with -P:
iptables -P INPUT DROPiptables -P FORWARD DROPiptables -P OUTPUT ACCEPTSetting INPUT to DROP builds a whitelist firewall. Only traffic you explicitly allow gets through. Everything else is silently discarded. This is the right default for most servers.
Watch out for this
If you set a restrictive INPUT policy on a remote server before allowing established connections you will lock yourself out. Always add the established connection rule first:
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPTA minimal working ruleset
Here is a sensible starting point for a server that runs a web application. Apply these rules in order. Chains are evaluated top to bottom so the sequence matters.
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPTAllow established connections back in
iptables -A INPUT -p tcp --dport 22 -j ACCEPTAllow SSH
iptables -A INPUT -p tcp --dport 80 -j ACCEPTAllow HTTP
iptables -A INPUT -p tcp --dport 443 -j ACCEPTAllow HTTPS
iptables -A INPUT -i lo -j ACCEPTAllow loopback interface
iptables -P INPUT DROPDrop everything else by default
Viewing your rules
iptables -L -v -nList all rules with packet counts. -n skips DNS lookups so it is faster.
iptables -L INPUT -v -nList rules for a specific chain only.
iptables-savePrint the full ruleset as commands. Useful for reviewing or backing up.
iptables -L -v -n --line-numbersShow rules with line numbers. Needed when you want to delete a specific rule.
To delete a specific rule, first list with --line-numbers then run iptables -D INPUT 3 to remove line 3 from the INPUT chain. To flush all rules at once use iptables -F.
Making rules survive a reboot
This is the thing that catches most people the first time. iptables rules are not persistent by default. When the machine reboots the rules are gone.
Save your ruleset
iptables-save > /etc/iptables/rules.v4Dumps the current rules to a file you can restore from.
Restore from a file
iptables-restore < /etc/iptables/rules.v4Loads a saved ruleset back into the kernel.
On Debian-based systems the iptables-persistent package handles automatic restore on boot. On RHEL-based systems iptables-services does the same job. Either way you will need to explicitly save your rules after any change. They are not auto-saved.
A note on nftables
iptables has been around since the late 1990s. Its successor nftables is now the default on most modern distributions. On a fresh Debian 12 or Ubuntu 22.04 install you may find that the iptables command is actually a compatibility shim wrapping nftables underneath.
The mental model is identical. Tables, chains, rules and targets all carry over. The syntax changes but the concepts do not. Learning iptables first gives you a solid foundation that makes nftables straightforward to pick up when you get there.