Configure advanced iptables firewall rules with logging, port knocking, and DDoS protection

Advanced 45 min Apr 20, 2026 725 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Build a production-grade iptables firewall with connection tracking, rate limiting, and port knocking. Includes automated DDoS protection, detailed logging, and security hardening for enterprise environments.

Prerequisites

  • Root or sudo access
  • Basic understanding of networking concepts
  • SSH access to the server
  • Another machine for testing port knocking

What this solves

Advanced iptables configurations provide enterprise-grade network security with stateful packet filtering, automated threat detection, and intelligent access control. This tutorial builds a production firewall with connection tracking, rate limiting for DDoS protection, port knocking for secure SSH access, and comprehensive logging for security monitoring.

Step-by-step configuration

Install required packages

Install iptables-persistent to save rules and rsyslog for advanced logging capabilities.

sudo apt update
sudo apt install -y iptables iptables-persistent rsyslog netfilter-persistent
sudo dnf install -y iptables iptables-services rsyslog
sudo systemctl disable firewalld
sudo systemctl stop firewalld
sudo systemctl enable iptables
sudo systemctl start iptables

Create backup of existing rules

Always backup current iptables configuration before making changes.

sudo iptables-save > /root/iptables-backup-$(date +%Y%m%d-%H%M%S).rules
sudo cp /etc/iptables/rules.v4 /etc/iptables/rules.v4.backup 2>/dev/null || true

Configure logging infrastructure

Set up dedicated log files for firewall events with proper log rotation.

# Iptables logging configuration
:msg, contains, "[IPTABLES-DROP]:" /var/log/iptables-drop.log
:msg, contains, "[IPTABLES-ACCEPT]:" /var/log/iptables-accept.log
:msg, contains, "[IPTABLES-REJECT]:" /var/log/iptables-reject.log
:msg, contains, "[PORT-KNOCK]:" /var/log/port-knock.log
:msg, contains, "[DDOS-PROTECT]:" /var/log/ddos-protect.log
& stop

Configure log rotation

Set up automated log rotation to prevent disk space issues.

/var/log/iptables-*.log /var/log/port-knock.log /var/log/ddos-protect.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 640 syslog adm
    postrotate
        /usr/lib/rsyslog/rsyslog-rotate
    endscript
}

Create advanced iptables rules script

Build comprehensive firewall rules with connection tracking, rate limiting, and logging.

#!/bin/bash

# Advanced iptables firewall configuration
# Variables
SSH_PORT=22
HTTP_PORT=80
HTTPS_PORT=443
KNOCK_SEQUENCE="7000 8000 9000"
INTERFACE="eth0"
TRUSTED_NETWORKS="10.0.0.0/8 172.16.0.0/12 192.168.0.0/16"

# Clear existing rules
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X

# Set default policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# Create custom chains
iptables -N DDOS_PROTECT
iptables -N PORT_KNOCK
iptables -N LOGGING_DROP
iptables -N LOGGING_ACCEPT
iptables -N LOGGING_REJECT
iptables -N SCAN_DETECT

# 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

# DDOS Protection Chain
# Rate limit new connections
iptables -A DDOS_PROTECT -m recent --name ddos --rcheck --seconds 60 --hitcount 20 -j LOG --log-prefix "[DDOS-PROTECT]: "
iptables -A DDOS_PROTECT -m recent --name ddos --rcheck --seconds 60 --hitcount 20 -j DROP
iptables -A DDOS_PROTECT -m recent --name ddos --set -j ACCEPT

# Scan Detection Chain
iptables -A SCAN_DETECT -m recent --name portscan --rcheck --seconds 86400 --hitcount 10 -j LOG --log-prefix "[PORT-SCAN]: "
iptables -A SCAN_DETECT -m recent --name portscan --rcheck --seconds 86400 --hitcount 10 -j DROP
iptables -A SCAN_DETECT -m recent --name portscan --set -j ACCEPT

# Port Knocking Chain
# Stage 1: Knock on port 7000
iptables -A PORT_KNOCK -m recent --name knock1 --remove
iptables -A PORT_KNOCK -m recent --name knock2 --remove
iptables -A PORT_KNOCK -m recent --name knock3 --remove
iptables -A PORT_KNOCK -p tcp --dport 7000 -m recent --name knock1 --set -j LOG --log-prefix "[PORT-KNOCK]: Stage 1 - "
iptables -A PORT_KNOCK -p tcp --dport 7000 -j DROP

