Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nmap doesn't respect rtt-timeout? #2312

Closed
DanIntruder opened this issue May 21, 2021 · 2 comments
Closed

Nmap doesn't respect rtt-timeout? #2312

DanIntruder opened this issue May 21, 2021 · 2 comments
Labels
expected-behavior Behavior described is currently expected/documented, but that doesn't preclude improvements Nmap

Comments

@DanIntruder
Copy link

DanIntruder commented May 21, 2021

Describe the bug
When running a SYN scan nmap doesn't respect the current rtt-timeout value when max-retries is non-zero. Specifically, the current "running timeout value" rtt timeout can be exceeded, and nmap will still identify an open port.

Evidence

Using the nmap command:

sudo nmap -sS -T5 -p22 -Pn <host> -d3

Using this command we scan the test host, and the host is forced to delay its response so that it responds on average in ~470ms. Using -T5, the initial rtt timeout value is 250ms, so we expect that the scanner should fail to discover the open port. See below the output of running this test command:

Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-05-21 15:10 BST
Fetchfile found /usr/local/bin/../share/nmap/nmap-services
Fetchfile found /usr/local/bin/../share/nmap/nmap.xsl
The max # of sockets we are using is: 0
--------------- Timing report ---------------
  hostgroups: min 1, max 100000
  rtt-timeouts: init 250, min 50, max 300
  max-scan-delay: TCP 5, UDP 1000, SCTP 5
  parallelism: min 0, max 0
  max-retries: 2, host-timeout: 900000
  min-rate: 0, max-rate: 0
