iptables can detect and block port scanners by analyzing connection attempts and implementing rate-limiting or outright blocking based on suspicious activity.

Let’s see iptables in action to detect and block port scanners. Imagine a simple firewall setup on a Linux machine. We’re going to add rules to our INPUT chain.

# First, let's add a rule to log suspicious connection attempts to a specific port, say SSH (port 22).
# We'll use the 'recent' module to track connections from the same IP address.
sudo iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set -j LOG --log-prefix "PORT_SCAN_ATTEMPT: "

# Now, we'll add a rule to drop connections from IPs that have made too many new connections within a certain timeframe.
# This rule should come *after* the logging rule.
sudo iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 5 -j DROP

In the first command, -p tcp --dport 22 specifies we’re looking at TCP traffic destined for port 22. -m state --state NEW targets only new connection attempts. -m recent --set adds the source IP address to a list managed by the recent module. If the IP is already in the list, it does nothing. LOG --log-prefix "PORT_SCAN_ATTEMPT: " then logs this event.

The second command, -m recent --update --seconds 60 --hitcount 5, checks if the source IP has been seen recently. Specifically, it looks if the IP has hit the target (--hitcount 5) at least 5 times within the last 60 seconds (--seconds 60). If it has, the connection is DROPped. This effectively rate-limits or blocks IPs that are aggressively probing port 22.

The problem this solves is that port scanners, by their nature, try to connect to many ports on a target system very quickly. Without any protection, your system’s logs can be flooded, and resources can be consumed by these rapid, often unwanted, connection attempts. iptables with the recent module provides a lightweight, kernel-level mechanism to identify and mitigate this behavior before it becomes a significant issue.

The recent module maintains a list of IP addresses and timestamps. When a packet matches a rule containing -m recent --set, the source IP address and the current time are stored. Subsequent packets from the same IP can be checked against this list using -m recent --update. You can specify a time window (--seconds) and a threshold (--hitcount) to define what constitutes "suspicious" activity.

A common pitfall is placing the DROP rule before the LOG rule. If you do that, the suspicious connection will be dropped silently without logging, making it harder to diagnose the problem. Always log first, then drop.

The beauty of this approach is its efficiency. iptables rules are processed in order, and the recent module is a kernel-level feature, meaning it’s much faster than user-space monitoring tools. You can apply this same logic to multiple ports or even to all TCP/UDP ports if you wish, though be mindful of the potential for legitimate traffic to be inadvertently blocked if your thresholds are too aggressive.

This setup is just for new connections. You might also want to consider blocking IPs that are making a large number of established connections in a short period, though that’s less common for basic port scanning and more indicative of other types of attacks.

Once you’ve set up these rules, you can monitor your system logs for the PORT_SCAN_ATTEMPT prefix. For example, using journalctl:

sudo journalctl -f -t "PORT_SCAN_ATTEMPT"

This will show you real-time log entries from IPs that are being flagged. If you see a specific IP repeatedly showing up, you might want to add a permanent DROP rule for it:

# Example: Permanently block an IP that's been identified as a scanner
sudo iptables -A INPUT -s 192.168.1.100 -j DROP

Remember that these iptables rules are volatile and will be lost on reboot unless you save them. Use iptables-save and iptables-restore or a service like iptables-persistent.

The next error you’ll likely encounter is dealing with SYN floods, which are a more advanced form of DoS attack that can overwhelm your system even before iptablesrecent module can kick in.

Want structured learning?

Take the full Iptables course →