Stop Port Scans In Their Tracks With iptables

Sure, there's a lot of tutorials out there for blocking SYN+FIN, christmas scans, etc.

But did you know that most of those won't help against a default nmap scan? Try it - block all the standard stealth scans, etc using something like the following:

$IPTABLES -A INPUT -p tcp --tcp-flags SYN,ACK SYN,ACK -m state --state NEW -j DROP
$IPTABLES -A INPUT -p tcp --tcp-flags ALL NONE -j DROP

$IPTABLES -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
$IPTABLES -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP

$IPTABLES -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j DROP
$IPTABLES -A INPUT -p tcp --tcp-flags ACK,FIN FIN -j DROP
$IPTABLES -A INPUT -p tcp --tcp-flags ACK,PSH PSH -j DROP
$IPTABLES -A INPUT -p tcp --tcp-flags ACK,URG URG -j DROP

You'll find that a simple nmap scan is still able to list all the ports available on the machine. Not that I'm telling you to not use the above code, in fact it's a good first step.

If someone is trying to find all open ports on your server, think about what's happening. They are randomly going around poking it in various places saying "Hey, who's there?". They poke to the tune of hundreds or even thousands of probes per second.

How do you combat this when the above filters won't catch a straightforward scan? There's several ways, including iptables logging coupled with external programs that block traffic based on those logs, but one way that's quick and painless is to track how fast the user is making new connections and if they go above a certain threshold, start dropping their packets.

Now if you're providing web services, you'll want to add this code after your web services allow code, so that you don't interfere with new connections to the web server. What we want to catch is all the other crap.

$IPTABLES -A INPUT -p tcp -i eth0 -m state --state NEW -m recent --set
$IPTABLES -A INPUT -p tcp -i eth0 -m state --state NEW -m recent --update --seconds 30 --hitcount 10 -j DROP
$IPTABLES -A FORWARD -p tcp -i eth0 -m state --state NEW -m recent --set
$IPTABLES -A FORWARD -p tcp -i eth0 -m state --state NEW -m recent --update --seconds 30 --hitcount 10 -j DROP

You'll notice I specifically stated to only do this on eth0 - which I'm assuming is your Internet-facing adapter. Substitute with whatever your Internet accessible adapter is if this firewall is doing NAT.

What this does is says that if a user attempts 10 new connections to any ports in any order within 30 seconds, start dropping their packets. This has the nice effect of simply stalling out nmap for some reason - after installing this filter and attempting a simple nmap scan from outside my network, nmap froze up and didn't return for over 5 minutes, and I'm only scanning one IP address. Even if nmap is able to work around the delay and actually get back a list of ports, your average user is going to give up long before that happens.

Posted on Mar 10, 2009 | Networking, Network Security, Servers