How to Log Dropped Packets in nftables with Policy Drop


2 views

When you set a default policy to drop in an nftables chain, all packets not explicitly accepted by rules will be silently dropped. This is common in firewall configurations for security, but debugging becomes challenging without logging.

The key is to insert a logging rule before the policy takes effect. Here's how to modify your input chain:

chain input {
    type filter hook input priority 0; policy drop;
    
    # Log dropped packets (must come before implicit policy drop)
    counter log prefix "nftables-dropped: " drop
}

Some prefer explicit drop rules instead of chain policies. This approach gives more control:

chain input {
    type filter hook input priority 0; policy accept;
    
    # Your accept rules here
    ct state established,related accept
    
    # Explicit drop with logging
    counter log prefix "input-drop: " drop
}

To prevent log flooding, add rate limiting:

chain input {
    type filter hook input priority 0; policy drop;
    
    # Rate-limited logging (5 packets/second max)
    limit rate 5/second counter log prefix "nft-dropped: " drop
}

Check your system logs using:

journalctl -k -g "nftables-dropped"
# Or for traditional syslog:
grep "nftables-dropped" /var/log/syslog

Here's a full example with common security rules:

table inet filter {
    chain input {
        type filter hook input priority 0; policy drop;
        
        # Allow loopback
        iif "lo" accept
        
        # Allow ICMP (ping)
        ip protocol icmp accept
        
        # Allow established connections
        ct state established,related accept
        
        # SSH rate limiting
        tcp dport 22 ct state new limit rate 15/minute accept
        
        # Log and drop everything else
        counter log prefix "input-drop: " drop
    }
}

When working with nftables, setting a chain policy to 'drop' means any packet not explicitly accepted by rules will be silently discarded. This default behavior makes troubleshooting difficult since there's no visibility into what's being blocked.

To log packets dropped by the chain policy, we need to add an explicit logging rule before the policy takes effect. The key is placing this rule at the end of your chain but before the implicit policy drop:

chain input {
    type filter hook input priority 0;
    
    # Your existing rules here
    # ...
    
    # Log rule before policy drop
    counter log prefix "nftables-policy-drop: " drop
    policy drop;
}

The log statement combined with drop creates an explicit rule that both logs and drops the packet. The prefix helps identify these logs in system logs. The counter is optional but useful for statistics.

For more detailed logging, you can customize the log output:

log flags all prefix "FW-DROP: " level debug \
    snaplen 128 group 1 queue-threshold 10

Key parameters include:

  • flags: Control what packet information gets logged
  • snaplen: Number of bytes to capture
  • group: Netlink group for userspace logging

Logged packets will appear in your system log. For most Linux distributions:

journalctl -k -g "nftables-policy-drop"

Or check traditional syslog files:

grep "nftables-policy-drop" /var/log/syslog

While logging every dropped packet can impact performance in high-traffic environments, consider these optimizations:

# Rate-limited logging
limit rate 5/second log prefix "FW-DROP-RATE: " drop

This limits logging to 5 packets per second while still dropping all unauthorized traffic.

For more selective logging, you can match specific traffic characteristics:

# Define set for interesting hosts
define interesting_ips = { 192.168.1.100, 10.0.0.5 }

chain input {
    # ... other rules
    
    ip saddr $interesting_ips log prefix "DROP-FROM-INTERESTING: " drop
    policy drop;
}