Skip to content

Commit 3f1ad07

Browse files
committed
New option --defeat-icmp-ratelimit. Closes nmap#353, Fixes nmap#216
1 parent be64d14 commit 3f1ad07

File tree

7 files changed

+63
-2
lines changed

7 files changed

+63
-2
lines changed

CHANGELOG

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Nmap Changelog ($Id$); -*-text-*-
22

3+
o [GH#353] New option --defeat-icmp-ratelimit dramatically reduces UDP scan
4+
times in exchange for labeling unresponsive (and possibly open) ports as
5+
"closed|filtered". Ports which give a UDP protocol response to one of Nmap's
6+
scanning payloads will be marked "open". [Sergey Khegay]
7+
38
o [NSE] Script cics-enum enumerates CICS transaction IDs, mapping to screens in
49
TN3270 services. [Soldier of Fortran]
510

NmapOps.cc

+6-1
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ void NmapOps::Initialize() {
323323
open_only = false;
324324
scanflags = -1;
325325
defeat_rst_ratelimit = 0;
326+
defeat_icmp_ratelimit = 0;
326327
resume_ip.s_addr = 0;
327328
osscan_limit = 0;
328329
osscan_guess = 0;
@@ -554,7 +555,11 @@ dialog where you can start NPF if you have administrator privileges.";
554555
servicescan = 0;
555556

556557
if (defeat_rst_ratelimit && !synscan) {
557-
fatal("Option --defeat-rst-ratelimit works only with a SYN scan (-sS)");
558+
fatal("Option --defeat-rst-ratelimit works only with a SYN scan (-sS)");
559+
}
560+
561+
if (defeat_icmp_ratelimit && !udpscan) {
562+
fatal("Option --defeat-icmp-ratelimit works only with a UDP scan (-sU)");
558563
}
559564

560565
if (resume_ip.s_addr && generate_random_ips)

NmapOps.h

+5
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,11 @@ class NmapOps {
304304
slow against it. If we don't distinguish between closed and filtered ports,
305305
we can get the list of open ports very fast */
306306

307+
int defeat_icmp_ratelimit; /* If a host rate-limits ICMP responses, then scanning
308+
is very slow against it. This option prevents Nmap to adjust timing
309+
when it changes the port's state because of ICMP response, as the latter
310+
might be rate-limited. Doing so we can get scan results faster. */
311+
307312
struct in_addr resume_ip; /* The last IP in the log file if user
308313
requested --restore . Otherwise
309314
restore_ip.s_addr == 0. Also

docs/refguide.xml

+19
Original file line numberDiff line numberDiff line change
@@ -2940,6 +2940,25 @@ worth the extra time.</para>
29402940
</listitem>
29412941
</varlistentry>
29422942

2943+
<varlistentry>
2944+
<term><option>--defeat-icmp-ratelimit</option>
2945+
<indexterm><primary><option>--defeat-icmp-ratelimit</option></primary></indexterm></term>
2946+
<listitem>
2947+
2948+
<para>Similar to <option>--defeat-rst-ratelimit</option>, the
2949+
<option>--defeat-icmp-ratelimit</option> option trades accuracy for speed,
2950+
increasing UDP scanning speed against hosts that rate-limit ICMP error
2951+
messages. Because this option causes Nmap to not delay in order to receive
2952+
the port unreachable messages, a non-responsive port will be labeled
2953+
<literal>closed|filtered</literal> instead of the default
2954+
<literal>open|filtered</literal>. This has the effect of only treating ports
2955+
which actually respond via UDP as <literal>open</literal>. Since many UDP
2956+
services do not respond in this way, the chance for inaccuracy is greater
2957+
with this option than with <option>--defeat-rst-ratelimit</option>.</para>
2958+
2959+
</listitem>
2960+
</varlistentry>
2961+
29432962
<varlistentry>
29442963
<term><option>--nsock-engine
29452964
epoll|kqueue|poll|select</option>

nmap.cc

+4
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,8 @@ void parse_options(int argc, char **argv) {
585585
{"scanflags", required_argument, 0, 0},
586586
{"defeat_rst_ratelimit", no_argument, 0, 0},
587587
{"defeat-rst-ratelimit", no_argument, 0, 0},
588+
{"defeat_icmp_ratelimit", no_argument, 0, 0},
589+
{"defeat-icmp-ratelimit", no_argument, 0, 0},
588590
{"host_timeout", required_argument, 0, 0},
589591
{"host-timeout", required_argument, 0, 0},
590592
{"scan_delay", required_argument, 0, 0},
@@ -835,6 +837,8 @@ void parse_options(int argc, char **argv) {
835837
delayed_options.pre_scan_delay = l;
836838
} else if (optcmp(long_options[option_index].name, "defeat-rst-ratelimit") == 0) {
837839
o.defeat_rst_ratelimit = 1;
840+
} else if (optcmp(long_options[option_index].name, "defeat-icmp-ratelimit") == 0) {
841+
o.defeat_icmp_ratelimit = 1;
838842
} else if (optcmp(long_options[option_index].name, "max-scan-delay") == 0) {
839843
l = tval2msecs(optarg);
840844
if (l < 0)

output.cc

+3
Original file line numberDiff line numberDiff line change
@@ -2543,6 +2543,9 @@ void printfinaloutput() {
25432543
log_write(LOG_PLAIN, "OS detection performed. Please report any incorrect results at https://nmap.org/submit/ .\n");
25442544
else if (o.servicescan)
25452545
log_write(LOG_PLAIN, "Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .\n");
2546+
else if (o.udpscan && o.defeat_icmp_ratelimit)
2547+
log_write(LOG_PLAIN, "WARNING: Some ports marked closed|filtered may actually be open. For more accurate results, do not use --defeat-icmp-ratelimit .\n");
2548+
25462549
}
25472550

25482551
log_write(LOG_STDOUT | LOG_SKID,

scan_engine.cc

+21-1
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,8 @@ static void set_default_port_state(std::vector<Target *> &targets, stype scantyp
865865
(*target)->ports.setDefaultPortState(IPPROTO_TCP, PORT_OPENFILTERED);
866866
break;
867867
case UDP_SCAN:
868-
(*target)->ports.setDefaultPortState(IPPROTO_UDP, PORT_OPENFILTERED);
868+
(*target)->ports.setDefaultPortState(IPPROTO_UDP,
869+
o.defeat_icmp_ratelimit ? PORT_CLOSEDFILTERED : PORT_OPENFILTERED);
869870
break;
870871
case IPPROT_SCAN:
871872
(*target)->ports.setDefaultPortState(IPPROTO_IP, PORT_OPENFILTERED);
@@ -2125,6 +2126,25 @@ void ultrascan_port_probe_update(UltraScanInfo *USI, HostScanStats *hss,
21252126
adjust_timing = false;
21262127
adjust_ping = false;
21272128
}
2129+
/* Do not slow down if
2130+
1) we are in --defeat-icmp-ratelimit mode
2131+
2) the new state is closed or filtered
2132+
3) this is a UDP scan
2133+
We don't want to adjust timing when we get ICMP response, as the host might
2134+
be ratelimiting them. E.g. the port is actually closed, but the host ratelimiting
2135+
ICMP responses so we had to retransmit the probe several times in order to
2136+
match the (slow) rate limit that the target is using for responses. We
2137+
do not want to waste time on such ports.
2138+
On the other hand if the port is detected to be open it is a good idea to
2139+
adjust timing as we could have done retransmissions due to conjested network */
2140+
if (rcvdtime != NULL
2141+
&& o.defeat_icmp_ratelimit
2142+
&& (newstate == PORT_CLOSED || newstate == PORT_FILTERED)
2143+
&& USI->udp_scan) {
2144+
if (probe->tryno > 0)
2145+
adjust_timing = false;
2146+
adjust_ping = false;
2147+
}
21282148

21292149
if (adjust_timing) {
21302150
ultrascan_adjust_timing(USI, hss, probe, rcvdtime);

0 commit comments

Comments
 (0)