# Stage 2: Knock on port 8000 within 30 seconds
iptables -A PORT_KNOCK -p tcp --dport 8000 -m recent --name knock1 --rcheck --seconds 30 -m recent --name knock2 --set -j LOG --log-prefix "[PORT-KNOCK]: Stage 2 - "
iptables -A PORT_KNOCK -p tcp --dport 8000 -j DROP

# Stage 3: Knock on port 9000 within 30 seconds
iptables -A PORT_KNOCK -p tcp --dport 9000 -m recent --name knock2 --rcheck --seconds 30 -m recent --name knock3 --set -j LOG --log-prefix "[PORT-KNOCK]: Stage 3 - "
iptables -A PORT_KNOCK -p tcp --dport 9000 -j DROP

# SSH access after successful port knocking
iptables -A PORT_KNOCK -p tcp --dport $SSH_PORT -m recent --name knock3 --rcheck --seconds 30 -m conntrack --ctstate NEW -j LOGGING_ACCEPT
iptables -A PORT_KNOCK -p tcp --dport $SSH_PORT -m conntrack --ctstate NEW -j LOGGING_DROP

# Logging Chains
iptables -A LOGGING_ACCEPT -j LOG --log-prefix "[IPTABLES-ACCEPT]: "
iptables -A LOGGING_ACCEPT -j ACCEPT

iptables -A LOGGING_DROP -j LOG --log-prefix "[IPTABLES-DROP]: "
iptables -A LOGGING_DROP -j DROP

iptables -A LOGGING_REJECT -j LOG --log-prefix "[IPTABLES-REJECT]: "
iptables -A LOGGING_REJECT -j REJECT

# Anti-spoofing rules
for network in $TRUSTED_NETWORKS; do
    iptables -A INPUT -i $INTERFACE ! -s $network -m addrtype --src-type LOCAL -j LOGGING_DROP
done

# Allow trusted networks full access
for network in $TRUSTED_NETWORKS; do
    iptables -A INPUT -s $network -j LOGGING_ACCEPT
done

# Allow ICMP (ping) with rate limiting
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/second --limit-burst 3 -j LOGGING_ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -j LOGGING_DROP

# Allow common ICMP types
iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
iptables -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
iptables -A INPUT -p icmp --icmp-type parameter-problem -j ACCEPT

# Web server protection with rate limiting
iptables -A INPUT -p tcp --dport $HTTP_PORT -m conntrack --ctstate NEW -j DDOS_PROTECT
iptables -A INPUT -p tcp --dport $HTTPS_PORT -m conntrack --ctstate NEW -j DDOS_PROTECT

# Allow HTTP and HTTPS
iptables -A INPUT -p tcp --dport $HTTP_PORT -m conntrack --ctstate NEW -j LOGGING_ACCEPT
iptables -A INPUT -p tcp --dport $HTTPS_PORT -m conntrack --ctstate NEW -j LOGGING_ACCEPT

# SSH protection through port knocking
iptables -A INPUT -p tcp --dport $SSH_PORT -j PORT_KNOCK

# Allow NTP (Network Time Protocol)
iptables -A INPUT -p udp --dport 123 -j LOGGING_ACCEPT

# Allow DNS
iptables -A INPUT -p udp --dport 53 -j LOGGING_ACCEPT
iptables -A INPUT -p tcp --dport 53 -j LOGGING_ACCEPT

# Port scan detection for other ports
iptables -A INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s --limit-burst 2 -j ACCEPT
iptables -A INPUT -m conntrack --ctstate INVALID -j LOGGING_DROP

# Protect against common attacks
# Null packets
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j LOGGING_DROP

# Syn-flood protection
iptables -A INPUT -p tcp ! --syn -m conntrack --ctstate NEW -j LOGGING_DROP

# XMAS packets
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j LOGGING_DROP

# Stealth scans
iptables -A INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -j LOGGING_DROP
iptables -A INPUT -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j LOGGING_DROP

# Drop fragments
iptables -A INPUT -f -j LOGGING_DROP

