A Go CLI tool for analyzing iptables/ip6tables firewall rules to find security issues, shadowed rules, Docker NAT bypasses, exposed services, and policy violations. Provides security scoring and actionable recommendations.
- Rule Analysis: Parses and displays iptables/ip6tables rules in readable tables
- Shadow Detection: Finds rules that are covered by earlier deterministic rules; stateful and probabilistic matches are kept out of definite shadow proofs
- Docker NAT Bypass Detection: Detects the critical issue where INPUT chain blocks are ineffective because Docker DNAT rules in the nat table redirect traffic through FORWARD, completely bypassing INPUT
- Dead Rule Detection: Identifies rules that come after a catch-all DROP and are unreachable, correctly handling conditional match extensions (e.g.
recent --updateis not a catch-all) - Service Cross-Reference: Matches firewall rules against actual listening services (
ssoutput) to find exposed ports, following user-defined chain jumps (e.g. SSHBRUTE, ICMPFLOOD chains) - Security Scoring: 100-point security score with A-F grades when every scored category was assessed, and an explicit
INCOMPLETEgrade otherwise:- Policy (default ACCEPT policies)
- Exposure (listening services open to the network)
- Shadows/Docker bypasses
- Hygiene (best practices like conntrack, rate limiting)
- IPv6 coverage
- Recommendations: Suggestions that identify the exact table, chain, and rule; ready-to-run replacements are emitted only when the original restrictions can be preserved
- Dual Stack: Full support for both IPv4 (iptables) and IPv6 (ip6tables)
- Flexible Input: Analyze live system (requires root) or saved iptables-save output files
- Multiple Output Formats: Colored CLI, JSON, score-only
- Rich TUI: Polished terminal UI built with lipgloss — 256-color palette, rounded borders, health bars, grade cards
This is sketchy, unsafe, don't do it at home, diry as Dirty Diana, omg what the fuck way of installing iptables-analyzer:
LATEST_VERSION=$(curl -s https://github.com/c0m4r/iptables-analyzer/releases | grep "releases/tag" | grep -o "<a href.*</a>" | head -n 1 | cut -f2 -d\> | cut -f1 -d\<)
if [[ ! "$(echo ${LATEST_VERSION} | sed 's/\.//g;')" =~ ^[0-9]+$ ]]; then echo "wrong version :(" ; fi
case "$(uname -m)" in
x86_64) ARCH="amd64" ;;
aarch64|arm64) ARCH="arm64" ;;
riscv64) ARCH="riscv64" ;;
esac
if [[ "$ARCH" && "$LATEST_VERSION" ]]; then wget -nv -O iptables-analyzer https://github.com/c0m4r/iptables-analyzer/releases/download/${LATEST_VERSION}/iptables-analyzer-${LATEST_VERSION}-${ARCH} ; else echo "<sad pepe the frog meme>" ; figit clone https://github.com/c0m4r/iptables-analyzer
cd iptables-analyzer
make build # or: go build -ldflags="-s -w" -o iptables-analyzer .The binary is self-contained with no runtime dependencies.
./addons/build.shsudo ./iptables-analyzerSave your firewall rules first:
sudo iptables-save > /tmp/rules.v4
sudo ip6tables-save > /tmp/rules.v6
./iptables-analyzer --file /tmp/rules.v4 --file6 /tmp/rules.v6File mode does not inspect services on the machine running the analyzer. To
cross-reference saved rules with listening sockets from the same host, capture
and provide ss output explicitly:
ss -tlnp > /tmp/services.txt
ss -ulnp >> /tmp/services.txt
./iptables-analyzer --file /tmp/rules.v4 --file6 /tmp/rules.v6 --services-file /tmp/services.txtWithout --services-file, the report marks service exposure and the overall
grade as INCOMPLETE. A missing or malformed explicitly requested services
file is a fatal input error. A valid header-only ss capture represents an
assessed host with no listeners.
# Security score only
./iptables-analyzer -f /tmp/rules.v4 --score-only
# JSON output for integration
./iptables-analyzer --file /tmp/rules.v4 --json
# Verbose: show all rules including empty chains
./iptables-analyzer --file /tmp/rules.v4 --verbose
# IPv4-only (skip IPv6 check)
./iptables-analyzer -4 --file /tmp/rules.v4
# IPv6-only
./iptables-analyzer -6 --file6 /tmp/rules.v6
# No colors (for logs/piping)
./iptables-analyzer --no-color./iptables-analyzer --helpShows a 0-100 score with letter grade (A-F) and breakdown of deductions when
all categories were assessed. The numeric subtotal remains visible with an
INCOMPLETE grade and an unassessed list when service evidence or a firewall
translation could not be evaluated:
- Policy: -15 INPUT ACCEPT, -10 FORWARD ACCEPT (maximum -25); OUTPUT ACCEPT is advisory
- Exposure: -5 per well-known TCP/UDP port, -2 per high TCP/UDP port exposed to the world (maximum -25); a port reachable over both IPv4 and IPv6 is counted once
- Shadows/Bypasses: -12 per critical Docker bypass, -5 per high-severity shadow (maximum -25)
- Hygiene: -5 no conntrack ESTABLISHED, -5 no final DROP, -2 dead rules
- IPv6: -10 when IPv6 is in scope but no IPv6 rules were loaded
Lists security issues grouped by severity:
- CRITICAL: Docker bypasses, input blocks that are ineffective
- HIGH: Exposed services on well-known ports, missing policies
- MEDIUM: Effectiveness issues, potential hygiene problems
- LOW: Best practice suggestions
- INFO: Unused rules or minor findings
Numbered list of prioritized improvements. Commands cite the actual table, chain, and rule. The analyzer provides descriptive guidance instead of a replacement command when it cannot prove that the replacement preserves the original access restrictions and established-session behavior.
# Set default policies to DROP
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
# Allow loopback
sudo iptables -A INPUT -i lo -j ACCEPT
# Allow established connections
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Allow SSH with rate limiting
sudo iptables -I INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m limit --limit 3/min --limit-burst 5 -j ACCEPT
# Allow HTTP/HTTPS
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# Allow ICMP
sudo iptables -A INPUT -p icmp -j ACCEPT# Match the original published port because DOCKER-USER sees post-DNAT packets
sudo iptables -I DOCKER-USER 1 -i eth0 -p tcp -s 10.0.0.0/8 -m conntrack --ctorigdstport 8080 -j ACCEPT
sudo iptables -I DOCKER-USER 2 -i eth0 -p tcp -m conntrack --ctorigdstport 8080 -j DROPsudo ./iptables-analyzer
# Will flag any DNAT rules with bypassed INPUT blocks- cmd/: CLI flag parsing and orchestration using cobra
- internal/models/: Data structures (Rule, Chain, Table, Ruleset, findings)
- internal/parser/: Hand-rolled iptables-save format parser with token walker
- internal/loader/: Load from files or live system (exec iptables-save/ip6tables-save)
- internal/analyzer/: Core analysis logic
evaluation.go: Order-aware packet-path evaluation with jump, goto, and RETURN traversalanalyzer.go: Service exposure detection and listening-service cross-referenceshadow.go: Detect shadowed rules using CIDR containment, port range logic, and match extension awarenessdocker.go: Docker NAT bypass detection by cross-referencing nat and filter tableseffectiveness.go: Policy checks, dead rules (with match extension awareness), conntrack optimization
- internal/services/: Parse
ss -tlnpoutput, cross-reference with rules - internal/scorer/: 100-point security score calculation with breakdown
- internal/recommender/: Generate actionable recommendations
- internal/ui/: Render output with lipgloss — 256-color palette, rounded borders, health bars, grade cards
Shadow Detection: For each rule in a chain, check if any earlier rule's match criteria is a superset:
- Protocol superset (all > specific)
- CIDR containment (larger network covers smaller)
- Port range containment
- Interface wildcard matching
- Conntrack state superset
- Match extension awareness (rate-limiting, ICMP types, recent module parameters)
Docker Bypass Detection:
- Walk
nat/PREROUTINGin order through jumps,goto, andRETURN, carrying parent predicates and remaining source ranges - Evaluate every port in each reachable DNAT range and preserve ports for address-only translations
- Retain original and translated tuples plus both connection state (
NEW) and NAT status (DNAT) - Evaluate the translated packet through
filter/FORWARD, including--ctorigdstportrestrictions - Report a bypass only for externally reachable forwarded traffic; expose unsupported translations as assessment diagnostics
Cross-Reference Services: Walk filter/INPUT rules in order, following user-defined jumps, goto, RETURN, and default policies. Source CIDRs are split symbolically so earlier terminal rules and partial allowlists are respected before comparing the result with listening services from ss.
make test # Run unit tests
make check # Run vet, fmt, testTest fixtures in testdata/:
basic.iptables-save: IPv4 baseline (100-point subtotal butINCOMPLETEwithout services; B with the bundled service inventory)docker.iptables-save: Docker with INPUT blocks on two DNAT ports (score: F, detects two bypasses)insecure.iptables-save: Default ACCEPT policies with shadowed rules (score: F)
# Development build
go build -o iptables-analyzer .
# Optimized build (stripped, minimal size)
make build # ~4.5MB stripped binary
# Cross-compile
GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o iptables-analyzer-amd64 .Only runtime dependencies:
- Go 1.26+
- iptables/ip6tables (for live analysis, requires root)
- ss utility (for service cross-referencing, usually in iproute2 package)
- Requires
iptables-save/ip6tables-saveformat. Native nftables rules, routing, policy routing, and host network configuration are outside the assessment scope - Exposure analysis covers
filter/INPUT, and published-port analysis coversnat/PREROUTINGplusfilter/FORWARD; it does not establish every other Netfilter hook or table effect - Advanced match extensions that are not modeled are preserved and handled conservatively: they cannot prove shadow/dead-rule findings, while possible exposure paths remain visible
- Stateful, probabilistic, and side-effecting matches such as
limit,statistic, andrecentdo not establish definite shadowing - Saved
sswildcard sockets rendered as*are assessed for both IPv4 and IPv6 because the saved text does not establish an IPv6-only socket option - Does not track iptables rule counters/statistics
This tool analyzes firewall rules but does not modify them. Always test recommendations in a non-production environment first. Be especially careful with production firewalls - incorrect changes could lock you out of your system.