Nmap Development mailing list archives

[NSE] Local IP geolocation script


From: Philipp Emanuel Weidmann <philipp.weidmann () gmx de>
Date: Sun, 16 Nov 2008 20:10:35 +0100

Hi everyone,

It's been quite a while since I worked on Nmap (last time I looked into the code NSE was just a pipe dream), but recently I found time again and whipped up this little script which I find very useful.

It provides IP geolocation (country lookup) for each scanned host WITHOUT making any outbound connections and therefore without sending out any data to any registries about your scanning activities. It is in fact a 100% locally acting script. Its lookups are extremely fast (usually less than 0.5 seconds) and since it is absolutely nonintrusive and provides valuable information I have placed it in the "default" category.

For its lookups it uses the MaxMind GeoLite Country database from http://www.maxmind.com (they are claiming 99.5% accuracy; I personally have not found one IP it is incorrect about. It is also updated regularly). To make this script work, install it as usual in your /scripts directory, then download the GeoLite database from http://www.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip and unpack it into your main Nmap directory (where the other data files are so it can be found by nmap.fetchfile).

I hacked this together without knowing any LUA, so if you can improve it in any way, please do so.


Sample output:

Interesting ports on fx-in-f99.google.com (74.125.39.99):
PORT  STATE    SERVICE
5/tcp filtered unknown

Host script results:
|_ IP geolocation: United States (US)


Hope you find it as useful as I do. Have a great day.

Philipp Emanuel Weidmann




=== locateIP.nse ===============================================================


-- NOTE: In order for this script to work, you must download the GeoLite Country database from
-- http://www.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip,
-- unpack it, and place it in the Nmap main directory (where the other Nmap data files are, too)

id          = "IP geolocation"

description = "Displays the location of the scanned host (country only), \
taken from the GeoLite Country database.\n\
NO information WHATSOEVER is sent from the scanning machine."

author      = "Philipp E. Weidmann <philipp.weidmann () gmx de>"

license = "Script: Same as Nmap, see http://nmap.org/book/man-legal.html; \ GeoLite Country database: See http://www.maxmind.com/download/geoip/database/LICENSE.txt";

categories  = {"default", "discovery"}


require "ipOps"


hostrule = function(host)
 return not ipOps.isPrivate(host.ip)
end


action = function(host)
 local ipnumber
 local range_start
 local range_end
 local countrycode
 local countryname

 ipnumber = 16777216 * tonumber(string.match(host.ip, '([0-9]+)')) +
65536 * tonumber(string.match(host.ip, '[0-9]+\.([0-9]+)')) + 256 * tonumber(string.match(host.ip, '[0-9]+\.[0-9]+\.([0-9]+)')) + tonumber(string.match(host.ip, '[0-9]+\.[0-9]+\.[0-9]+\.([0-9]+)'))

 for line in io.lines(nmap.fetchfile("GeoIPCountryWhois.csv")) do
range_start = tonumber(string.match(line, '"[0-9\.]+","[0-9\.]+","([0-9]+)"')) range_end = tonumber(string.match(line, '"[0-9\.]+","[0-9\.]+","[0-9]+","([0-9]+)"')) countrycode = string.match(line, '"[0-9\.]+","[0-9\.]+","[0-9]+","[0-9]+","([^"]+)"') countryname = string.match(line, '"[0-9\.]+","[0-9\.]+","[0-9]+","[0-9]+","[^"]+","([^"]+)"') if (ipnumber >= range_start) and (ipnumber <= range_end) then
     return countryname .. " (" .. countrycode .. ")"
   end
 end

 return
end


=== EOF ===


_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://SecLists.Org


Current thread: