Configure iptables with connection tracking modules to implement stateful packet filtering, advanced NAT rules, and comprehensive network security monitoring. Build robust firewall rules that track connection states and provide granular control over network traffic.
Prerequisites
- Root or sudo access
- Basic understanding of networking concepts
- Familiarity with Linux command line
- Network interface configuration knowledge
What this solves
Iptables connection tracking (conntrack) enables stateful packet filtering by tracking the state of network connections and allowing you to create firewall rules based on connection states like NEW, ESTABLISHED, and RELATED. This provides superior security compared to stateless filtering by automatically allowing return traffic for established connections while blocking unwanted incoming connections. You'll implement advanced connection tracking with NAT, port forwarding, and comprehensive logging to monitor and troubleshoot network traffic in production environments.
Step-by-step configuration
Install iptables and connection tracking modules
Install iptables and ensure connection tracking modules are loaded for stateful packet filtering.
sudo apt update
sudo apt install -y iptables iptables-persistent netfilter-persistent
Load connection tracking modules
Load the necessary kernel modules for connection tracking and NAT functionality.
sudo modprobe nf_conntrack
sudo modprobe nf_conntrack_ftp
sudo modprobe nf_conntrack_irc
sudo modprobe nf_nat
sudo modprobe nf_nat_ftp
Configure automatic module loading
Ensure connection tracking modules load automatically on system boot.
nf_conntrack
nf_conntrack_ftp
nf_conntrack_irc
nf_nat
nf_nat_ftp
nf_nat_irc
Create basic stateful firewall rules
Implement fundamental stateful packet filtering rules that track connection states and allow established connections.
# Clear existing rules
sudo iptables -F
sudo iptables -X
sudo iptables -t nat -F
sudo iptables -t nat -X
Set default policies
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT
Allow loopback traffic
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A OUTPUT -o lo -j ACCEPT
Allow established and related connections
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Configure service-specific stateful rules
Create stateful rules for common services using connection tracking states.
# SSH with connection tracking
sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
HTTP/HTTPS with connection tracking
sudo iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
DNS with connection tracking
sudo iptables -A INPUT -p udp --dport 53 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 53 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
Implement advanced connection tracking with rate limiting
Add rate limiting and connection tracking to prevent abuse and maintain performance.
# Rate limit new SSH connections
sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --set
sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --update --seconds 60 --hitcount 4 -j DROP
Limit concurrent connections per IP
sudo iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW -m connlimit --connlimit-above 20 -j REJECT
Block invalid connection states
sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
sudo iptables -A FORWARD -m conntrack --ctstate INVALID -j DROP
Configure NAT with connection tracking
Set up Network Address Translation with stateful connection tracking for advanced routing scenarios.
# Enable IP forwarding
echo 'net.ipv4.ip_forward=1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
MASQUERADE for outbound connections (replace eth0 with your interface)
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
Allow forwarding for established and related connections
sudo iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Allow forwarding from internal network (adjust 192.168.1.0/24 to your network)
sudo iptables -A FORWARD -s 192.168.1.0/24 -j ACCEPT
Implement port forwarding with connection tracking
Configure port forwarding rules that leverage connection tracking for secure traffic redirection.
# Port forward example: external port 8080 to internal server 192.168.1.100:80
sudo iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.100:80
Allow forwarding for the port forward rule
sudo iptables -A FORWARD -p tcp -d 192.168.1.100 --dport 80 -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
Port forward for SSH to internal server
sudo iptables -t nat -A PREROUTING -p tcp --dport 2222 -j DNAT --to-destination 192.168.1.101:22
sudo iptables -A FORWARD -p tcp -d 192.168.1.101 --dport 22 -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
Configure connection tracking parameters
Optimize connection tracking performance and memory usage for production environments.
# Connection tracking table size
net.netfilter.nf_conntrack_max = 262144
Connection tracking timeouts
net.netfilter.nf_conntrack_tcp_timeout_established = 7440
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.netfilter.nf_conntrack_udp_timeout = 30
net.netfilter.nf_conntrack_udp_timeout_stream = 120
Connection tracking buckets
net.netfilter.nf_conntrack_buckets = 65536
sudo sysctl -p /etc/sysctl.d/99-conntrack.conf
Enable comprehensive logging and monitoring
Configure detailed logging for connection tracking events and security monitoring.
# Log dropped packets with connection state information
sudo iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables-INPUT-denied: " --log-level 4
sudo iptables -A FORWARD -m limit --limit 5/min -j LOG --log-prefix "iptables-FORWARD-denied: " --log-level 4
Log invalid connection states
sudo iptables -I INPUT -m conntrack --ctstate INVALID -m limit --limit 2/min -j LOG --log-prefix "iptables-INVALID: "
Log new connections to sensitive services
sudo iptables -I INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j LOG --log-prefix "SSH-NEW-CONNECTION: "
Configure log rotation for iptables
Set up log rotation to manage iptables log file sizes and prevent disk space issues.
# Separate iptables logs
kern.warning /var/log/iptables.log
& stop
/var/log/iptables.log {
daily
missingok
rotate 30
compress
notifempty
create 0640 root root
postrotate
/usr/lib/rsyslog/rsyslog-rotate
endscript
}
sudo systemctl restart rsyslog
Create iptables management script
Build a script to manage iptables rules with connection tracking for easy administration.
#!/bin/bash
Iptables stateful firewall script
Clear existing rules
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
Set default policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
Allow loopback
iptables -A INPUT -i lo -j ACCEPT
Connection tracking rules
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
Service rules with connection tracking
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
Rate limiting
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --set
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --update --seconds 60 --hitcount 4 -j DROP
NAT rules
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -A FORWARD -s 192.168.1.0/24 -j ACCEPT
Logging
iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables-denied: "
echo "Iptables rules applied successfully"
sudo chmod 755 /etc/iptables/rules.sh
sudo /etc/iptables/rules.sh
Save and restore iptables rules
Configure automatic saving and restoration of iptables rules with connection tracking on system reboot.
sudo netfilter-persistent save
sudo systemctl enable netfilter-persistent
Monitor and troubleshoot connection tracking
Monitor connection tracking table
Use conntrack tools to monitor active connections and troubleshoot connection tracking issues.
sudo apt install -y conntrack-tools
# View all tracked connections
sudo conntrack -L
View connection statistics
sudo conntrack -S
Monitor real-time connections
sudo conntrack -E
View specific protocol connections
sudo conntrack -L -p tcp
sudo conntrack -L -p udp
Analyze connection tracking performance
Monitor connection tracking performance metrics and identify potential bottlenecks.
# Check connection tracking table usage
cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max
Monitor connection tracking memory usage
cat /proc/net/nf_conntrack | wc -l
Check for dropped packets due to full table
dmesg | grep "nf_conntrack: table full"
View detailed conntrack statistics
cat /proc/net/stat/nf_conntrack
Set up connection tracking monitoring script
Create an automated monitoring script to track connection table health and performance.
#!/bin/bash
Connection tracking monitoring script
CURRENT=$(cat /proc/sys/net/netfilter/nf_conntrack_count)
MAXIMUM=$(cat /proc/sys/net/netfilter/nf_conntrack_max)
PERCENT=$((CURRENT * 100 / MAXIMUM))
echo "$(date): Conntrack usage: $CURRENT/$MAXIMUM ($PERCENT%)"
Alert if usage is above 80%
if [ $PERCENT -gt 80 ]; then
echo "WARNING: Connection tracking table usage above 80%"
logger "conntrack-monitor: High connection tracking usage: $PERCENT%"
fi
Show top connection types
echo "Top connection types:"
cat /proc/net/nf_conntrack | cut -d' ' -f1 | sort | uniq -c | sort -nr | head -5
sudo chmod +x /usr/local/bin/conntrack-monitor.sh
Configure automated monitoring with cron
Schedule regular connection tracking monitoring to detect issues proactively.
sudo crontab -e
Add this line to run monitoring every 5 minutes:
/5 * /usr/local/bin/conntrack-monitor.sh >> /var/log/conntrack-monitor.log
Verify your setup
# Check iptables rules are active
sudo iptables -L -n -v
sudo iptables -t nat -L -n -v
Verify connection tracking modules
lsmod | grep nf_conntrack
Test connection tracking functionality
sudo conntrack -L | head -10
Check connection tracking statistics
sudo conntrack -S
Verify logging is working
sudo tail -f /var/log/iptables.log
Test service connectivity
ss -tuln | grep -E ':22|:80|:443'
Check connection tracking table usage
echo "Conntrack usage: $(cat /proc/sys/net/netfilter/nf_conntrack_count)/$(cat /proc/sys/net/netfilter/nf_conntrack_max)"
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Connection tracking table full errors | nf_conntrack_max too low | Increase net.netfilter.nf_conntrack_max in sysctl.conf |
| High memory usage | Too many tracked connections | Reduce connection timeouts and increase cleanup frequency |
| Services unreachable after iptables rules | Missing ESTABLISHED,RELATED rule | Add -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT |
| NAT not working | IP forwarding disabled | Enable with echo 1 > /proc/sys/net/ipv4/ip_forward |
| Rules lost after reboot | Rules not saved persistently | Use netfilter-persistent save or iptables-save |
| Port forwarding fails | Missing FORWARD chain rules | Add corresponding FORWARD rules for DNAT targets |
| FTP connections drop | Missing FTP conntrack module | Load nf_conntrack_ftp and nf_nat_ftp modules |
Next steps
- Configure advanced iptables rules for bridge network security and container isolation
- Set up intrusion detection with OSSEC HIDS and nftables integration for automated threat response
- Configure iptables with fail2ban integration for automated threat blocking
- Implement iptables geo-blocking and geographic security rules
- Set up iptables high availability clustering with keepalived
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Global variables
INTERFACE=""
# Usage function
usage() {
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " -i, --interface INTERFACE Network interface for NAT (default: auto-detect)"
echo " -h, --help Show this help message"
exit 1
}
# Print colored output
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Cleanup function for rollback
cleanup() {
print_error "Installation failed. Cleaning up..."
# Restore basic iptables rules to prevent lockout
iptables -P INPUT ACCEPT 2>/dev/null || true
iptables -P FORWARD ACCEPT 2>/dev/null || true
iptables -P OUTPUT ACCEPT 2>/dev/null || true
iptables -F 2>/dev/null || true
iptables -X 2>/dev/null || true
exit 1
}
# Set trap for cleanup on error
trap cleanup ERR
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
-i|--interface)
INTERFACE="$2"
shift 2
;;
-h|--help)
usage
;;
*)
echo "Unknown option: $1"
usage
;;
esac
done
# Check if running as root
if [[ $EUID -ne 0 ]]; then
print_error "This script must be run as root"
exit 1
fi
# Auto-detect distribution
print_status "[1/8] Detecting distribution..."
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_INSTALL="apt install -y"
PKG_UPDATE="apt update"
MODULES_FILE="/etc/modules-load.d/netfilter.conf"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
PKG_UPDATE="dnf check-update || true"
MODULES_FILE="/etc/modules-load.d/netfilter.conf"
;;
amzn)
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
PKG_UPDATE="yum check-update || true"
MODULES_FILE="/etc/modules-load.d/netfilter.conf"
;;
*)
print_error "Unsupported distribution: $ID"
exit 1
;;
esac
else
print_error "Cannot detect distribution (/etc/os-release not found)"
exit 1
fi
print_status "Detected distribution: $ID"
# Auto-detect network interface if not provided
if [[ -z "$INTERFACE" ]]; then
print_status "[2/8] Auto-detecting network interface..."
INTERFACE=$(ip route | grep default | head -1 | awk '{print $5}')
if [[ -z "$INTERFACE" ]]; then
print_error "Could not auto-detect network interface. Please specify with -i"
exit 1
fi
print_status "Using interface: $INTERFACE"
fi
# Update package manager
print_status "[3/8] Updating package manager..."
$PKG_UPDATE
# Install iptables and required packages
print_status "[4/8] Installing iptables and required packages..."
if [[ "$ID" == "ubuntu" || "$ID" == "debian" ]]; then
$PKG_INSTALL iptables iptables-persistent netfilter-persistent
elif [[ "$ID" == "almalinux" || "$ID" == "rocky" || "$ID" == "centos" || "$ID" == "rhel" || "$ID" == "ol" || "$ID" == "fedora" ]]; then
$PKG_INSTALL iptables-services iptables-utils
systemctl disable firewalld 2>/dev/null || true
systemctl stop firewalld 2>/dev/null || true
systemctl enable iptables
elif [[ "$ID" == "amzn" ]]; then
$PKG_INSTALL iptables-services
systemctl disable firewalld 2>/dev/null || true
systemctl stop firewalld 2>/dev/null || true
systemctl enable iptables
fi
# Load connection tracking modules
print_status "[5/8] Loading connection tracking modules..."
modprobe nf_conntrack
modprobe nf_conntrack_ftp
modprobe nf_conntrack_irc
modprobe nf_nat
modprobe nf_nat_ftp
# Configure automatic module loading
print_status "[6/8] Configuring automatic module loading..."
mkdir -p "$(dirname "$MODULES_FILE")"
cat > "$MODULES_FILE" << 'EOF'
nf_conntrack
nf_conntrack_ftp
nf_conntrack_irc
nf_nat
nf_nat_ftp
nf_nat_irc
EOF
# Configure stateful firewall rules
print_status "[7/8] Configuring stateful firewall rules..."
# Clear existing rules
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
# Set default policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Allow loopback traffic
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# Allow established and related connections
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Block invalid connection states
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
iptables -A FORWARD -m conntrack --ctstate INVALID -j DROP
# SSH with rate limiting
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --set
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --update --seconds 60 --hitcount 4 -j DROP
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
# HTTP/HTTPS with connection limiting
iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW -m connlimit --connlimit-above 20 -j REJECT
iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW -m connlimit --connlimit-above 20 -j REJECT
iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
# DNS with connection tracking
iptables -A INPUT -p udp --dport 53 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp --dport 53 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
# Enable IP forwarding
echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
sysctl -p
# Configure NAT with connection tracking
iptables -t nat -A POSTROUTING -o "$INTERFACE" -j MASQUERADE
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Add comprehensive logging for monitoring
iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables-INPUT: " --log-level 4
iptables -A FORWARD -m limit --limit 5/min -j LOG --log-prefix "iptables-FORWARD: " --log-level 4
# Save iptables rules
if [[ "$ID" == "ubuntu" || "$ID" == "debian" ]]; then
iptables-save > /etc/iptables/rules.v4
systemctl enable netfilter-persistent
elif [[ "$ID" == "almalinux" || "$ID" == "rocky" || "$ID" == "centos" || "$ID" == "rhel" || "$ID" == "ol" || "$ID" == "fedora" || "$ID" == "amzn" ]]; then
iptables-save > /etc/sysconfig/iptables
fi
# Verification checks
print_status "[8/8] Performing verification checks..."
# Check if modules are loaded
for module in nf_conntrack nf_nat; do
if lsmod | grep -q "$module"; then
print_status "Module $module loaded successfully"
else
print_error "Module $module failed to load"
exit 1
fi
done
# Check if iptables rules are applied
if iptables -L INPUT | grep -q "ESTABLISHED,RELATED"; then
print_status "Stateful firewall rules applied successfully"
else
print_error "Failed to apply stateful firewall rules"
exit 1
fi
# Check connection tracking
if [ -f /proc/net/nf_conntrack ]; then
print_status "Connection tracking is active"
else
print_warning "Connection tracking status unclear"
fi
print_status "Stateful iptables firewall configuration completed successfully!"
print_status "Connection tracking and stateful packet filtering are now active"
print_status "Default policy: DROP for INPUT and FORWARD, ACCEPT for OUTPUT"
print_status "Allowed services: SSH (rate limited), HTTP/HTTPS (connection limited), DNS"
print_status "NAT configured on interface: $INTERFACE"
print_warning "Please test your connection before disconnecting to ensure you're not locked out"
Review the script before running. Execute with: bash install.sh