From 47bbcc165fe6361cd3763693fe79ee1341560b98 Mon Sep 17 00:00:00 2001 From: david Date: Wed, 29 Jul 2009 16:06:03 +0000 Subject: [PATCH] Use ICMP echo for traceroute if no other responsive probe is known. This can happen with -PN against a filtered host or with -PN -sP against any host. This works as expected when the remote host actually responds to the ping probes, but takes a long time when the remote host ignores it. Take this for example: nmap -PN -sP --traceroute www.microsoft.com -n TRACEROUTE (using proto 1/icmp) HOP RTT ADDRESS 1 0.77 192.168.0.1 2 38.76 206.81.73.81 3 38.65 206.81.73.82 4 39.28 66.54.149.185 5 39.73 63.211.250.17 6 39.15 4.68.107.190 7 40.05 4.69.132.37 8 59.33 4.69.132.106 9 54.55 4.69.145.208 10 ... 11 ... [Lots more lines] 49 ... 50 ... ! maximum TTL reached (50) Nmap done: 1 IP address (1 host up) scanned in 2201.79 seconds The traceroute can't stop, as it normally does, when it gets a response from the target because no such response is forthcoming. So it keeps going until it hits its own limit. The same trace against www.google.com takes only about 30 seconds. --- traceroute.cc | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/traceroute.cc b/traceroute.cc index a6d2ba5ca..d11c7ac46 100644 --- a/traceroute.cc +++ b/traceroute.cc @@ -247,10 +247,17 @@ Traceroute::getTraceProbe (Target * t) { struct probespec probe; probe = t->pingprobe; - /* If this is an IP protocol probe, fill in some fields for some common - protocols. We cheat and store them in the TCP-, UDP-, SCTP- and - ICMP-specific fields. Traceroute::sendProbe checks for them there. */ - if (probe.type == PS_PROTO) { + if (probe.type == PS_NONE) { + /* No responsive probe known? The user probably skipped both ping and + port scan. Guess ICMP echo as the most likely to get a response. */ + probe.type = PS_ICMP; + probe.proto = IPPROTO_ICMP; + probe.pd.icmp.type = ICMP_ECHO; + probe.pd.icmp.code = 0; + } else if (probe.type == PS_PROTO) { + /* If this is an IP protocol probe, fill in some fields for some common + protocols. We cheat and store them in the TCP-, UDP-, SCTP- and + ICMP-specific fields. Traceroute::sendProbe checks for them there. */ if (probe.proto == IPPROTO_TCP) { probe.pd.tcp.flags = TH_ACK; probe.pd.tcp.dport = get_random_u16(); @@ -552,12 +559,7 @@ Traceroute::sendTTLProbes (vector < Target * >&Targets, vector < Target * >&vali /* Determine active port to probe */ probe = getTraceProbe (t); - if (probe.type == PS_NONE) { - if (o.verbose > 1) - log_write (LOG_STDOUT, "%s: no responsive probes\n", - t->targetipstr ()); - continue; - } + assert(probe.type != PS_NONE); /* start off with a random source port and increment * it for each probes sent. The source port is the @@ -1135,9 +1137,6 @@ TraceGroup::retransmissions (vector < TraceProbe * >&retrans) { it->second->timing.setState (P_TIMEDOUT); decRemaining (); - if(it->second->ttl > MAX_TTL) - setState(G_DEAD_TTL); - if ((++consecTimeouts) > 5 && maxRetransmissions > 2) maxRetransmissions = 2; if (it->second->probeType () == PROBE_TTL) { @@ -1145,6 +1144,8 @@ TraceGroup::retransmissions (vector < TraceProbe * >&retrans) { noDistProbe = true; if (o.verbose) log_write (LOG_STDOUT, "%s: no reply to our hop distance probe!\n", IPStr ()); + } else if (it->second->ttl > MAX_TTL) { + setState(G_DEAD_TTL); } } else { droppedPackets++;