# Apply scan detection to remaining traffic
iptables -A INPUT -p tcp -m conntrack --ctstate NEW -j SCAN_DETECT

# Log and drop everything else
iptables -A INPUT -j LOGGING_DROP

echo "Advanced firewall rules applied successfully"
echo "Port knocking sequence: $KNOCK_SEQUENCE"
echo "Check logs in /var/log/iptables-*.log and /var/log/port-knock.log"

Create port knocking client script

Build a helper script for legitimate users to perform the port knock sequence.

#!/bin/bash

# Port knocking client for SSH access
if [ $# -ne 1 ]; then
    echo "Usage: $0 

Make scripts executable and apply rules

Set proper permissions and execute the firewall configuration script.

sudo chmod +x /usr/local/bin/setup-advanced-firewall.sh
sudo chmod +x /usr/local/bin/knock-ssh.sh
sudo /usr/local/bin/setup-advanced-firewall.sh

Save iptables rules permanently

Ensure firewall rules persist after system reboot.

sudo iptables-save | sudo tee /etc/iptables/rules.v4
sudo ip6tables-save | sudo tee /etc/iptables/rules.v6
sudo systemctl enable netfilter-persistent
sudo iptables-save | sudo tee /etc/sysconfig/iptables
sudo systemctl enable iptables
sudo systemctl save iptables

Restart rsyslog and configure log monitoring

Apply logging configuration and set up log file permissions.

sudo systemctl restart rsyslog
sudo touch /var/log/iptables-drop.log /var/log/iptables-accept.log /var/log/iptables-reject.log /var/log/port-knock.log /var/log/ddos-protect.log
sudo chown syslog:adm /var/log/iptables-*.log /var/log/port-knock.log /var/log/ddos-protect.log
sudo chmod 640 /var/log/iptables-*.log /var/log/port-knock.log /var/log/ddos-protect.log

Create firewall management script

Build a management interface for common firewall operations.

#!/bin/bash

case "$1" in
    status)
        echo "=== Firewall Status ==="
        iptables -L -n --line-numbers
        echo ""
        echo "=== Connection Tracking ==="
        cat /proc/net/nf_conntrack | wc -l
        echo "Active connections"
        ;;
    logs)
        echo "=== Recent Firewall Logs ==="
        echo "Dropped packets (last 10):"
        tail -10 /var/log/iptables-drop.log 2>/dev/null || echo "No drop logs yet"
        echo ""
        echo "Port knocking attempts (last 10):"
        tail -10 /var/log/port-knock.log 2>/dev/null || echo "No knock logs yet"
        echo ""
        echo "DDoS protection triggers (last 10):"
        tail -10 /var/log/ddos-protect.log 2>/dev/null || echo "No DDoS logs yet"
        ;;
    stats)
        echo "=== Firewall Statistics ==="
        echo "Chain packet/byte counts:"
        iptables -L -n -v
        echo ""
        echo "Recent connection tracking:"
        cat /proc/sys/net/netfilter/nf_conntrack_count
        echo "Current connections"
        cat /proc/sys/net/netfilter/nf_conntrack_max
        echo "Maximum connections"
        ;;
    allow-ip)
        if [ -z "$2" ]; then
            echo "Usage: $0 allow-ip 

Make management script executable

Set permissions for the firewall management script.

sudo chmod +x /usr/local/bin/manage-firewall.sh
Important: Test your configuration thoroughly before applying to production systems. Always maintain a backup connection method and have console access available when implementing advanced firewall rules.

Advanced configuration options

Configure connection tracking optimization

Tune connection tracking parameters for high-traffic environments.

# Connection tracking optimization
net.netfilter.nf_conntrack_max = 1048576
net.netfilter.nf_conntrack_tcp_timeout_established = 1200
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 30
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 60
net.netfilter.nf_conntrack_udp_timeout = 30
net.netfilter.nf_conntrack_udp_timeout_stream = 180

# Hash table size
net.netfilter.nf_conntrack_buckets = 262144

# TCP window scaling
net.netfilter.nf_conntrack_tcp_be_liberal = 1
net.netfilter.nf_conntrack_tcp_loose = 1

Apply sysctl settings

Load the connection tracking optimizations.

