📝 Logging and Analysis
Why Log?
A firewall silently drops packets, but you want to know exactly what was dropped. A firewall without logs is like a factory without surveillance — when something goes wrong, all you can do is guess.
iptables' LOG target can record packet information to /var/log/kern.log or /var/log/messages before dropping.
LOG Target In-Depth
bash
# Basic logging
iptables -A INPUT -j LOG --log-prefix "IPT-INPUT-DROP: " --log-level 4
# Common log levels
# 0 = emerg 1 = alert 2 = crit 3 = err
# 4 = warning 5 = notice 6 = info 7 = debug
# Only log traffic for specific ports (don't log everything or logs will explode)
iptables -A INPUT -p tcp --dport 22 -m state --state NEW \
-j LOG --log-prefix "SSH-NEW: " --log-level 4
# Rate-limit logging (prevent log storms from killing the system!)
iptables -A INPUT -m limit --limit 5/min --limit-burst 10 \
-j LOG --log-prefix "IPT-DROP: " --log-level 4
# Log invalid packets
iptables -A INPUT -m state --state INVALID \
-j LOG --log-prefix "INVALID: " --log-level 4
# Log rejections for different services separately (easier troubleshooting)
iptables -A INPUT -p tcp --dport 3306 -j LOG --log-prefix "MYSQL-BLOCKED: "
iptables -A INPUT -p tcp --dport 6379 -j LOG --log-prefix "REDIS-BLOCKED: "
iptables -A INPUT -p tcp --dport 27017 -j LOG --log-prefix "MONGO-BLOCKED: "> ⚠️ Warning: > ⚠️ Important: Don't follow LOG with DROP/REJECT! LOG only "records" — it doesn't terminate rule chain processing. The correct approach is to match before LOG, and rules after LOG continue to match (typically followed by a DROP).
Viewing and Analyzing Logs
bash
# Real-time firewall log viewing
tail -f /var/log/kern.log | grep IPT
# View last 100 rejected connections
journalctl -k --since "1 hour ago" | grep "IPT-DROP" | tail -100
# Count most rejected IPs (Top 10 attackers)
journalctl -k | grep "IPT-DROP" | \
grep -oP 'SRC=\K[0-9.]+' | sort | uniq -c | sort -rn | head -10
15234 185.220.101.34
8921 45.155.205.12
3201 192.168.1.200
...
# Analyze which ports are scanned most
journalctl -k | grep "IPT-DROP" | \
grep -oP 'DPT=\K[0-9]+' | sort | uniq -c | sort -rn | head -10
23001 445
18923 3389
5421 22
2100 3306
...
# View all logs for a specific IP
journalctl -k | grep "185.220.101.34" | tail -20
# One-click export analysis report
echo "=== iptables Log Analysis Report ===" > /tmp/ipt-report.txt
echo "Time: $(date)" >> /tmp/ipt-report.txt
echo "" >> /tmp/ipt-report.txt
echo "--- Top 10 Rejected IPs ---" >> /tmp/ipt-report.txt
journalctl -k --since "24 hours ago" | grep "IPT-DROP" | \
grep -oP 'SRC=\K[0-9.]+' | sort | uniq -c | sort -rn | head -10 >> /tmp/ipt-report.txt
echo "" >> /tmp/ipt-report.txt
echo "--- Top 10 Scanned Ports ---" >> /tmp/ipt-report.txt
journalctl -k --since "24 hours ago" | grep "IPT-DROP" | \
grep -oP 'DPT=\K[0-9]+' | sort | uniq -c | sort -rn | head -10 >> /tmp/ipt-report.txt
cat /tmp/ipt-report.txtUsing rsyslog for Categorized Storage
Having trouble finding iptables logs mixed in with system logs? Use rsyslog to store them in a separate file:
bash
# Create rsyslog rule
cat > /etc/rsyslog.d/iptables.conf << 'EOF'
:msg, contains, "IPT-" /var/log/iptables.log
& stop
EOF
# Restart rsyslog
systemctl restart rsyslog
# Configure logrotate to prevent logs from filling the disk
cat > /etc/logrotate.d/iptables << 'EOF'
/var/log/iptables.log {
daily
rotate 7
compress
missingok
notifempty
postrotate
systemctl restart rsyslog
endscript
}
EOF