Tony's ramblings on Open Source Software, Life and Photography

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 ALL SYN,RST,ACK,FIN,URG -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.


Anonymous n00b's picture

very useful, thanks. btw

very useful, thanks. btw there's a typo: on the second line you missed to add a "DROP"

tony's picture

Ah good catch - dunno how

Ah good catch - dunno how that happened because I thought I pasted the lines in from my firewall script. Corrected.

Adam Jakab's picture

cheers

Cheers for these four lines - it always bugged me people scanning my server but i never got around to do anything about it - until i thumbled upon this howto - i tried it myself and now nmap is in great difficulty ;)