Skip to content

Firewall Rules Persistence (iptables)

Overview

hub2 uses iptables (netfilter) for critical firewall rules that control: - Network security - Blocking direct access to sensitive services - Docker networking - Port forwarding and service isolation - WireGuard tunnels - UniFi WG tunnel connectivity (wg-uk, wg-fr)

Critical Issue: iptables rules are stored in kernel memory only. They survive Docker restarts but are completely lost on system reboots unless explicitly persisted to disk.


Current Status (Feb 12, 2026)

DEPLOYED & ENABLED - iptables-persistent installed - Current rules saved to /etc/iptables/rules.v4 - netfilter-persistent.service enabled for auto-restore on boot - Service status: active (exited) - runs at boot and exits

Note: WG-Easy (wg-easy container with WG_EASY_MARK and WG_EASY_FORWARD chains) was decommissioned on Feb 12, 2026. UniFi WireGuard tunnels (wg-uk, wg-fr) remain active.


Rule Categories

1. RAW Chain - Localhost Security

These rules block external access to critical services on localhost (127.0.0.1).

-A PREROUTING -d 127.0.0.1/32 ! -i lo -p tcp -m tcp --dport 5432 -j DROP
-A PREROUTING -d 127.0.0.1/32 ! -i lo -p tcp -m tcp --dport 6379 -j DROP
-A PREROUTING -d 127.0.0.1/32 ! -i lo -p tcp -m tcp --dport 9115 -j DROP
Port Service Why Block
5432 PostgreSQL Direct DB access from external systems
6379 Redis In-memory cache (no auth)
9115 Blackbox Exporter Internal monitoring only
8091 Traefik Dashboard Admin panel access

Impact if lost: Services become directly accessible from outside hub2 → CRITICAL SECURITY BREACH

2. Docker Chain - Port Forwarding

These rules handle Docker's port mappings and container networking:

-A DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.19.0.2:80
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 443 -j DNAT --to-destination 172.19.0.2:443
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8883 -j DNAT --to-destination 172.19.0.2:8883

Note: Managed automatically by Docker. Do not edit manually.

3. UniFi WireGuard Tunnels

The following WireGuard interfaces are active (no iptables rules, but noted for reference): - wg-uk - Tunnel to UK homelab (10.44.x.x) - wg-fr - Tunnel to FR homelab (10.35.x.x)

These are managed by wg-quick@wg-*.service systemd units and do not require special iptables rules.


Managing Rules

View All Rules

# Show all rules with rule numbers
sudo iptables -L -n -v --line-numbers

# Show specific chain
sudo iptables -L RAW -n -v
sudo iptables -L DOCKER -n -v

# Show as commands that could be re-executed
sudo iptables-save

Add a New Rule

# Example: Block port 9200 from external access
sudo iptables -A PREROUTING -d 127.0.0.1/32 ! -i lo -p tcp --dport 9200 -j DROP

# Persist to disk
sudo iptables-save | sudo tee /etc/iptables/rules.v4 > /dev/null

Delete a Rule

# Find the rule
sudo iptables -L RAW -n -v --line-numbers

# Delete by number (e.g., delete rule 5)
sudo iptables -D RAW 5

# Persist changes
sudo iptables-save | sudo tee /etc/iptables/rules.v4 > /dev/null

Test Before Saving

# View current rules in save format
sudo iptables-save

# Restore from file (non-persistent)
sudo iptables-restore < /etc/iptables/rules.v4

# Then save if satisfied
sudo iptables-save | sudo tee /etc/iptables/rules.v4 > /dev/null

Auto-Restore on Boot

The netfilter-persistent service automatically restores rules at boot time:

# Check service status
sudo systemctl status netfilter-persistent

# Enable auto-restore (already done)
sudo systemctl enable netfilter-persistent

# Manually restore
sudo systemctl start netfilter-persistent

# View service file
cat /etc/systemd/system-preset/netfilter-persistent.preset

Backup and Recovery

Create a Backup

# Backup current rules
sudo cp /etc/iptables/rules.v4 /etc/iptables/rules.v4.backup-$(date +%s)

# List backups
ls -la /etc/iptables/rules.v4.backup-*

Restore from Backup

# Copy backup to active rules
sudo cp /etc/iptables/rules.v4.backup-1707836400 /etc/iptables/rules.v4

# Load into kernel
sudo netfilter-persistent start

# Verify
sudo iptables-save | head -20

Emergency Reset (Use with Caution!)

# Flush ALL rules (WARNING: This blocks everything)
sudo iptables -F
sudo iptables -X
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT

# Restore from backup
sudo iptables-restore < /etc/iptables/rules.v4

# Verify
sudo iptables -L -n -v

Troubleshooting

Rules Lost After Reboot

# Check if netfilter-persistent started
sudo systemctl status netfilter-persistent

# Check if rules file exists
cat /etc/iptables/rules.v4 | head -5

# Manually restore
sudo netfilter-persistent start

Port Still Accessible After Blocking

# Verify rule is in place
sudo iptables -L RAW -n | grep dport

# Test connectivity
sudo ncat -zv 127.0.0.1 5432

# Check if rule is in the right order (rules are processed top-to-bottom)
sudo iptables -L RAW -n -v --line-numbers

Service Won't Start After Rules Change

# Restore to working backup
sudo iptables-restore < /etc/iptables/rules.v4.backup-XXXX

# Load into kernel
sudo systemctl restart netfilter-persistent

# Try service again
docker compose restart charliehub-postgres


Last updated: 2026-02-12 | WG-Easy decommissioned Feb 12