interview-prep

Crisp answer: iptables/nftables are the Linux kernel's packet filtering framework. Rules define what happens to packets: accept, drop, modify, or redirect. Kubernetes uses them heavily for Service routing and network policy enforcement.

The netfilter framework:

Both iptables and nftables are front-ends to netfilter — the kernel's packet processing hooks. nftables is the modern replacement for iptables (faster, cleaner syntax, single tool).

iptables basics:

Packets traverse chains of rules organised in tables:

Table Purpose
filter Accept or drop packets (default table)
nat Rewrite source/destination addresses (NAT, port forwarding)
mangle Modify packet headers (TTL, ToS, marks)
raw Pre-connection tracking, bypass conntrack

Within each table, packets move through chains:

Chain When it fires
PREROUTING Before routing decision (nat, mangle, raw)
INPUT Incoming packets for local delivery (filter, mangle)
FORWARD Packets being forwarded (not destined for this host)
OUTPUT Locally generated outgoing packets
POSTROUTING After routing decision, before leaving the host

Common iptables commands:

# List rules
iptables -L                      # filter table, all chains
iptables -L -v -n                # Verbose, numeric (no DNS), with packet counts
iptables -t nat -L -n -v         # NAT table
iptables -L INPUT --line-numbers # Show rule numbers (for deletion)
iptables-save                    # Dump all rules in restorable format

# Allow/deny rules
iptables -A INPUT -p tcp --dport 443 -j ACCEPT   # Allow HTTPS in
iptables -A INPUT -p tcp --dport 22 -s 10.0.0.0/8 -j ACCEPT  # SSH from internal only
iptables -A INPUT -j DROP                         # Default deny (append last)

# Insert (before existing rules)
iptables -I INPUT 1 -p tcp --dport 80 -j ACCEPT  # Insert at position 1

# Delete rules
iptables -D INPUT 3              # Delete rule number 3
iptables -F                      # Flush (delete all) rules in filter table
iptables -F -t nat               # Flush NAT table

# NAT examples
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE  # Source NAT for internet sharing
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 10.0.0.5:8080  # Port forward

# Persist rules (varies by distro)
iptables-save > /etc/iptables/rules.v4
iptables-restore < /etc/iptables/rules.v4

How Kubernetes uses iptables:

kube-proxy (the default mode) uses iptables to implement Kubernetes Services. Every Service gets a ClusterIP, and iptables rules on every node do DNAT to redirect traffic to a random healthy pod endpoint.

# See Kubernetes NAT rules
iptables -t nat -L KUBE-SERVICES -n -v
# Chain KUBE-SERVICES
# target           prot  source  destination
# KUBE-SVC-XXXXX   tcp   all     10.96.0.1/32  tcp dpt:443  /* kubernetes ClusterIP */

iptables -t nat -L KUBE-SVC-XXXXX -n -v
# KUBE-SEP-AAA  all  random 33%   /* endpoint 1 */
# KUBE-SEP-BBB  all  random 50%   /* endpoint 2 */
# KUBE-SEP-CCC  all             /* endpoint 3 */

The statistic module distributes traffic across endpoints probabilistically. kube-proxy watches the API server and rewrites these rules whenever endpoints change.

Cilium uses eBPF instead of iptables:

Cilium (which you run in your homelab) replaces kube-proxy entirely using eBPF programs loaded into the kernel. This is faster (avoids iptables chain traversal), supports network policy at L7, and provides better observability. Hubble is Cilium's observability layer.

nftables — the modern replacement:

# nftables equivalent of common iptables operations
nft list ruleset                 # Show all rules
nft list table ip filter         # Specific table

# Create a basic ruleset
nft add table ip filter
nft add chain ip filter INPUT { type filter hook input priority 0 \; policy drop \; }
nft add rule ip filter INPUT tcp dport 443 accept
nft add rule ip filter INPUT tcp dport 22 ip saddr 10.0.0.0/8 accept

# nftables has native sets (much faster than iptables -m set)
nft add set ip filter allowed_ips { type ipv4_addr \; }
nft add element ip filter allowed_ips { 10.0.0.1, 10.0.0.2 }
nft add rule ip filter INPUT ip saddr @allowed_ips accept

Key difference: nftables uses a single binary (nft) for all table types (filter, nat, mangle) vs iptables needing separate tools. nftables is also faster for large rulesets.

Debugging connectivity with iptables:

# Is a rule dropping your traffic?
iptables -L -v -n               # Check packet counts — which rules are matching?

# Log dropped packets
iptables -A INPUT -j LOG --log-prefix "DROPPED: " --log-level 4
# Then check: dmesg | grep DROPPED or journalctl -k | grep DROPPED

# Trace a packet through all chains (careful — very verbose)
iptables -t raw -A PREROUTING -p tcp --dport 8080 -j TRACE
modprobe xt_LOG
xtables-monitor --trace

What to say in the interview:

"iptables organises rules into tables and chains. The filter table handles accept/drop; the nat table handles address translation. In Kubernetes, kube-proxy uses the nat table heavily — every Service ClusterIP is implemented as DNAT rules that redirect to pod endpoints, selected probabilistically using the statistics module. When debugging connectivity issues in Kubernetes, I check the KUBE-SERVICES chain to see if the Service exists in iptables, and the KUBE-SEP chains to see the endpoint rules. Cilium replaces all of this with eBPF, which is what my homelab runs — same semantics but faster and with L7 visibility."


My notes