Nmap Development mailing list archives
[PATCH] Shortening scan time with SO_DONTROUTE
From: Kris Katterjohn <katterjohn () gmail com>
Date: Thu, 01 Jan 2009 02:10:50 -0600
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hey guys, I got an idea flipping through UNP which I thought might be beneficial to Nmap: setting SO_DONTROUTE on the raw sending socket when we're sending to hosts that are directly connected (a very common situation I'm sure). There is the following comment and behavior in targets.cc which says that setting this on the socket shouldn't cause any problems as opposed to having to set MSG_DONTROUTE separately for each packet: /* In some cases, we can only allow hosts that use the same device in a group. Similarly, we don't mix directly-connected boxes with those that aren't */ While my tests unfortunately can't be foolproof, I've done scans varying in the number of ports scanned and with different timing options. Most of the time I've been using a Ruby script to run the different Nmaps several times (with delays between each run) and average out the times (which I had to hack into the XML since accurate times aren't available from what I can see). So while one scan can skew the results, the Nmap that utilizes SO_DONTROUTE wins the vast majority of the time for me with averaged results and not. While the "win" isn't dramatic, a lot of my scans lasted less than five seconds (many thousand ports) and the DONTROUTE version tends to improve at least 1/5 second and sometimes more than 1/2 second better both averaged and standalone. I tried to do many tests with equal environments, but like I said I can't make it anywhere near perfect in my situation. Any testing is encouraged and much appreciated. So is there any reason not to put this in? This doesn't fall in line with the big improvements David's been making in his -perf branch, but this certainly seems to help. I've attached a patch for the SO_DONTROUTE changes, and one for adding the probably misplaced/misnamed XML attribute for the scan time. I would've attached my Ruby script, but it would've been far more trouble than it's worth since it uses a hacked version of my Nmap::Parser, etc, etc. Thanks, Kris Katterjohn -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iQIcBAEBAgAGBQJJXHqFAAoJEEQxgFs5kUfuY2cP/RfUt9vATsEgdR90ZzuFzszC UGNhajAHnygoD7XnvOaPhqEaJnlU2rJXbP20wr3BuMb8LNAV34JNXi8zCZGmRrhL ploUCrGQphsyoxrIMSCb/i294YJzJx8WVCCq8V0+cw3G+spg5jvpRp8NP+YZZNd+ aBla7nw88v2sqbVau31jqXyuT3PN7QyxnhPK/uKpj/tssuTu8OpUmr8pSe8ei4D+ niQmG61pKxHuKZUWKJFk4jVDuLCWoulW73vKfAyS6Nxd4TzdGhAAxRA1eo0pyAKc pYL2CP9VTMS6lwbMBdxNcxWLeyroorMleF2auk3/rZG/yp9LjakKuFieKkerloDF s6QmskiHYlFSVhmuxv+uuIr6Kmc6cq5o0Og5tkGoS7rNOZFUeN5njQundrPN1awy 3wGJS059Alf89Np+IxgblAtJ2BfOzyMfQeViug0mCDxREHnp8BUpPPrJzKsvMOgc BmSxCasiyoEVNWS3HJ93sy0xgSd1no8/w11a4I3D2ttj1USdd/LmPXPS4eXQHKef 7XT5/mzg6oRPS2IZZvW113BZvaGQRziZFWj2DD5gpSrmIN1aPLJRWt9HRya8ObxS dtePnTGHLbOumw6syuwUrX6jRgr74WjLrFsOIdlkfQpjqqutLHgna/Xcddjr6Pl3 P3LYC1wxknrDjrmZS2yC =sbNP -----END PGP SIGNATURE-----
Index: tcpip.cc =================================================================== --- tcpip.cc (revision 11589) +++ tcpip.cc (working copy) @@ -181,6 +181,18 @@ #endif } +void setdontroute(int sd) +{ +#ifdef SO_DONTROUTE + int one = 1; + + if (sd == -1) + return; + + setsockopt(sd, SOL_SOCKET, SO_DONTROUTE, (const char *) &one, sizeof one); +#endif +} + // Takes a protocol number like IPPROTO_TCP, IPPROTO_UDP, or // IPPROTO_IP and returns a ascii representation (or "unknown" if it // doesn't recognize the number). If uppercase is true, the returned Index: tcpip.h =================================================================== --- tcpip.h (revision 11589) +++ tcpip.h (working copy) @@ -667,6 +667,8 @@ void set_ttl(int sd, int ttl); +void setdontroute(int sd); + /* Fill buf (up to buflen -- truncate if necessary but always terminate) with a short representation of the packet stats. Returns buf. Aborts if there is a problem. */ Index: scan_engine.cc =================================================================== --- scan_engine.cc (revision 11589) +++ scan_engine.cc (working copy) @@ -1551,6 +1551,11 @@ #ifndef WIN32 sethdrinclude(rawsd); #endif + /* If these hosts are directly connected, tell the kernel not + * to bother routing these packets (seems to save some time) + */ + if (Targets[0]->directlyConnected()) + setdontroute(rawsd); ethsd = NULL; } }
Index: output.cc =================================================================== --- output.cc (revision 11589) +++ output.cc (working copy) @@ -1957,7 +1957,7 @@ Strncpy(mytime, ctime(&timep), sizeof(mytime)); chomp(mytime); - log_write(LOG_XML, "<runstats><finished time=\"%lu\" timestr=\"%s\"/><hosts up=\"%d\" down=\"%d\" total=\"%d\" />\n", (unsigned long) timep, mytime, o.numhosts_up, o.numhosts_scanned - o.numhosts_up, o.numhosts_scanned); + log_write(LOG_XML, "<runstats><finished time=\"%lu\" timestr=\"%s\" total=\"%.2f\"/><hosts up=\"%d\" down=\"%d\" total=\"%d\" />\n", (unsigned long) timep, mytime, o.TimeSinceStartMS(&tv) / 1000.0, o.numhosts_up, o.numhosts_scanned - o.numhosts_up, o.numhosts_scanned); log_write(LOG_XML, "<!-- Nmap done at %s; %d %s (%d %s up) scanned in %.2f seconds -->\n", mytime, o.numhosts_scanned, (o.numhosts_scanned == 1)? "IP address" : "IP addresses", o.numhosts_up, (o.numhosts_up == 1)? "host" : "hosts", o.TimeSinceStartMS(&tv) / 1000.0 ); log_write(LOG_NORMAL|LOG_MACHINE, "# Nmap done at %s -- %d %s (%d %s up) scanned in %.2f seconds\n", mytime, o.numhosts_scanned, (o.numhosts_scanned == 1)? "IP address" : "IP addresses", o.numhosts_up, (o.numhosts_up == 1)? "host" : "hosts", o.TimeSinceStartMS(&tv) / 1000.0 );
_______________________________________________ Sent through the nmap-dev mailing list http://cgi.insecure.org/mailman/listinfo/nmap-dev Archived at http://SecLists.Org
Current thread:
- [PATCH] Shortening scan time with SO_DONTROUTE Kris Katterjohn (Dec 31)