11.2 Writing iptables Rules and NAT

Key Takeaways

  • Rules are managed with -A (append), -I (insert), -D (delete), and matched with options like -p, --dport, -s, -d, and -i.
  • DROP silently discards a packet; REJECT discards it but returns an ICMP error (or TCP RST with --reject-with tcp-reset).
  • Stateful firewalls use `-m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT` to permit return traffic without opening ports inbound.
  • MASQUERADE is source NAT for dynamic/outbound interfaces; SNAT with --to-source is preferred on static addresses.
  • Rules are lost at reboot unless saved: iptables-save/iptables-restore plus the netfilter-persistent service (iptables-persistent package) make them survive.
Last updated: July 2026

11.2 Writing iptables Rules and NAT

Section 11.1 gave you the framework; now you write the rules. Every iptables command follows the same grammar: table, chain operation, match criteria, and a target (the -j jump action). Because the KLCP exam is closed-book, you should be able to read a rule and state exactly what it does without documentation.

Rule Management Syntax

Chain operations you must know cold:

  • iptables -A INPUT ...append a rule to the end of the chain
  • iptables -I INPUT 3 ...insert at position 3 (defaults to position 1, the top)
  • iptables -D INPUT 3delete rule number 3 (or repeat the full rule specification)
  • iptables -R INPUT 3 ...replace a rule in place
  • iptables -F INPUTflush (delete) all rules in the chain; the policy stays
  • iptables -L -v -n --line-numbers — list rules with counters, numeric output, and rule numbers
  • iptables -P INPUT DROP — set the chain policy

Match criteria narrow which packets a rule sees: -p tcp or -p udp selects the protocol, --dport 22 and --sport select ports, -s 10.0.0.0/8 and -d match source/destination addresses, and -i eth0 / -o eth0 match the incoming/outgoing interface. Negate any match by placing ! before the option, as in ! -s 192.168.1.0/24 — the old intrapositioned form -s ! 192.168.1.0/24 is rejected by modern iptables.

A Worked Host Firewall

Here is a minimal, correct inbound ruleset for a Kali box that should only accept SSH from one management subnet:

iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 22 -m conntrack --ctstate NEW -j ACCEPT
iptables -A INPUT -j LOG --log-prefix 'IPTABLES-DROP: '

Read it top to bottom: loopback is always allowed; return traffic for connections this host initiated is allowed by the stateful rule (so your outbound updates and tool traffic keep working despite the DROP policy); new SSH attempts from 192.168.1.0/24 are allowed; everything else falls off the end of the chain and hits the DROP policy — after being logged by the non-terminating LOG rule.

DROP vs REJECT

Both targets discard the packet. The difference is what the sender learns:

TargetSender seesTypical use
DROPNothing — connections hang until timeoutInternet-facing interfaces; slows port scans and reveals less
REJECTICMP port-unreachable (customizable with --reject-with tcp-reset for TCP)Internal networks where fast, clean failure helps diagnostics

The exam trap is assuming REJECT is 'more secure.' It isn't inherently — REJECT confirms a live host is there, while DROP makes the host nearly indistinguishable from a dead IP. A common compromise is REJECT on trusted internal interfaces and DROP facing outward.

Stateful Matching with conntrack

The conntrack module tracks connection state in the kernel. Its key states: NEW (first packet of a flow), ESTABLISHED (part of a flow already seen in both directions), RELATED (a new flow tied to an existing one — classic example: FTP data connections), and INVALID (unidentifiable packets, usually dropped). The single most important firewall line on any Linux host is:

iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

Without it, a default-DROP INPUT policy would break your own outbound connections, because the replies would be dropped on the way back in. Note the older syntax -m state --state ... still appears in old documentation; conntrack is the modern form.

NAT: MASQUERADE vs SNAT

Network Address Translation lives in the nat table. For source NAT — sharing one public address with an internal network, such as routing a victim VM lab through your Kali box — you rewrite the source address in POSTROUTING:

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Two prerequisites people forget: IP forwarding must be enabled (net.ipv4.ip_forward=1, made permanent in /etc/sysctl.conf), and the FORWARD chain must permit the traffic.

  • MASQUERADE rewrites the source to whatever address the outbound interface currently has. It is designed for dynamic addresses (DHCP, dial-up): if the link drops, related conntrack entries are discarded so stale NAT state doesn't linger. That per-packet address lookup costs a little overhead.
  • SNAT with --to-source 203.0.113.10 rewrites the source to a fixed address. Use it when the interface has a static IP — it is slightly cheaper and the only correct choice for a stable mapping. iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 203.0.113.10.

Remember the direction: SNAT/MASQUERADE happen in POSTROUTING; destination NAT (DNAT, port forwarding) happens in PREROUTING.

Saving and Restoring Rules

iptables rules live only in kernel memory — reboot and they're gone. The persistence toolchain:

  1. iptables-save > /etc/iptables/rules.v4 — dump the live ruleset in restore format.
  2. iptables-restore < /etc/iptables/rules.v4 — load it back atomically.
  3. Install the iptables-persistent package — the iptables/ip6tables plugin for the separate netfilter-persistent package, which it pulls in as a dependency. The netfilter-persistent service loads rules.v4 (and rules.v6) at boot. After changing rules, run netfilter-persistent save to update the files.

Kali Linux Revealed teaches a fourth, ifupdown-based variant you should recognize on the exam: put your iptables calls in a script (the book's example is /usr/local/etc/arrakis.fw) and register it with an up /usr/local/etc/arrakis.fw directive inside the interface stanza of /etc/network/interfaces, so the rules are installed every time that interface comes up. A box running NetworkManager or systemd-networkd instead of ifupdown uses their dispatcher hooks rather than interfaces.

Always test a new ruleset before saving it — a mistaken -A INPUT -j DROP at the top of the chain, persisted across reboots, is a self-inflicted lockout on a remote box.

One more operational note: iptables-restore applies a file atomically, replacing the current ruleset, which makes it far safer than pasting individual iptables commands into a remote shell. If you are tuning firewall rules over SSH, load the candidate ruleset with a timed fallback (for example, schedule iptables-restore of the previous rules via at a few minutes out, then cancel the job once you confirm you still have connectivity). The exam won't test the at trick, but it will test that you know rules are memory-resident until explicitly saved, and that flushing rules with iptables -F does not reset chain policies — a flushed chain with a DROP policy still drops everything.

Test Your Knowledge

Which iptables rule allows response traffic for connections that your Kali machine initiated, while keeping a default DROP policy on INPUT?

A
B
C
D
Test Your Knowledge

Your Kali box shares its DHCP-assigned uplink with an internal lab network. Which NAT configuration is most appropriate?

A
B
C
D