From iptables to nftables, beginner edition.
Linux Networking
In this lesson you will learn how the Linux kernel inspects and filters network packets using the netfilter framework, how to write and read iptables rules, what conntrack is and why it matters, and how the newer nftables tool improves on the classic toolchain.
Think of the Linux kernel as a post office. Every packet is a letter passing through. Netfilter is the sorting machine that can inspect, redirect, or shred any letter. iptables and nftables are the tools you use to program that sorting machine — they just write the instructions, they don't run them.
iptables organises rules into tables (purpose) and chains (hook attachment points).
| Table | What it does | Typical chains | Example rule |
|---|---|---|---|
filter |
Accept, drop, or reject packets — the default firewall table | INPUT, FORWARD, OUTPUT | -A INPUT -p tcp --dport 22 -j ACCEPT |
nat |
Rewrite source or destination IP/port (SNAT, DNAT, MASQUERADE) | PREROUTING, OUTPUT, POSTROUTING | -t nat -A POSTROUTING -o eth0 -j MASQUERADE |
mangle |
Modify packet headers (TTL, TOS, mark for routing) without rewriting addresses | All 5 chains | -t mangle -A PREROUTING -j MARK --set-mark 1 |
raw |
Bypass conntrack for specific traffic (performance) | PREROUTING, OUTPUT | -t raw -A PREROUTING -p udp --dport 53 -j NOTRACK |
filter table is the default — when you omit -t, you are working in filter. Rules are evaluated top-to-bottom; first match wins.Three commands every sysadmin needs to know:
List all rules with packet/byte counters:
iptables -L -v -n
The -v flag shows interface and packet/byte counters. -n prevents slow DNS lookups — always use it.
Allow inbound SSH:
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
Appends (-A) a rule to the INPUT chain: TCP on port 22 → ACCEPT. The -A adds to the end; use -I to insert at a specific position.
Set default policy to drop all inbound:
iptables -P INPUT DROP
The policy is the fallback when no rule matches. Set this after adding ACCEPT rules for needed services, or you will lock yourself out.
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
iptables — the tool that writes rules into the kernel's netfilter tables-A INPUT — Append to the INPUT chain (packets destined for this machine)-p tcp — match only TCP packets--dport 22 — match destination port 22 (SSH)-m conntrack --ctstate NEW,ESTABLISHED — load the conntrack module and match packets in state NEW or ESTABLISHED-j ACCEPT — jump to target ACCEPT (let the packet through)Read it aloud: "For all TCP packets arriving at port 22 that are new or part of an established connection, accept them."
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
MASQUERADE is dynamic SNAT — it automatically uses the current IP of the outgoing interface. Ideal for dynamic IP addresses (home routers, VMs sharing a host NIC).
Packet is silently discarded. The sender gets no response and must wait for a timeout. Harder to fingerprint your firewall, but slower failure for legitimate clients.
iptables -A INPUT -p tcp --dport 23 -j DROP
Packet is discarded AND an ICMP "port unreachable" (or TCP RST) is sent back. Sender knows immediately the port is closed — faster failure, but reveals firewall presence.
iptables -A INPUT -p tcp --dport 23 -j REJECT \
--reject-with tcp-reset
nftables replaced iptables as the recommended Linux firewall tool starting with kernel 3.13 (2014), and became the default in Debian 10 / RHEL 8.
nft replaces four tools: iptables, ip6tables, arptables, ebtables. One syntax for IPv4, IPv6, ARP, and bridge filtering.ip saddr @blocked_ips drop. Performance scales sub-linearly.nft -f rules.nft. No window where partial rules leave the machine exposed.# List all tables and rules
nft list ruleset
# Load a complete ruleset from a file (atomic)
nft -f /etc/nftables.conf
| Task | iptables | nftables |
|---|---|---|
| Accept SSH (port 22) | iptables -A INPUT -p tcp --dport 22 -j ACCEPT |
tcp dport 22 accept |
| Drop all ICMP | iptables -A INPUT -p icmp -j DROP |
ip protocol icmp drop |
| NAT MASQUERADE | iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE |
ip saddr 10.0.0.0/8 oifname "eth0" masquerade |
| Match a set of IPs | Requires multiple -A rules or ipset module |
ip saddr { 192.168.1.0/24, 10.0.0.0/8 } accept |
| Reload entire ruleset atomically | Not natively supported; use iptables-restore | nft -f /etc/nftables.conf |
| IPv6 support | Separate ip6tables command |
Same ruleset; use inet table for dual-stack |
Both tools write rules into the same kernel netfilter subsystem — they can coexist but may conflict; pick one per production system.
iptables-translate — converts individual iptables rules to nftables syntax. Run iptables-translate -A INPUT -p tcp --dport 22 -j ACCEPT to get the equivalent nft line. Not 100% coverage, but a great starting point.policy accept/drop per chain. Moving from one to the other can silently change behaviour if chain policies differ.iptables -L -v -n or nft list ruleset before assuming a host is hardened.-m conntrack --ctstate ESTABLISHED work for DNS, QUIC, and other UDP protocols.iptables-save / iptables-restore or via netfilter-persistent. nftables rules are loaded from /etc/nftables.conf by systemd on boot if the service is enabled.-m conntrack --ctstate ESTABLISHED,RELATED) lets you write a single inbound ACCEPT rule instead of one per response port, and is the foundation of NAT.iptables-translate to convert existing rules and nft list ruleset to audit nftables configuration.In the lab you will: add, list, and delete iptables rules on a live VM; observe conntrack state transitions with conntrack -L; write an equivalent nftables ruleset; and test DROP vs REJECT behaviour with netcat.