How to Analyze and Troubleshoot Dropped Traffic in iptables Logs for Linux Firewalls


2 views

When examining iptables log entries like these, we need to decode the key fields to understand what traffic is being blocked:

Oct 20 03:45:50 hostname kernel: iptables denied: IN=eth0 OUT= MAC=xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx SRC=x.x.x.x DST=x.x.x.x LEN=1059 TOS=0x00 PREC=0x00 TTL=115 ID=31368 DF PROTO=TCP SPT=17992 DPT=80 WINDOW=16477 RES=0x00 ACK PSH URGP=0

The critical fields are:

  • SRC: Source IP address of the traffic
  • DST: Destination IP address (your server)
  • PROTO: Protocol (TCP/UDP/ICMP etc.)
  • SPT: Source port of the connection
  • DPT: Destination port (the service being accessed on your server)
  • TCP Flags: ACK/PSH/SYN etc. showing connection state

From your logs, we can identify several patterns:

DPT=80  # HTTP traffic
DPT=22  # SSH traffic

These indicate attempts to access web services and SSH on your server. The fact that these appear frequently suggests either:

  • Normal internet background noise (bots scanning common ports)
  • A misconfiguration in your firewall rules
  • A targeted attack (less likely given the frequency)

Your current rules show:

-A INPUT -s z.z.z.z/32 -j DROP
-A INPUT -s y.y.y.y/32 -j DROP
-A INPUT -s a.a.a.a/32 -j DROP
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

The key observation is that your logging rule is catching traffic before it hits your default policy, which is likely DROP or REJECT. To properly diagnose:

# Check default policy
iptables -L | grep policy

# View complete ruleset with line numbers
iptables -L -v -n --line-numbers

To get more actionable logs, modify your logging rules:

# Log dropped packets with chain and rule info
iptables -I INPUT 5 -m limit --limit 5/min -j LOG --log-prefix "INPUT-DROP: " --log-level 7
iptables -I FORWARD 5 -m limit --limit 5/min -j LOG --log-prefix "FORWARD-DROP: " --log-level 7

# Alternatively, log just before final policy drop
iptables -N LOGGING
iptables -A INPUT -j LOGGING
iptables -A LOGGING -m limit --limit 5/min -j LOG --log-prefix "FINAL-DROP: " --log-level 7
iptables -A LOGGING -j DROP

To filter and analyze logs effectively:

# View only SSH blocked attempts
grep "DPT=22" /var/log/kern.log

# Count blocked IPs
grep "iptables denied" /var/log/kern.log | awk '{print $10}' | sort | uniq -c | sort -n

# Real-time monitoring of drops
tail -f /var/log/kern.log | grep --line-buffered "iptables denied"

Based on the traffic patterns you're seeing:

  1. Rate limiting instead of complete blocking:
    iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set
    iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP
    
  2. Geolocation blocking if attacks come from specific regions
  3. Port knocking for sensitive services like SSH

The key is understanding that some background noise is normal on internet-facing servers, and focusing your rules on protecting actual services while minimizing log noise.


The log entries you're seeing contain crucial network packet information. Let's break down the key fields:

  • DPT: Destination Port (e.g., 22 for SSH, 80 for HTTP)
  • SPT: Source Port
  • PROTO: Protocol (TCP/UDP/ICMP)
  • SRC/DST: Source/Destination IP addresses
  • IN/OUT: Network interface direction
# Sample raw log entry:
Oct 20 03:45:50 hostname kernel: iptables denied: IN=eth0 OUT= MAC=xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx SRC=x.x.x.x DST=x.x.x.x LEN=1059 TOS=0x00 PREC=0x00 TTL=115 ID=31368 DF PROTO=TCP SPT=17992 DPT=80 WINDOW=16477 RES=0x00 ACK PSH URGP=0

Based on your logs, you're seeing blocked attempts to:

  1. HTTP (DPT=80) traffic from various sources
  2. SSH (DPT=22) connections

This suggests your default policy is likely set to DROP packets that don't match any explicit rules. The fact that these aren't from your blocked IP ranges (z.z.z.z, y.y.y.y, a.a.a.a) indicates they're being caught by your default chain policy.

To better understand what's happening, run:

# View current iptables rules with line numbers
sudo iptables -L -v -n --line-numbers

# Check default policies
sudo iptables -S | grep POLICY

The output will show whether your INPUT chain has a default DROP policy, which would explain these logs.

Modify your logging rule to include more context:

# More detailed logging rule
sudo iptables -I INPUT -m conntrack --ctstate NEW -m limit --limit 5/min -j LOG \
  --log-prefix "iptables NEW conn: " --log-level 7

sudo iptables -I INPUT -m limit --limit 5/min -j LOG \
  --log-prefix "iptables DROP: " --log-level 7

This separates new connection attempts from general drops.

Create a traffic summary report from your logs:

# Count blocked traffic by destination port
sudo grep "iptables denied" /var/log/messages | \
  awk '{print $NF}' | \
  awk -F "=" '{print $2}' | \
  sort | uniq -c | sort -n

# Group by source IP and port
sudo grep "iptables denied" /var/log/messages | \
  awk -F "SRC=" '{print $2}' | \
  awk '{print $1,$11}' | \
  awk -F "DPT=" '{print $1,$2}' | \
  sort | uniq -c | sort -n

Based on your analysis, you might want to:

# Allow established connections
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Explicitly allow your services
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT

# Set default policy to DROP (if not already)
sudo iptables -P INPUT DROP

For repeated connection attempts:

# Limit new HTTP connections from single IP
sudo iptables -A INPUT -p tcp --dport 80 -m connlimit \
  --connlimit-above 20 -j LOG --log-prefix "HTTP flood: "

sudo iptables -A INPUT -p tcp --dport 80 -m connlimit \
  --connlimit-above 20 -j DROP

# Protection against port scanners
sudo iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
sudo iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP

To prevent log overflow:

# Rotate logs more frequently
sudo nano /etc/logrotate.d/iptables

# Sample content:
/var/log/iptables.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    notifempty
    create 640 root adm
    postrotate
        /usr/lib/rsyslog/rsyslog-rotate
    endscript
}