1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 04:31:29 +00:00

Use the cached timing ping probe as the traceroute probe in all situations.

This commit is contained in:
david
2008-09-06 04:12:34 +00:00
parent dfdf8a5752
commit 40d78569d2
3 changed files with 88 additions and 248 deletions

View File

@@ -6,6 +6,13 @@ o zenmap scan inventory place holder.
o zenmap radialnet integration place holder.
o --traceroute now uses the timing ping probe saved from host
discovery and port scanning instead of finding its own probe. The
timing ping probe is always the best probe for eliciting a response
Nmap knows of. This will have the most effect on traceroute after a
ping scan, where traceroute would sometimes pick the wrong probe and
traceroute would fail even though the target was up.
o Expanded nmap-services to include information on how frequently each
port number is found open. The results were generated by scanning
tens of millions of IPs on the Internet. [Fyodor]

View File

@@ -227,85 +227,6 @@ Traceroute::Traceroute (const char *device_name, devtype type, const scan_lists
/* rely on each group using the same device */
pd = my_pcap_open_live (device_name, 100, o.spoofsource ? 1 : 0, 2);
scaninfo.initial_proto = IPPROTO_IP;
scaninfo.open_response = 0;
scaninfo.open_state = PORT_OPEN;
scaninfo.closed_state = PORT_CLOSED;
scaninfo.ipproto = false;
/* Set up which protocols, tcp flags and responsive
* states to use with the current scan type.
*
* Horribly messy but it is better then peppering
* the nmap source code with references to traceroute */
if (o.synscan) {
scaninfo.scan_flags = TH_SYN;
scaninfo.open_response = TH_SYN | TH_ACK;
scaninfo.closed_response = TH_RST;
} else if (o.ackscan) {
scaninfo.scan_flags = TH_ACK;
scaninfo.open_response = TH_RST;
scaninfo.closed_response = TH_RST;
scaninfo.open_state = PORT_UNFILTERED;
scaninfo.closed_state = PORT_UNFILTERED;
} else if (o.finscan) {
scaninfo.scan_flags = TH_FIN;
scaninfo.closed_response = TH_RST;
} else if (o.xmasscan) {
scaninfo.scan_flags = TH_FIN | TH_URG | TH_PUSH;
scaninfo.closed_response = TH_RST;
} else if (o.nullscan) {
scaninfo.scan_flags = 0;
scaninfo.closed_response = TH_RST;
} else if (o.windowscan) {
scaninfo.scan_flags = TH_ACK;
scaninfo.open_response = TH_RST;
scaninfo.closed_response = TH_RST;
} else if (o.maimonscan) {
scaninfo.scan_flags = TH_FIN | TH_ACK;
scaninfo.open_response = TH_RST;
scaninfo.closed_response = TH_RST;
}
if (o.udpscan)
scaninfo.initial_proto = IPPROTO_UDP;
if (o.synscan || o.finscan || o.xmasscan || o.nullscan ||
o.ackscan || o.windowscan || o.maimonscan)
scaninfo.initial_proto = IPPROTO_TCP;
if (o.ipprotscan)
scaninfo.ipproto = true;
if(o.pingscan) {
scaninfo.open_state = HOST_UP;
if (o.pingtype & PINGTYPE_TCP_USE_SYN) {
scaninfo.scan_flags = TH_SYN;
scaninfo.open_response = TH_SYN | TH_ACK;
scaninfo.closed_response = TH_RST;
scaninfo.initial_proto = IPPROTO_TCP;
} else if (o.pingtype & PINGTYPE_TCP_USE_ACK) {
scaninfo.scan_flags = TH_ACK;
scaninfo.open_response = TH_RST;
scaninfo.closed_response = TH_RST;
scaninfo.initial_proto = IPPROTO_TCP;
} else if (o.pingtype & PINGTYPE_UDP) {
scaninfo.initial_proto = IPPROTO_UDP;
} else if (o.pingtype & PINGTYPE_ICMP_PING) {
scaninfo.initial_proto = IPPROTO_ICMP;
scaninfo.icmp_type = ICMP_ECHO;
} else if (o.pingtype & PINGTYPE_ICMP_TS) {
scaninfo.initial_proto = IPPROTO_ICMP;
scaninfo.icmp_type = ICMP_TIMESTAMP;
} else if(o.pingtype & PINGTYPE_ICMP_MASK) {
scaninfo.initial_proto = IPPROTO_ICMP;
scaninfo.icmp_type = ICMP_ADDRESS;
} else if (o.pingtype & PINGTYPE_PROTO) {
scaninfo.ipproto = true;
}
}
if (o.scanflags != -1)
scaninfo.scan_flags = o.scanflags;
memset (commonPath, 0, sizeof (commonPath));
}
@@ -327,86 +248,26 @@ Traceroute::~Traceroute () {
/* get an open or closed port from the portlist. Traceroute requires a positive response,
* positive responses are generated by different port states depending on the type of scan */
inline int
Traceroute::getTracePort (u8 proto, Target * t) {
u16 open_port = 1;
u16 closed_port = 1;
u16 filtered_port = 1;
u16 port = 0;
int state = -1;
Port *np;
inline const probespec
Traceroute::getTraceProbe (Target * t) {
struct probespec probe;
/* Use the first specified port for ping traceroutes */
if (o.pingscan) {
if (o.pingtype & PINGTYPE_TCP_USE_SYN)
return scanlists->syn_ping_ports[0];
else if (o.pingtype & PINGTYPE_TCP_USE_ACK)
return scanlists->ack_ping_ports[0];
else if (o.pingtype & PINGTYPE_UDP)
return scanlists->udp_ping_ports[0];
else if (o.pingtype & PINGTYPE_PROTO) {
// Initialize protocol header information
port = scanlists->proto_ping_ports[0];
goto ipproto;
} else
return 0;
}
if (proto == IPPROTO_TCP) {
/* can't use filtered ports for tcp */
filtered_port = 0;
open_port = (!scaninfo.open_response) ? 0 : 1;
}
/* For UDP we try for a closed port, then an open one. For everything else
* we try the opposite. When all else fails, we try for filtered */
if (proto == IPPROTO_UDP) {
if (closed_port && t->ports.getStateCounts (proto, scaninfo.closed_state))
state = scaninfo.closed_state;
else if (open_port && t->ports.getStateCounts (proto, scaninfo.open_state))
state = scaninfo.open_state;
} else {
if (open_port && t->ports.getStateCounts (proto, scaninfo.open_state))
state = scaninfo.open_state;
else if (closed_port && t->ports.getStateCounts (proto, scaninfo.closed_state))
state = scaninfo.closed_state;
}
if (state == -1 && filtered_port &&
t->ports.getStateCounts (proto, PORT_FILTERED)) {
state = PORT_FILTERED;
if (o.verbose)
log_write (LOG_PLAIN, "%s: only filtered %s available, results may be incorrect\n",
t->targetipstr (), scaninfo.ipproto ? "protocols" : "ports");
}
if (state == -1)
return -1;
np = t->ports.nextPort (NULL, proto, state);
if (!np)
return -1;
port = np->portno;
ipproto:
/* If this is a protocol scan/ping traceroute and we are using
* one of the major protocols, set up the required information
* so we include the correct protocol headers */
if (proto == IPPROTO_IP) {
if (port == IPPROTO_TCP) {
scaninfo.initial_proto = IPPROTO_TCP;
scaninfo.scan_flags = TH_ACK;
scaninfo.open_response = TH_RST;
scaninfo.closed_response = TH_RST;
} else if (port == IPPROTO_UDP) {
scaninfo.initial_proto = IPPROTO_UDP;
} else if (port == IPPROTO_ICMP) {
scaninfo.initial_proto = IPPROTO_ICMP;
scaninfo.icmp_type = ICMP_ECHO;
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-, and ICMP-specific
fields. Traceroute::sendProbe checks for them there. */
if (probe.type == PS_PROTO) {
if (probe.proto == IPPROTO_TCP) {
probe.pd.tcp.flags = TH_ACK;
probe.pd.tcp.dport = get_random_u16();
} else if (probe.proto == IPPROTO_UDP) {
probe.pd.udp.dport = get_random_u16();
} else if (probe.proto == IPPROTO_ICMP) {
probe.pd.icmp.type = ICMP_ECHO;
}
}
return port;
return probe;
}
/* finite state machine that reads all incoming packets
@@ -480,7 +341,7 @@ Traceroute::readTraceResponses () {
if (tp->ipreplysrc.s_addr)
break;
if ((tg->proto == IPPROTO_UDP && (ip2 && ip2->ip_p == IPPROTO_UDP)) ||
if ((tg->probe.proto == IPPROTO_UDP && (ip2 && ip2->ip_p == IPPROTO_UDP)) ||
(icmp->icmp_type == ICMP_DEST_UNREACH)) {
switch (icmp->icmp_code) {
/* reply from a closed port */
@@ -502,7 +363,7 @@ Traceroute::readTraceResponses () {
}
}
/* icmp ping scan replies */
else if (tg->proto == IPPROTO_ICMP && (icmp->icmp_type == ICMP_ECHOREPLY ||
else if (tg->probe.proto == IPPROTO_ICMP && (icmp->icmp_type == ICMP_ECHOREPLY ||
icmp->icmp_type == ICMP_ADDRESSREPLY || icmp->icmp_type == ICMP_TIMESTAMPREPLY)) {
if (tp->probeType () == PROBE_TTL) {
tg->setHopDistance (get_initial_ttl_guess (ip->ip_ttl), ip->ip_ttl);
@@ -562,8 +423,8 @@ Traceroute::readTraceResponses () {
/* We have reached the destination host and the
* trace can stop for this target */
if (tcp->th_flags & scaninfo.open_response || tcp->th_flags & scaninfo.closed_response) {
if ((tcp->th_flags & TH_RST) == TH_RST
|| (tcp->th_flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK)) {
/* We might have got a late reply */
if (tp->timing.getState () == P_TIMEDOUT)
tp->timing.setState (P_OK);
@@ -643,16 +504,14 @@ Traceroute::readTraceResponses () {
inline void
Traceroute::sendTTLProbes (vector < Target * >&Targets, vector < Target * >&valid_targets) {
Target *t = NULL;
long dport = 0;
struct probespec probe;
u16 sport = 0;
u8 proto;
TraceProbe *tp;
TraceGroup *tg = NULL;
vector < Target * >::iterator it = Targets.begin ();
for (; it != Targets.end (); ++it) {
t = *it;
proto = scaninfo.initial_proto;
/* No point in tracing directly connected nodes */
if (t->directlyConnected ())
@@ -665,36 +524,19 @@ Traceroute::sendTTLProbes (vector < Target * >&Targets, vector < Target * >&vali
}
/* Determine active port to probe */
if ((dport = getTracePort (proto, t)) == -1) {
/* If we could not find a responsive tcp port then try
* to find a responsive udp port */
if (o.udpscan && proto != IPPROTO_UDP) {
proto = IPPROTO_UDP;
dport = getTracePort (proto, t);
}
}
if (dport == -1) {
probe = getTraceProbe (t);
if (probe.type == PS_NONE) {
if (o.verbose > 1)
log_write (LOG_STDOUT, "%s: no responsive %s\n",
t->targetipstr (), scaninfo.ipproto ? "protocols" : "ports");
t->targetipstr (), "probes");
continue;
}
/* If this is a protocol scan/ping, getTracePort() returns
* a protocol number so we need a random destination
* port */
if (scaninfo.ipproto) {
proto = dport;
dport = get_random_u16 ();
scaninfo.initial_proto = IPPROTO_IP;
}
/* start off with a random source port and increment
* it for each probes sent. The source port is the
* distinguishing value used to identify each probe */
sport = get_random_u16 ();
tg = new TraceGroup (t->v4hostip ()->s_addr, sport, dport, proto);
tg = new TraceGroup (t->v4hostip ()->s_addr, sport, probe);
tg->src_mac_addr = t->SrcMACAddress ();
tg->nxt_mac_addr = t->NextHopMACAddress ();
tg->sport++;
@@ -705,8 +547,8 @@ Traceroute::sendTTLProbes (vector < Target * >&Targets, vector < Target * >&vali
if (t->distance != -1) {
tg->setHopDistance (0, t->distance);
} else {
tp = new TraceProbe (proto, t->v4hostip ()->s_addr,
t->v4sourceip ()->s_addr, sport, dport);
tp = new TraceProbe (t->v4hostip ()->s_addr,
t->v4sourceip ()->s_addr, sport, probe);
tp->setProbeType (PROBE_TTL);
tp->ttl = o.ttl;
tg->TraceProbes[sport] = tp;
@@ -731,9 +573,9 @@ Traceroute::sendProbe (TraceProbe * tp) {
struct eth_nfo eth;
struct eth_nfo *ethptr = NULL;
if (scaninfo.scan_flags & TH_ACK)
if (tp->probe.type == PS_TCP && (tp->probe.pd.tcp.flags & TH_ACK) == TH_ACK)
ack = rand ();
if (scaninfo.scan_flags & TH_SYN) {
if (tp->probe.type == PS_TCP && (tp->probe.pd.tcp.flags & TH_SYN) == TH_SYN) {
tcpopts = (u8 *) "\x02\x04\x05\xb4";
tcpoptslen = 4;
}
@@ -764,7 +606,6 @@ Traceroute::sendProbe (TraceProbe * tp) {
}
tg->sport++;
tp->ttl = tg->ttl;
tp->dport = tg->dport;
tg->incRemaining ();
} else {
/* this probe is a retransmission */
@@ -781,29 +622,34 @@ Traceroute::sendProbe (TraceProbe * tp) {
else
source = o.decoys[decoy];
switch (tp->proto) {
case IPPROTO_TCP:
/* For TCP, UDP, and ICMP, also check if the probe is an IP proto probe
whose protocol happens to be one of those protocols. The
protocol-specific fields will have been filled in by
Traceroute::getTraceProbe. */
if (tp->probe.type == PS_TCP
|| (tp->probe.type == PS_PROTO && tp->probe.proto == IPPROTO_TCP)) {
packet = build_tcp_raw (&source, &tp->ipdst, tp->ttl, get_random_u16 (),
get_random_u8 (), 0, NULL, 0, tp->sport, tp->dport,
get_random_u32 (), ack, 0, scaninfo.scan_flags,
get_random_u8 (), false, NULL, 0, tp->sport, tp->probe.pd.tcp.dport,
get_random_u32 (), ack, 0, tp->probe.pd.tcp.flags,
get_random_u16 (), 0, tcpopts, tcpoptslen,
o.extra_payload, o.extra_payload_length, &packetlen);
break;
case IPPROTO_UDP:
} else if (tp->probe.type == PS_UDP
|| (tp->probe.type == PS_PROTO && tp->probe.proto == IPPROTO_UDP)) {
packet = build_udp_raw (&source, &tp->ipdst, tp->ttl, get_random_u16 (),
get_random_u8 (), false,
NULL, 0, tp->sport,
tp->dport, o.extra_payload, o.extra_payload_length, &packetlen);
break;
case IPPROTO_ICMP:
tp->probe.pd.udp.dport, o.extra_payload, o.extra_payload_length, &packetlen);
} else if (tp->probe.type == PS_ICMP
|| (tp->probe.type == PS_PROTO && tp->probe.proto == IPPROTO_ICMP)) {
packet = build_icmp_raw (&source, &tp->ipdst, tp->ttl, 0, 0, false,
NULL, 0, get_random_u16 (), tp->sport, scaninfo.icmp_type, 0,
NULL, 0, get_random_u16 (), tp->sport, tp->probe.pd.icmp.type, 0,
o.extra_payload, o.extra_payload_length, &packetlen);
break;
default:
packet = build_ip_raw (&source, &tp->ipdst, tp->proto, tp->ttl, tp->sport,
get_random_u8 (), false, NULL, 0, o.extra_payload,
o.extra_payload_length, &packetlen);
} else if (tp->probe.type == PS_PROTO) {
packet = build_ip_raw(&source, &tp->ipdst, tp->probe.proto, tp->ttl,
tp->sport, get_random_u8 (), false, NULL, 0,
o.extra_payload, o.extra_payload_length, &packetlen);
} else {
fatal("Unknown probespec type %d in %s\n", tp->probe.type, __func__);
}
send_ip_packet (fd, ethptr, packet, packetlen);
free (packet);
@@ -891,8 +737,8 @@ Traceroute::trace (vector < Target * >&Targets) {
if (tg->getState () != G_OK || !tg->hopDistance)
continue;
tp = new TraceProbe (tg->proto, t->v4hostip ()->s_addr,
t->v4sourceip ()->s_addr, tg->sport, 0);
tp = new TraceProbe (t->v4hostip ()->s_addr,
t->v4sourceip ()->s_addr, tg->sport, tg->probe);
sendProbe (tp);
}
@@ -993,7 +839,6 @@ Traceroute::outputTarget (Target * t) {
TraceGroup *tg = NULL;
NmapOutputTable *Tbl = NULL;
struct protoent *proto;
bool last_consolidation = false;
bool common_consolidation = false;
char row_count = 0;
@@ -1108,11 +953,14 @@ Traceroute::outputTarget (Target * t) {
}
/* Traceroute header and footer */
proto = nmap_getprotbynum(htons(tg->proto));
if(o.ipprotscan || (o.pingscan && !(o.pingtype & PINGTYPE_TCP || o.pingtype & PINGTYPE_UDP)))
log_write(LOG_PLAIN, "\nTRACEROUTE (using proto %d/%s)\n", tg->proto, proto?proto->p_name:"unknown");
else
log_write(LOG_PLAIN, "\nTRACEROUTE (using port %d/%s)\n", tg->dport, proto2ascii(tg->proto));
if (tg->probe.type == PS_TCP) {
log_write(LOG_PLAIN, "\nTRACEROUTE (using port %d/%s)\n", tg->probe.pd.tcp.dport, proto2ascii(tg->probe.proto));
} else if (tg->probe.type == PS_UDP) {
log_write(LOG_PLAIN, "\nTRACEROUTE (using port %d/%s)\n", tg->probe.pd.udp.dport, proto2ascii(tg->probe.proto));
} else if (tg->probe.type == PS_ICMP || tg->probe.type == PS_PROTO) {
struct protoent *proto = nmap_getprotbynum(htons(tg->probe.proto));
log_write(LOG_PLAIN, "\nTRACEROUTE (using proto %d/%s)\n", tg->probe.proto, proto?proto->p_name:"unknown");
}
log_write (LOG_PLAIN, "%s", Tbl->printableTable(NULL));
if(G_TTL(tg->getState()))
@@ -1130,19 +978,23 @@ Traceroute::outputXMLTrace(TraceGroup * tg) {
map < u16, TraceProbe * >::const_iterator it;
TraceProbe *tp = NULL;
const char *hostname_tmp = NULL;
struct protoent *proto;
struct in_addr addr;
long timediff;
short ttl_count;
/* XML traceroute header */
log_write(LOG_XML, "<trace ");
if ((o.pingscan && (o.pingtype & PINGTYPE_TCP || o.pingtype & PINGTYPE_UDP)) || (!o.ipprotscan && !o.pingscan))
log_write(LOG_XML, "port=\"%d\" ", tg->dport);
if((proto = nmap_getprotbynum(htons(tg->proto))))
log_write(LOG_XML, "proto=\"%s\"", proto->p_name);
else
log_write(LOG_XML, "proto=\"%d\"", tg->proto);
if (tg->probe.type == PS_TCP) {
log_write(LOG_XML, "port=\"%d\" ", tg->probe.pd.tcp.dport);
} else if (tg->probe.type == PS_UDP) {
log_write(LOG_XML, "port=\"%d\" ", tg->probe.pd.udp.dport);
} else if (tg->probe.type == PS_ICMP || tg->probe.type == PS_PROTO) {
struct protoent *proto = nmap_getprotbynum(htons(tg->probe.proto));
if (proto == NULL)
log_write(LOG_XML, "proto=\"%d\"", tg->probe.proto);
else
log_write(LOG_XML, "proto=\"%s\"", proto->p_name);
}
log_write(LOG_XML, ">\n");
/* add missing hosts host from the common path */
@@ -1185,11 +1037,10 @@ Traceroute::outputXMLTrace(TraceGroup * tg) {
log_flush(LOG_XML);
}
TraceGroup::TraceGroup (u32 dip, u16 sport, u16 dport, u8 proto) {
TraceGroup::TraceGroup (u32 dip, u16 sport, struct probespec& probe) {
this->ipdst = dip;
this->dport = dport;
this->sport = sport;
this->proto = proto;
this->probe = probe;
ttl = 0;
state = G_OK;
remaining = 0;
@@ -1263,7 +1114,7 @@ TraceGroup::retransmissions (vector < TraceProbe * >&retrans) {
if (droppedPackets > 10 && (droppedPackets /
((double) droppedPackets + repliedPackets) > threshold)) {
if (!scanDelay)
scanDelay = (proto == IPPROTO_TCP) ? 5 : 50;
scanDelay = (probe.type == PS_TCP) ? 5 : 50;
else
scanDelay = MIN (scanDelay * 2, MAX (scanDelay, 800));
droppedPackets = 0;
@@ -1349,10 +1200,9 @@ TraceGroup::setHopDistance (u8 hop_distance, u8 ttl) {
return this->hopDistance;
}
TraceProbe::TraceProbe (u8 proto, u32 dip, u32 sip, u16 sport, u16 dport) {
this->proto = proto;
TraceProbe::TraceProbe (u32 dip, u32 sip, u16 sport, struct probespec& probe) {
this->sport = sport;
this->dport = dport;
this->probe = probe;
ipdst.s_addr = dip;
ipsrc.s_addr = sip;
ipreplysrc.s_addr = 0;

View File

@@ -172,20 +172,6 @@
class NmapOutputTable;
/* various pieces of scan data used by
* traceroute to find responsive ports
* and match probes */
struct scan_info {
u8 initial_proto;
u8 icmp_type;
u8 scan_flags;
u8 open_response;
u8 open_state;
u8 closed_response;
u8 closed_state;
bool ipproto;
};
/* Keeps track of each probes timing state */
class TimeInfo {
public:
@@ -217,7 +203,7 @@ class TimeInfo {
* ttl. Traceprobes are stored inside tracegroups. */
class TraceProbe {
public:
TraceProbe (u8 proto, u32 dip, u32 sip, u16 sport, u16 dport);
TraceProbe (u32 dip, u32 sip, u16 sport, struct probespec& probe);
~TraceProbe ();
/* Return the ip address and resolved hostname in a string
@@ -244,9 +230,8 @@ class TraceProbe {
struct in_addr ipdst;
struct in_addr ipsrc;
struct in_addr ipreplysrc;
struct probespec probe;
u16 sport;
u16 dport;
u8 proto;
u8 ttl;
char **hostname;
@@ -260,7 +245,7 @@ class TraceProbe {
* the ip */
class TraceGroup {
public:
TraceGroup (u32 dip, u16 dport, u16 sport, u8 proto);
TraceGroup (u32 dip, u16 sport, struct probespec& probe);
~TraceGroup ();
/* map of all probes sent to this TraceGroups IP address. The map
* is keyed by the source port of the probe */
@@ -295,9 +280,8 @@ class TraceGroup {
u16 repliedPackets;
u8 consecTimeouts;
/* protocol information */
u8 proto;
struct probespec probe;
u16 sport;
u16 dport;
u32 ipdst;
/* estimated ttl distance to target */
u8 hopDistance;
@@ -344,7 +328,6 @@ class Traceroute {
* the groups destination IP address */
std::map < u32, TraceGroup * >TraceGroups;
struct scan_info scaninfo;
const struct scan_lists * scanlists;
Target **hops;
pcap_t *pd;
@@ -355,7 +338,7 @@ class Traceroute {
/* called by outputTarget to log XML data */
void outputXMLTrace (TraceGroup * tg);
/* find a responsive port for t based on scan results */
int getTracePort (u8 proto, Target * t);
const probespec getTraceProbe (Target * t);
/* sendTTLProbes() guesses the hop distance to a
* target by actively probing the host. */
void sendTTLProbes (std::vector < Target * >&Targets, std::vector < Target * >&vaild_targets);