Home Blog Certs Knowledge Base About

iptables / nftables

Linux firewall reference: iptables (chains, tables, stateful filtering, NAT, logging, persistence) and nftables (modern syntax). Covers LPIC-2 topic 212.1.

iptables โ€” structure

Tables & chains
TableChainsPurpose
filterINPUT ยท OUTPUT ยท FORWARDDefault table โ€” allow/drop/reject
natPREROUTING ยท OUTPUT ยท POSTROUTINGAddress translation
mangleAll fivePacket modification (TTL, TOS, marks)
rawPREROUTING ยท OUTPUTConntrack bypass
Chain flow
TrafficPath
Incoming to hostPREROUTING โ†’ INPUT โ†’ local process
Outgoing from hostlocal process โ†’ OUTPUT โ†’ POSTROUTING
Forwarded (router)PREROUTING โ†’ FORWARD โ†’ POSTROUTING

Listing & reset

Viewing rules
CommandDescription
iptables -L -n -v --line-numbersAll filter rules with counters and line numbers
iptables -L INPUT -n -v --line-numbersINPUT chain only
iptables -t nat -L -n -vNAT table
iptables -t mangle -L -n -vMangle table
Reset to clean state
CommandDescription
iptables -FFlush all filter rules
iptables -F INPUTFlush INPUT chain only
iptables -XDelete user-defined chains
iptables -ZZero counters
iptables -Z INPUTZero INPUT counters only
iptables -t nat -FFlush NAT table
iptables -t mangle -FFlush mangle table
iptables -P INPUT ACCEPTReset default INPUT policy

Policies & rule management

Adding, inserting, deleting rules
CommandDescription
iptables -P INPUT DROPSet default policy to DROP
iptables -A INPUT -p tcp --dport 22 -j ACCEPTAppend rule to end of chain
iptables -I INPUT 1 -s 10.0.0.0/8 -j ACCEPTInsert rule at position 1
iptables -D INPUT 3Delete rule by line number
iptables -D INPUT -p tcp --dport 80 -j ACCEPTDelete rule by specification
iptables -R INPUT 2 -p tcp --dport 443 -j ACCEPTReplace rule at position 2

Common filter rules

Essential INPUT rules
CommandDescription
iptables -A INPUT -i lo -j ACCEPTAllow loopback (always required)
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPTAllow established/related traffic
iptables -A INPUT -m conntrack --ctstate INVALID -j DROPDrop invalid packets
iptables -A INPUT -p tcp --dport 22 -j ACCEPTAllow SSH
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPTAllow HTTP/HTTPS (multiport)
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPTAllow ping
iptables -A INPUT -j DROPDrop everything else
Source/destination filtering
CommandDescription
iptables -A INPUT -s 192.168.1.0/24 -j ACCEPTAllow from subnet
iptables -A INPUT -s 10.0.0.55 -j DROPBlock a specific IP
iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPTSSH on specific interface only
iptables -A INPUT -m iprange --src-range 10.0.0.10-10.0.0.11 -j ACCEPTAllow IP range
iptables -A INPUT -m mac --mac-source aa:bb:cc:dd:ee:ff -j DROPBlock by MAC (L2 only)
iptables -A OUTPUT -m owner --uid-owner nobody -j DROPDrop traffic from user (OUTPUT only)

Stateful filtering (conntrack)

Connection states
StateMeaning
NEWFirst packet of a new connection
ESTABLISHEDConnection is established, packets flowing both ways
RELATEDRelated to an existing connection (FTP data, ICMP error)
INVALIDDoes not match any known connection, should be dropped
conntrack commands
CommandDescription
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPTCore stateful rule
iptables -A INPUT -m conntrack --ctstate INVALID -j DROPDrop invalid
iptables -A INPUT -p tcp --dport 22 --syn -m conntrack --ctstate NEW -j ACCEPTNew SSH connections only
conntrack -LShow connection tracking table
conntrack -SConntrack statistics

NAT

SNAT & MASQUERADE
CommandDescription
iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o eth0 -j MASQUERADEMASQUERADE โ€” dynamic source IP (DHCP, PPPoE)
iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o eth0 -j SNAT --to-source 203.0.113.10SNAT โ€” fixed source IP (faster than MASQUERADE)
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forwardEnable IP forwarding (required for NAT router)
net.ipv4.ip_forward = 1Persist in /etc/sysctl.conf, apply with sysctl -p
DNAT & port forwarding
CommandDescription
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8080 -j DNAT --to-destination 10.0.0.50:80Forward port 8080 โ†’ internal host:80
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 10000:10010 -j DNAT --to-destination 10.0.0.50Forward port range (mapped 1:1)
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080Redirect to local port (PREROUTING/OUTPUT only)
iptables -A FORWARD -i eth0 -o eth1 -p tcp --dport 80 -d 10.0.0.50 -m conntrack --ctstate NEW -j ACCEPTFORWARD rule required alongside DNAT
conntrack -L -jShow active NAT translations

