1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-07 21:21:31 +00:00

New option --defeat-icmp-ratelimit. Closes #353, Fixes #216

This commit is contained in:
dmiller
2016-12-09 04:19:45 +00:00
parent be64d14098
commit 3f1ad0742e
7 changed files with 63 additions and 2 deletions

View File

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

View File

@@ -323,6 +323,7 @@ void NmapOps::Initialize() {
open_only = false; open_only = false;
scanflags = -1; scanflags = -1;
defeat_rst_ratelimit = 0; defeat_rst_ratelimit = 0;
defeat_icmp_ratelimit = 0;
resume_ip.s_addr = 0; resume_ip.s_addr = 0;
osscan_limit = 0; osscan_limit = 0;
osscan_guess = 0; osscan_guess = 0;
@@ -554,7 +555,11 @@ dialog where you can start NPF if you have administrator privileges.";
servicescan = 0; servicescan = 0;
if (defeat_rst_ratelimit && !synscan) { if (defeat_rst_ratelimit && !synscan) {
fatal("Option --defeat-rst-ratelimit works only with a SYN scan (-sS)"); fatal("Option --defeat-rst-ratelimit works only with a SYN scan (-sS)");
}
if (defeat_icmp_ratelimit && !udpscan) {
fatal("Option --defeat-icmp-ratelimit works only with a UDP scan (-sU)");
} }
if (resume_ip.s_addr && generate_random_ips) if (resume_ip.s_addr && generate_random_ips)

View File

@@ -304,6 +304,11 @@ class NmapOps {
slow against it. If we don't distinguish between closed and filtered ports, slow against it. If we don't distinguish between closed and filtered ports,
we can get the list of open ports very fast */ we can get the list of open ports very fast */
int defeat_icmp_ratelimit; /* If a host rate-limits ICMP responses, then scanning
is very slow against it. This option prevents Nmap to adjust timing
when it changes the port's state because of ICMP response, as the latter
might be rate-limited. Doing so we can get scan results faster. */
struct in_addr resume_ip; /* The last IP in the log file if user struct in_addr resume_ip; /* The last IP in the log file if user
requested --restore . Otherwise requested --restore . Otherwise
restore_ip.s_addr == 0. Also restore_ip.s_addr == 0. Also

View File

@@ -2940,6 +2940,25 @@ worth the extra time.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--defeat-icmp-ratelimit</option>
<indexterm><primary><option>--defeat-icmp-ratelimit</option></primary></indexterm></term>
<listitem>
<para>Similar to <option>--defeat-rst-ratelimit</option>, the
<option>--defeat-icmp-ratelimit</option> option trades accuracy for speed,
increasing UDP scanning speed against hosts that rate-limit ICMP error
messages. Because this option causes Nmap to not delay in order to receive
the port unreachable messages, a non-responsive port will be labeled
<literal>closed|filtered</literal> instead of the default
<literal>open|filtered</literal>. This has the effect of only treating ports
which actually respond via UDP as <literal>open</literal>. Since many UDP
services do not respond in this way, the chance for inaccuracy is greater
with this option than with <option>--defeat-rst-ratelimit</option>.</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>--nsock-engine <term><option>--nsock-engine
epoll|kqueue|poll|select</option> epoll|kqueue|poll|select</option>

View File

@@ -585,6 +585,8 @@ void parse_options(int argc, char **argv) {
{"scanflags", required_argument, 0, 0}, {"scanflags", required_argument, 0, 0},
{"defeat_rst_ratelimit", no_argument, 0, 0}, {"defeat_rst_ratelimit", no_argument, 0, 0},
{"defeat-rst-ratelimit", no_argument, 0, 0}, {"defeat-rst-ratelimit", no_argument, 0, 0},
{"defeat_icmp_ratelimit", no_argument, 0, 0},
{"defeat-icmp-ratelimit", no_argument, 0, 0},
{"host_timeout", required_argument, 0, 0}, {"host_timeout", required_argument, 0, 0},
{"host-timeout", required_argument, 0, 0}, {"host-timeout", required_argument, 0, 0},
{"scan_delay", required_argument, 0, 0}, {"scan_delay", required_argument, 0, 0},
@@ -835,6 +837,8 @@ void parse_options(int argc, char **argv) {
delayed_options.pre_scan_delay = l; delayed_options.pre_scan_delay = l;
} else if (optcmp(long_options[option_index].name, "defeat-rst-ratelimit") == 0) { } else if (optcmp(long_options[option_index].name, "defeat-rst-ratelimit") == 0) {
o.defeat_rst_ratelimit = 1; o.defeat_rst_ratelimit = 1;
} else if (optcmp(long_options[option_index].name, "defeat-icmp-ratelimit") == 0) {
o.defeat_icmp_ratelimit = 1;
} else if (optcmp(long_options[option_index].name, "max-scan-delay") == 0) { } else if (optcmp(long_options[option_index].name, "max-scan-delay") == 0) {
l = tval2msecs(optarg); l = tval2msecs(optarg);
if (l < 0) if (l < 0)

View File

@@ -2543,6 +2543,9 @@ void printfinaloutput() {
log_write(LOG_PLAIN, "OS detection performed. Please report any incorrect results at https://nmap.org/submit/ .\n"); log_write(LOG_PLAIN, "OS detection performed. Please report any incorrect results at https://nmap.org/submit/ .\n");
else if (o.servicescan) else if (o.servicescan)
log_write(LOG_PLAIN, "Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .\n"); log_write(LOG_PLAIN, "Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .\n");
else if (o.udpscan && o.defeat_icmp_ratelimit)
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");
} }
log_write(LOG_STDOUT | LOG_SKID, log_write(LOG_STDOUT | LOG_SKID,

View File

@@ -865,7 +865,8 @@ static void set_default_port_state(std::vector<Target *> &targets, stype scantyp
(*target)->ports.setDefaultPortState(IPPROTO_TCP, PORT_OPENFILTERED); (*target)->ports.setDefaultPortState(IPPROTO_TCP, PORT_OPENFILTERED);
break; break;
case UDP_SCAN: case UDP_SCAN:
(*target)->ports.setDefaultPortState(IPPROTO_UDP, PORT_OPENFILTERED); (*target)->ports.setDefaultPortState(IPPROTO_UDP,
o.defeat_icmp_ratelimit ? PORT_CLOSEDFILTERED : PORT_OPENFILTERED);
break; break;
case IPPROT_SCAN: case IPPROT_SCAN:
(*target)->ports.setDefaultPortState(IPPROTO_IP, PORT_OPENFILTERED); (*target)->ports.setDefaultPortState(IPPROTO_IP, PORT_OPENFILTERED);
@@ -2125,6 +2126,25 @@ void ultrascan_port_probe_update(UltraScanInfo *USI, HostScanStats *hss,
adjust_timing = false; adjust_timing = false;
adjust_ping = false; adjust_ping = false;
} }
/* Do not slow down if
1) we are in --defeat-icmp-ratelimit mode
2) the new state is closed or filtered
3) this is a UDP scan
We don't want to adjust timing when we get ICMP response, as the host might
be ratelimiting them. E.g. the port is actually closed, but the host ratelimiting
ICMP responses so we had to retransmit the probe several times in order to
match the (slow) rate limit that the target is using for responses. We
do not want to waste time on such ports.
On the other hand if the port is detected to be open it is a good idea to
adjust timing as we could have done retransmissions due to conjested network */
if (rcvdtime != NULL
&& o.defeat_icmp_ratelimit
&& (newstate == PORT_CLOSED || newstate == PORT_FILTERED)
&& USI->udp_scan) {
if (probe->tryno > 0)
adjust_timing = false;
adjust_ping = false;
}
if (adjust_timing) { if (adjust_timing) {
ultrascan_adjust_timing(USI, hss, probe, rcvdtime); ultrascan_adjust_timing(USI, hss, probe, rcvdtime);