๐ Custom Chains In-Depth โ
Why Use Custom Chains? โ
Imagine you manage a public-facing web server with traffic from around the world. If you cram all rules into the INPUT chain, dozens of rules lined up makes troubleshooting like finding a thread in a tangled mess.
Custom chains are like organizing your rules into folders โ SSH rules go in one chain, HTTP in another, database in yet another. Clear, maintainable, and reusable.
๐ก Tip: ๐ก Analogy: Built-in chains (INPUT/OUTPUT/FORWARD) are the operating system's "inbox/outbox," while custom chains are your own "sorted folders." Packets don't automatically enter custom chains; you must use -j to jump to them from built-in chains.
Creating and Using Custom Chains โ
# Create a custom chain called WEBSERVER
iptables -N WEBSERVER
# View โ it will appear at the end of -L output
iptables -L -n
Chain INPUT (policy DROP)
target prot opt source destination
...
Chain WEBSERVER (0 references)
target prot opt source destination
# Add rules to the custom chain
iptables -A WEBSERVER -p tcp --dport 80 -j ACCEPT
iptables -A WEBSERVER -p tcp --dport 443 -j ACCEPT
iptables -A WEBSERVER -p tcp --dport 8080 -j ACCEPT
# Jump from INPUT chain to the custom chain (note: -j not -A)
iptables -A INPUT -p tcp -m multiport --dports 80,443,8080 -j WEBSERVER
# View statistics โ which rules matched how many packets
iptables -L WEBSERVER -v -n
Chain WEBSERVER (1 references)
pkts bytes target prot opt in out source destination
15K 960K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
23K 1400K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080๐ก Tip: ๐ก See "1 references"? That means 1 rule references this chain. If references is 0, no rules jump to this chain โ it's like a folder that's never been opened.
Practice: Service-Based Firewall Organization โ
This is the recommended organization for production environments โ each service gets its own custom chain, and the main chain only handles routing:
#!/bin/bash
# ============================================
# Production server firewall โ organized by service
# ============================================
# Flush
iptables -F
iptables -X # Delete all custom chains
# Default policy
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Loopback + established connections
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# ---- Create service chains ----
iptables -N SVC_SSH
iptables -N SVC_HTTP
iptables -N SVC_MONITOR
# ---- SSH service ----
iptables -A SVC_SSH -p tcp --dport 22 -m state --state NEW -m recent \
--set --name SSH
iptables -A SVC_SSH -p tcp --dport 22 -m state --state NEW -m recent \
--update --seconds 60 --hitcount 5 --name SSH -j DROP
iptables -A SVC_SSH -p tcp --dport 22 -j ACCEPT
# ---- HTTP/HTTPS service ----
iptables -A SVC_HTTP -p tcp -m multiport --dports 80,443 -j ACCEPT
# ---- Monitoring service (Prometheus + Grafana) ----
iptables -A SVC_MONITOR -p tcp --dport 9090 -s 10.0.0.0/8 -j ACCEPT
iptables -A SVC_MONITOR -p tcp --dport 3000 -s 10.0.0.0/8 -j ACCEPT
# ---- Mount to INPUT chain ----
iptables -A INPUT -p tcp --dport 22 -j SVC_SSH
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j SVC_HTTP
iptables -A INPUT -p tcp -m multiport --dports 9090,3000 -j SVC_MONITOR
# ---- Log and drop the rest ----
iptables -A INPUT -j LOG --log-prefix "IPT-DROP: " --log-level 4
iptables -A INPUT -j DROP
echo "Firewall rules loaded successfully"
iptables -L -v -n | head -30โ ๏ธ Warning: โ ๏ธ Note:
iptables -Xdeletes all custom chains. If a chain is still referenced by other rules (references โ 0), -X will error out. You must clear the rules that reference it first.
Renaming and Flushing Custom Chains โ
# Flush a custom chain's rules (keeps the chain itself)
iptables -F WEBSERVER
# Rename a custom chain
iptables -E WEBSERVER WEB_RULES
# Now -j WEBSERVER needs to be changed to -j WEB_RULES
# Delete a single custom chain (must clear references first)
iptables -D INPUT -p tcp -m multiport --dports 80,443 -j WEBSERVER
iptables -X WEBSERVER