sudo sysctl -p /etc/sysctl.d/99-netfilter.conf
sudo sysctl net.netfilter.nf_conntrack_max

Set up automated log monitoring

Create a script to monitor and alert on suspicious firewall activity.

#!/bin/bash

# Firewall log monitoring script
LOG_FILE="/var/log/iptables-drop.log"
ALERT_FILE="/tmp/firewall-alerts.tmp"
THRESHOLD=100
TIME_WINDOW=300  # 5 minutes

# Check for high drop rates
DROP_COUNT=$(tail -1000 "$LOG_FILE" | grep "$(date '+%b %d %H:%M' -d '5 minutes ago')" | wc -l)

if [ "$DROP_COUNT" -gt "$THRESHOLD" ]; then
    echo "$(date): High drop rate detected - $DROP_COUNT drops in last $TIME_WINDOW seconds" >> "$ALERT_FILE"
    
    # Send alert (configure mail/slack webhook as needed)
    echo "ALERT: High firewall drop rate - $DROP_COUNT drops detected" | logger -p local0.warning
fi

# Check for port scan attempts
SCAN_ATTEMPTS=$(grep "PORT-SCAN" /var/log/iptables-drop.log | grep "$(date '+%b %d')" | wc -l)

if [ "$SCAN_ATTEMPTS" -gt 10 ]; then
    echo "$(date): Port scan activity detected - $SCAN_ATTEMPTS attempts today" >> "$ALERT_FILE"
    echo "ALERT: Port scan activity - $SCAN_ATTEMPTS attempts detected today" | logger -p local0.warning
fi

# Check connection tracking table usage
CURRENT_CONNS=$(cat /proc/sys/net/netfilter/nf_conntrack_count)
MAX_CONNS=$(cat /proc/sys/net/netfilter/nf_conntrack_max)
USAGE_PERCENT=$(( CURRENT_CONNS * 100 / MAX_CONNS ))

if [ "$USAGE_PERCENT" -gt 80 ]; then
    echo "$(date): High connection tracking usage - ${USAGE_PERCENT}%" >> "$ALERT_FILE"
    echo "ALERT: Connection tracking usage at ${USAGE_PERCENT}%" | logger -p local0.warning
fi

Set up monitoring cron job

Schedule the monitoring script to run every 5 minutes.

sudo chmod +x /usr/local/bin/firewall-monitor.sh
(sudo crontab -l 2>/dev/null; echo "*/5 * * * * /usr/local/bin/firewall-monitor.sh") | sudo crontab -

Verify your setup

# Check firewall status
sudo /usr/local/bin/manage-firewall.sh status

# View recent logs
sudo /usr/local/bin/manage-firewall.sh logs

# Test port knocking from another machine
# /usr/local/bin/knock-ssh.sh 203.0.113.10

# Check connection tracking
cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max

# Verify logging is working
sudo tail -f /var/log/iptables-drop.log

# Test DDoS protection (from external host)
# for i in {1..25}; do curl -m 1 http://your-server; done

# Check custom chains
sudo iptables -L DDOS_PROTECT -n -v
sudo iptables -L PORT_KNOCK -n -v
sudo iptables -L SCAN_DETECT -n -v

Port knocking usage

To access SSH after implementing port knocking, users must perform the knock sequence first:

# From client machine
/usr/local/bin/knock-ssh.sh 203.0.113.10

# Then immediately connect
ssh user@203.0.113.10

The port knock sequence opens SSH access for 30 seconds. Each successful knock is logged for auditing purposes.

Monitoring and maintenance

Task Command Frequency
Check firewall status manage-firewall.sh status Daily
Review security logs manage-firewall.sh logs Daily
Monitor connection usage manage-firewall.sh stats Weekly
Backup firewall rules manage-firewall.sh backup Before changes
Check log rotation ls -la /var/log/iptables-* Monthly

Consider integrating firewall logs with your centralized logging infrastructure or setting up

Automated install script

Run this to automate the entire setup

¿Prefiere no gestionarlo usted mismo?

Gestionamos la infraestructura de empresas que dependen del tiempo de actividad. Totalmente gestionada, con un contacto fijo que conoce su entorno.

Tiene un contacto fijo que conoce su entorno

Róterdam 20:59 · accesible por mensaje, sin formulario de tickets