Logging & custom chains

Logging
CommandDescription
iptables -A INPUT -j LOG --log-prefix "[DROP] " --log-level 4Log (does NOT stop processing โ€” packet continues)
iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "[INPUT-DROP] "Log with rate limit (last rule before default policy)
journalctl -k | grep DROPRead kernel log (iptables LOG target)
Custom chains
CommandDescription
iptables -N LOGDROPCreate custom chain
iptables -A LOGDROP -j LOG --log-prefix "[DROP] "Add LOG to custom chain
iptables -A LOGDROP -j DROPAdd DROP to custom chain
iptables -A INPUT -s 10.0.0.55 -j LOGDROPSend traffic to custom chain
iptables -A chain -j RETURNReturn to parent chain (continue processing there)

Rate limiting

limit & recent modules
CommandDescription
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 5/second --limit-burst 10 -j ACCEPTLimit ping to 5/s (burst 10)
iptables -A INPUT -p tcp --dport 22 --syn -m conntrack --ctstate NEW -m limit --limit 1/second --limit-burst 5 -j ACCEPTSSH brute-force protection
iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW -m recent --set --name HTTPTrack new HTTP connections per IP
iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW -m recent --update --seconds 1 --hitcount 20 --name HTTP -j DROPDrop if >20 new connections/s from same IP

FORWARD & routing

Routing / forwarding rules
CommandDescription
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPTAllow established forwarded traffic
iptables -A FORWARD -s 192.168.10.0/24 -i eth1 -o eth0 -m conntrack --ctstate NEW -j ACCEPTAllow internal LAN to initiate connections outward
iptables -I FORWARD 1 -s 192.168.10.50 -j DROPBlock a single internal host from forwarding

Persistence

Save & restore
CommandDescription
iptables-save > /etc/iptables/rules.v4Save rules to file
iptables-restore < /etc/iptables/rules.v4Restore rules atomically
sudo apt install iptables-persistentAuto-load rules on boot
sudo netfilter-persistent saveSave current rules via persistent service
sudo netfilter-persistent reloadReload rules from /etc/iptables/

Minimal server template

# Safe order: allow SSH first, then set DROP policy
iptables -F; iptables -X
iptables -A INPUT -p tcp --dport 22 -j ACCEPT   # SSH before DROP policy
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 5/s -j ACCEPT
iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "[DROP] "

netfilter-persistent save

nftables

Key differences from iptables
Featureiptablesnftables
CLIiptables / ip6tables / arptablesnft (single tool)
Atomic updateNo (rule-by-rule)Yes (transactions)
Setsipset (external)Built-in named sets
TablesBuilt-in (filter/nat/โ€ฆ)User-defined
nft syntax
CommandDescription
nft list rulesetShow all tables, chains, rules
nft add table inet filterCreate table (inet = IPv4+IPv6)
nft add chain inet filter input '{ type filter hook input priority 0; policy drop; }'Create input chain with DROP policy
nft add rule inet filter input ct state established,related acceptAllow established
nft add rule inet filter input tcp dport { 22, 80, 443 } acceptAllow ports (set literal)
nft add rule inet filter input iif lo acceptAllow loopback
nft delete rule inet filter input handle 5Delete rule by handle number
nft -f /etc/nftables.confLoad ruleset from file
nft list ruleset > /etc/nftables.confSave ruleset to file
iptables โ†’ nftables equivalents
iptablesnftables equivalent
-p tcp --dport 22 -j ACCEPTtcp dport 22 accept
-s 192.168.1.0/24 -j DROPip saddr 192.168.1.0/24 drop
-m conntrack --ctstate ESTABLISHED -j ACCEPTct state established accept
-t nat -A POSTROUTING -j MASQUERADEip saddr ... masquerade (in postrouting chain)
-m multiport --dports 80,443tcp dport { 80, 443 }
-m limit --limit 5/s -j ACCEPTlimit rate 5/second accept
-j LOG --log-prefix "DROP: "log prefix "DROP: "