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 does not respect probe timeout #1339

Closed
Tim--- opened this Issue Oct 3, 2018 · 5 comments

Comments

Projects
None yet
2 participants
@Tim---

Tim--- commented Oct 3, 2018

Hi !

I'm having trouble with nmap complaining about ping probes getting dropped even though I can see the probe responses. This has the effect of slowing down the scan speed.
After a little investigation, I think there might be a bug in the way nmap handles ping timeouts.

Here is an example :

# nmap -sS -PS53 -p 10000- 8.8.8.8 -dddd --packet-trace --min-rtt-timeout 100ms 2>/dev/null | egrep -w '8.8.8.8:53|Ultrascan'

SENT (0.1231s) TCP [92.169.168.155:34785 > 8.8.8.8:53 S seq=1397322944 ack=0 <snip>
RCVD (0.1247s) TCP [8.8.8.8:53 > 92.169.168.155:34785 SA seq=1196998761 ack=1397322945 <snip>
Ultrascan PING SENT to 8.8.8.8 [tcp to port 53; flags: S]
SENT (1.5927s) TCP [92.169.168.155:35052 > 8.8.8.8:53 S seq=3549618320 ack=0 <snip>
Ultrascan DROPPED PING probe packet to 8.8.8.8 detected
RCVD (1.5945s) TCP [8.8.8.8:53 > 92.169.168.155:35052 SA seq=1468973500 ack=3549618321 <snip>
Ultrascan PING SENT to 8.8.8.8 [tcp to port 53; flags: S]
SENT (2.8870s) TCP [92.169.168.155:35053 > 8.8.8.8:53 S seq=3499287440 ack=0 <snip>
Ultrascan DROPPED PING probe packet to 8.8.8.8 detected
RCVD (2.8884s) TCP [8.8.8.8:53 > 92.169.168.155:35053 SA seq=1224904857 ack=3499287441 <snip>
RCVD (3.1885s) TCP [8.8.8.8:53 > 92.169.168.155:35053 SA seq=1224904857 ack=3499287441 <snip>
Ultrascan PING SENT to 8.8.8.8 [tcp to port 53; flags: S]
SENT (4.2025s) TCP [92.169.168.155:35054 > 8.8.8.8:53 S seq=3516064400 ack=0 <snip>
RCVD (4.2043s) TCP [8.8.8.8:53 > 92.169.168.155:35054 SA seq=221185077 ack=3516064401 <snip>
RCVD (4.5046s) TCP [8.8.8.8:53 > 92.169.168.155:35054 SA seq=221185077 ack=3516064401 <snip>
RCVD (5.1885s) TCP [8.8.8.8:53 > 92.169.168.155:35053 SA seq=1224904857 ack=3499287441 <snip>
...

We can see that nmap sends ping probes using tcp port 53.
It looks like each probe sent gets a response quite fast (~2ms).
Since the minimum rtt timeout is 100ms, nmap should wait at least this amount of time before declaring that a probe is lost.
But we can see that nmap does not wait, and declares the ping as "DROPPED" before the response comes back.

If we specify --min-rtt-timeout 1000ms in the command line, we don't get DROPPED pings anymore.

I have tested nmap from the ubuntu repositories (7.60) and from github master (7.70SVN).

I'll be glad to provide more information if you need.

Regards.

@Tim---

This comment has been minimized.

Show comment
Hide comment
@Tim---

Tim--- Oct 3, 2018

After a big debugging session, I finally got the root cause.
When packets are retrieved with pcap_next(), they are quite "old", between 0 and 200ms.
This means that incoming packets are buffered for some time, and that nmap can't see the response to ping probes early enough.
That's why it assumes those requests are dropped.

If we follow the trace, we find that the buffer time is specified as the last parameter to my_pcap_open_live() (scan_engine_raw.cc) :

if ((USI->pd = my_pcap_open_live(Targets[0]->deviceName(), 256,  (o.spoofsource) ? 1 : 0, pcap_selectable_fd_valid() ? 200 : 2)) == NULL)

In my case, I get 200ms which is of course too much given that the default rtt timeout is 100ms.
I hardcoded a value of 2 and it solved the problem for me. However, I'm not sure this is a proper fix.
Also, I don't know if this should also be fixed in other parts of the code.

Anyway, I hope this has been useful.

Regards.

Tim--- commented Oct 3, 2018

After a big debugging session, I finally got the root cause.
When packets are retrieved with pcap_next(), they are quite "old", between 0 and 200ms.
This means that incoming packets are buffered for some time, and that nmap can't see the response to ping probes early enough.
That's why it assumes those requests are dropped.

If we follow the trace, we find that the buffer time is specified as the last parameter to my_pcap_open_live() (scan_engine_raw.cc) :

if ((USI->pd = my_pcap_open_live(Targets[0]->deviceName(), 256,  (o.spoofsource) ? 1 : 0, pcap_selectable_fd_valid() ? 200 : 2)) == NULL)

In my case, I get 200ms which is of course too much given that the default rtt timeout is 100ms.
I hardcoded a value of 2 and it solved the problem for me. However, I'm not sure this is a proper fix.
Also, I don't know if this should also be fixed in other parts of the code.

Anyway, I hope this has been useful.

Regards.

@dmiller-nmap

This comment has been minimized.

Show comment
Hide comment
@dmiller-nmap

dmiller-nmap Oct 3, 2018

Thanks for this detailed report! Can you please include the output of nmap --version when you make a bug report? This helps us see what versions of libraries are linked with your version. I suspect that this might be related to #34, which was eventually corrected by fixes to libpcap and the Linux kernel. You could easily test for this by using the latest Nmap from github master and configuring --with-libpcap=included.

dmiller-nmap commented Oct 3, 2018

Thanks for this detailed report! Can you please include the output of nmap --version when you make a bug report? This helps us see what versions of libraries are linked with your version. I suspect that this might be related to #34, which was eventually corrected by fixes to libpcap and the Linux kernel. You could easily test for this by using the latest Nmap from github master and configuring --with-libpcap=included.

@Tim---

This comment has been minimized.

Show comment
Hide comment
@Tim---

Tim--- Oct 4, 2018

Thanks for your answer.

Here is the full version :

Nmap version 7.70SVN ( https://nmap.org )
Platform: x86_64-unknown-linux-gnu
Compiled with: nmap-liblua-5.3.4 openssl-1.0.2n nmap-libssh2-1.8.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

I can confirm that using --with-libpcap=included fixed the problem. Thanks !

However, I tried once more with the system-wide version of libpcap to see why it didn't work :

configure gives me this :

checking for pcap_set_immediate_mode... no

config.log tells me more :

configure:6460: checking for pcap_set_immediate_mode
configure:6460: gcc -o conftest -g -O2 -Wall  -Wl,-E  conftest.c  >&5
/tmp/ccBfM6a7.o: In function `main':
/home/tim/soft/nmap/conftest.c:64: undefined reference to `pcap_set_immediate_mode'

Obviously, we see that we miss "-lpcap" in the gcc flags.
This means that the $LIBS variable is empty, probably because we miss a call to AC_CHECK_LIB.

The culprit is here :

[  case "$with_libpcap" in
  yes)
    AC_CHECK_HEADER(pcap.h,[
      AC_CHECK_LIB(pcap, pcap_create,
      [have_libpcap=yes ])])
    ;;

The default action of AC_CHECK_LIB is to updates $LIBS if the library is found.
However, since we specify an explicit action, it does not update $LIBS.

As a quick and dirty fix, I added -lpcap to LIBS and I can confirm that it works great with the system-wide version of libpcap !

Tim--- commented Oct 4, 2018

Thanks for your answer.

Here is the full version :

Nmap version 7.70SVN ( https://nmap.org )
Platform: x86_64-unknown-linux-gnu
Compiled with: nmap-liblua-5.3.4 openssl-1.0.2n nmap-libssh2-1.8.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

I can confirm that using --with-libpcap=included fixed the problem. Thanks !

However, I tried once more with the system-wide version of libpcap to see why it didn't work :

configure gives me this :

checking for pcap_set_immediate_mode... no

config.log tells me more :

configure:6460: checking for pcap_set_immediate_mode
configure:6460: gcc -o conftest -g -O2 -Wall  -Wl,-E  conftest.c  >&5
/tmp/ccBfM6a7.o: In function `main':
/home/tim/soft/nmap/conftest.c:64: undefined reference to `pcap_set_immediate_mode'

Obviously, we see that we miss "-lpcap" in the gcc flags.
This means that the $LIBS variable is empty, probably because we miss a call to AC_CHECK_LIB.

The culprit is here :

[  case "$with_libpcap" in
  yes)
    AC_CHECK_HEADER(pcap.h,[
      AC_CHECK_LIB(pcap, pcap_create,
      [have_libpcap=yes ])])
    ;;

The default action of AC_CHECK_LIB is to updates $LIBS if the library is found.
However, since we specify an explicit action, it does not update $LIBS.

As a quick and dirty fix, I added -lpcap to LIBS and I can confirm that it works great with the system-wide version of libpcap !

@dmiller-nmap

This comment has been minimized.

Show comment
Hide comment
@dmiller-nmap

dmiller-nmap Oct 4, 2018

Oh, I see! Yeah, when using system-provided libpcap, we need to check if immediate mode is available, but for the purposes of the test it's not even linking with libpcap, so that test will always be false. It's not "breaking" our build because it's semi-functional without that, but obviously it's not working properly. I'll get a fix in right away! Thanks!

dmiller-nmap commented Oct 4, 2018

Oh, I see! Yeah, when using system-provided libpcap, we need to check if immediate mode is available, but for the purposes of the test it's not even linking with libpcap, so that test will always be false. It's not "breaking" our build because it's semi-functional without that, but obviously it's not working properly. I'll get a fix in right away! Thanks!

@dmiller-nmap

This comment has been minimized.

Show comment
Hide comment
@dmiller-nmap

dmiller-nmap commented Oct 4, 2018

Fixed in e483615.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment