Nmap is exponentialy slow when scanning more ports

nmap

I sometimes use nmap to check my hosts. For example: nmap -sS -p- example.com
But this command never finish.

So I divide the scan into small parts: nmap -sS -p 0-999 example.com (12 seconds to finish)
And then nmap -sS -p 1000-1999 example.com (14 seconds to finish)
etc. This is tedious.

If a use wider parts: nmap -sS -p 0-3999 example.com
it takes more than 3 minutes to finish.

And with nmap -sS -p 0-7999 example.com it is not finished after 30 minutes.

So:
1000 ports -> 12 seconds
4000 ports -> 3 minutes
9000 ports -> 30 minutes

What's the problem?
How can I find open TCP ports for one host with nmap?

Best Answer

Nmap does its best to find the speed at which it can accurately find the state (open, closed, or filtered) for every port. The timing system is complex, and it has some worst-case scenarios that can lead to very slow scans. One of these cases is when the target is rate-limiting TCP connection resets (RST), which are the responses Nmap receives when a port is closed. The majority of ports on a system are usually closed, and in order to save resources or perhaps to stymie scanning attempts, the target's OS may choose only to issue a RST once per second.

When Nmap detects RST rate-limiting, it must slow its probes down to match that rate, otherwise a port that is closed may be marked "filtered" because no response was received, consistent with a firewall dropping traffic to that port. This slowdown behavior happens gradually, so the first few ports are not as much affected as later ones. Also, it only affects closed ports, so the commonly-used ports between 1 and 1000 are less likely to contribute to slowness.

There's a workaround for this problem, but it comes with a loss in accuracy. If you don't care about knowing the difference between filtered and closed ports, you can use the --defeat-rst-ratelimit option to not let rate-limited RSTs affect Nmap's timing. Nmap will continue sending at an appropriate rate for the network, detecting dropped packets and slowing down when necessary, but being perfectly happy marking closed ports as filtered. The set of open ports should be exactly the same, which is all that most people want. In fact, you can even add --open to avoid printing info about closed and filtered ports altogether.

Related Question