---------------------------------------------
mass_rdns: Using DNS server 127.0.0.53
NSOCK INFO [0.1320s] nsock_iod_new2(): nsock_iod_new (IOD #1)
NSOCK INFO [0.1320s] nsock_connect_udp(): UDP connection requested to 127.0.0.53:53 (IOD #1) EID 8
NSOCK INFO [0.1320s] nsock_read(): Read request from IOD #1 [127.0.0.53:53] (timeout: -1ms) EID 18
Initiating Parallel DNS resolution of 1 host. at 15:10
NSOCK INFO [0.1360s] nsock_write(): Write request for 42 bytes to IOD #1 EID 27 [127.0.0.53:53]
NSOCK INFO [0.1370s] nsock_trace_handler_callback(): Callback: CONNECT SUCCESS for EID 8 [127.0.0.53:53]
NSOCK INFO [0.1370s] nsock_trace_handler_callback(): Callback: WRITE SUCCESS for EID 27 [127.0.0.53:53]
NSOCK INFO [0.1370s] nsock_trace_handler_callback(): Callback: READ SUCCESS for EID 18 [127.0.0.53:53] (108 bytes)
NSOCK INFO [0.1370s] nsock_read(): Read request from IOD #1 [127.0.0.53:53] (timeout: -1ms) EID 34
NSOCK INFO [0.1370s] nsock_iod_delete(): nsock_iod_delete (IOD #1)
NSOCK INFO [0.1370s] nevent_delete(): nevent_delete on event #34 (type READ)
mass_rdns: 0.01s 0/1 [#: 1, OK: 0, NX: 0, DR: 0, SF: 0, TR: 1]
Completed Parallel DNS resolution of 1 host. at 15:10, 0.00s elapsed
DNS resolution of 1 IPs took 0.01s. Mode: Async [#: 1, OK: 1, NX: 0, DR: 0, SF: 0, TR: 1, CN: 0]
Fetchfile found /usr/local/bin/../share/nmap/nmap-payloads
Initiating SYN Stealth Scan at 15:10
Scanning <host> [1 port]
Packet capture filter (device enp0s3): dst host 192.168.1.187 and (icmp or icmp6 or ((tcp or udp or sctp) and (src host <host>)))
Ultrascan timeout init for <host> at 1621606229.857388
SENT (0.2706s) TCP [192.168.1.187:56241 > <host>:22 S seq=4192887628 ack=0 off=6 res=0 win=1024 csum=0x33BF urp=0 <mss 1460>] IP [ver=4 ihl=5 tos=0x00 iplen=44 id=56411 foff=0 ttl=40 proto=6 csum=0x8f08]
**TIMING STATS** (0.2707s): IP, probes active/freshportsleft/retry_stack/outstanding/retranwait/onbench, cwnd/ssthresh/delay, timeout/srtt/rttvar/
   Groupstats (1/1 incomplete): 1/*/*/*/*/* 10.00/75/* 250000/-1/-1
Current sending rates: 720.46 packets / s, 31700.29 bytes / s.
Overall sending rates: 720.46 packets / s, 31700.29 bytes / s.
SENT (0.5209s) TCP [192.168.1.187:56242 > <host>:22 S seq=4192953165 ack=0 off=6 res=0 win=1024 csum=0x33BC urp=0 <mss 1460>] IP [ver=4 ihl=5 tos=0x00 iplen=44 id=25305 foff=0 ttl=49 proto=6 csum=0xff8a]
**TIMING STATS** (0.5218s): IP, probes active/freshportsleft/retry_stack/outstanding/retranwait/onbench, cwnd/ssthresh/delay, timeout/srtt/rttvar/
   Groupstats (1/1 incomplete): 1/*/*/*/*/* 10.00/75/* 250000/-1/-1
Current sending rates: 7.92 packets / s, 348.39 bytes / s.
Overall sending rates: 7.92 packets / s, 348.39 bytes / s.
RCVD (0.7670s) TCP [<host>:22 > 192.168.1.187:56241 SA seq=1688625693 ack=4192887629 off=6 res=0 win=62727 csum=0x7BEA urp=0 <mss 1452>] IP [ver=4 ihl=5 tos=0x00 iplen=44 id=0 flg=D foff=0 ttl=45 proto=6 csum=0x2664]
Found <host> in incomplete hosts list.
Discovered open port 22/tcp on <host>
Changing ping technique for <host> to tcp to port 22; flags: S
**TIMING STATS** (0.8210s): IP, probes active/freshportsleft/retry_stack/outstanding/retranwait/onbench, cwnd/ssthresh/delay, timeout/srtt/rttvar/
   Groupstats (1/1 incomplete): 0/*/*/*/*/* 12.00/75/* 300000/496614/496614
Current sending rates: 3.62 packets / s, 159.49 bytes / s.
Overall sending rates: 3.62 packets / s, 159.49 bytes / s.
Moving <host> to completed hosts list with 0 outstanding probes.
Changing global ping host to <host>.
Completed SYN Stealth Scan at 15:10, 0.56s elapsed (1 total ports)
Overall sending rates: 3.61 packets / s, 158.63 bytes / s.
pcap stats: 1 packets received by filter, 0 dropped by kernel.
Nmap scan report for <host>
Host is up, received user-set (0.50s latency).
Scanned at 2021-05-21 15:10:29 BST for 1s

PORT   STATE SERVICE REASON
22/tcp open  ssh     syn-ack ttl 45
Final times for host: srtt: 496614 rttvar: 496614  to: 300000

Note the SENT/RCVD timings, and the current rtt timeouts above. The host takes 0.76s - 0.27s = 490ms to response, which exceeds the current rtt timeout value of 250000 = 250ms. The port is marked as open, not filtered in the output.

Expected behavior

Based on the timing options documentation, I expected nmap to stop listening for the response after the timeout was exceeded. Intsead, it appears that nmap continues to listen for the first packet even after the second packet (first retry) is sent. Is this expected behaviour?

Whilst this is usually not a bad thing (identifying an open port correctly is normally what a user is aiming to achieve), it does make fine-tuning of timing options difficult, since it appears that nmap can continue to identify an open port right up until the last retry has timed out. Max-retries usually defaults to 1 retry, except if the user has specified max-retries 0 or where nmap deems more retries necessary.

A reasonable use-case for nmap is to perform port scans as quickly as possible, whilst maintaining a reasonable degree of accuracy based on expected latency. If my evaluation of the current functionality is correct, then would it not be necessary to set the timing parameters to half of the targeted rtt, or to use max-retries 0 and accept the loss of accuracy if packets are lost?

Version info (please complete the following information):

  • OS: Ubuntu 18.04.5 LTS
  • Output of nmap --version:
Nmap version 7.91 ( https://nmap.org )
Platform: x86_64-unknown-linux-gnu
Compiled with: liblua-5.3.3 openssl-1.1.1 nmap-libssh2-1.9.0 libz-1.2.11 libpcre-8.39 libpcap-1.8.1 nmap-libdnet-1.12 ipv6
Compiled without:
Available nsock engines: epoll poll select
  • Output of nmap --iflist
 Starting Nmap 7.91 ( https://nmap.org ) at 2021-05-21 15:22 BST
************************INTERFACES************************
DEV     (SHORT)   IP/MASK                     TYPE     UP MTU   MAC
lo      (lo)      127.0.0.1/8                 loopback up 65536
lo      (lo)      ::1/128                     loopback up 65536
enp0s3  (enp0s3)  192.168.1.187/24            ethernet up 1500  08:00:27:EA:C4:A8
enp0s3  (enp0s3)  fe80::37b9:b50e:8d5:d7b8/64 ethernet up 1500  08:00:27:EA:C4:A8
docker0 (docker0) 172.17.0.1/16               ethernet up 1500  02:42:58:98:49:D3

**************************ROUTES**************************
DST/MASK                     DEV     METRIC GATEWAY
192.168.1.0/24               enp0s3  100
172.17.0.0/16                docker0 0
169.254.0.0/16               enp0s3  1000
0.0.0.0/0                    enp0s3  100    192.168.1.254
::1/128                      lo      0
fe80::37b9:b50e:8d5:d7b8/128 enp0s3  0
::1/128                      lo      256
fe80::/64                    enp0s3  100
fe80::/64                    enp0s3  256
ff00::/8                     enp0s3  256

@dmiller-nmap
Copy link

This is intended behavior. Nmap keeps a collection of previous probes around for a while in case they need to be retransmitted (e.g. if the number of retries permitted increases due to network degradation). If a response comes in for one of those, it is accepted, regardless of RTT. The round-trip timeout value is instructional for Nmap, telling it how much time to expect a probe/response to take, and can vary based on network conditions. Timing and performance options are to be used to tune whole scans, not dictate particular behavior on a single-probe basis. You may be more interested in using Nping or another packet crafting tool if you require that level of control over the timeout values.

@dmiller-nmap dmiller-nmap added the expected-behavior Behavior described is currently expected/documented, but that doesn't preclude improvements label Aug 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
expected-behavior Behavior described is currently expected/documented, but that doesn't preclude improvements Nmap
Projects
None yet
Development

No branches or pull requests

3 participants
@dmiller-nmap @DanIntruder and others