MRL WikiMain Page | About | Help | FAQ | Special pages | Log in

Printable version | Disclaimers | Privacy policy

Geoip2kml

From MRL Wiki

If you would like to see geographical distribution of all ips in the world download the latest maxmind GeoLiteCity database ( http://www.maxmind.com/app/geolitecity) and run this script to generate Google Earth KML file. Enjoy ;-)

Below are a few screenshots with the kind of visual data you can get with this tool:

Mapping entire Asia?

Image:Asia.png

Or may be just Bay Area?

Image:Bayarea.png

Each green dot contains a set of ip addresses assigned to that area

Image:Frisco.png

And here is the code to make your own maps. Just copy and paste it into geoip2kml file and run it as perl geoip2kml:

#!/usr/bin/perl
# This script will convert GeoIP data obtained from maxmind
# to Google Earth's KML format for easy viewing. It also 
# supports filters to narrow down interesting areas.
#
# You can get latest GeoIP database here:
# http://www.maxmind.com/app/geolitecity
# Note: Click on "Download the latest GeoLite City CSV Format" link
#       and extract all files in the same directory as this executable
#       The first time you execute, you will have to generate a new
#       database optimized for operations of this script.
#
# Usage:
# geoip2kml -o output_file -f countrycode_or_city_filter
#
# Developed by iphelix@midnightresearch.com

use Socket;
use Getopt::Std;

my %options;
getopt('of',\%options);
my $output_file = $options{o};
my $filter = $options{f};

unless (defined $output_file) {
print '
   _____ __________.____     
  /     \______   \    |    
 /  \ /  \|       _/    |    
/    Y    \    |   \    |___ 
\____|__  /____|_  /_______ \
        \/       \/        \/
'."\t\tpresents...\n\n";
		
print "geoip2kml - Converts GeoIP information to Google Earth's KML format\n";
print "For questions and bug reports contact: iphelix at  midnightresearch.com\n\n";
print "Typical Usage: ./geoip2kml -o filename.kml -f US\n"; 
print " -o filename - specify output KML file name to use with Google Earth\n";
print " -f filter - specify filter (regex) to use when generating KML file\n";
print "             e.g -f US will only show US locations or\n";
print "		    -f \"San Francisco\" will display all ips assigned\n";
print "		    to San Francisco and South San Francisco area\n";
exit 1;
}

###############################################################################
# A) First check if GeoLiteCity-Ids exists which is important for future steps
unless(-e "GeoLiteCity-Ids.csv") {
	print "[!!!] I did not detect GeoLiteCity-Ids.csv file!\n";
	print "[ * ] Generating GeoLiteCity-Ids.csv (it might take awhile)...\n";

	my $temp;
	open(BLOC,"GeoLiteCity-Blocks.csv") || die "[!!!] Couldn't open GeoLiteCity-Blocks.csv\n";

	# skip first two lines
	#read BLOC, $temp, 1; read BLOC, $temp, 1;

	my @ids;
	my ($startIpNum,$endIpNum,$locId);

	my $counter=-1;
	while(<BLOC>) {
		$counter++;
		if($counter < 2) { next; } # skip first two lines
		s/\"//g;
		($startIpNum,$endIpNum,$locId) = split(/,/);
		$ids[$locId] = $ids[$locId].$startIpNum.'-'.$endIpNum."|";	
	}
	close BLOC;

	my $counter=0;

	print "[ * ] Done loading, now sorting ".@ids." elements\n";

	open(IDS,">GeoLiteCity-Ids.csv") || die "[!!!] Couldn't open GeoLiteCity-Ids.csv\n";

	foreach (@ids) {
		print IDS $counter.','.$_."\n";
		unless($counter % 100000) { print "$counter - $_\n"; }
		$counter++;
	}
	close IDS;

}


###############################################################################
# B) Load GeoLiteCity-Ids file and split values into array
my $counter = 0;
my @blocks;

open(BLOC, "GeoLiteCity-Ids.csv") || die "[!!!] Couldn't open GeoLiteCity-Ids.csv\n";
print "[ * ] Loading GeoLiteCity database...\n";
while(<BLOC>) {
	my ($blocId,$ips) = split(/,/);
	$blocks[$blocId] = $ips;
	$counter++;
}
close BLOC;
print "[ * ] Finished loading ".@blocks." elements\n";

###############################################################################
# C) Start generating KML file
print "[ * ] Generating KML file...\n";
$counter = 0;
open(OUT, ">$output_file");

print OUT "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
print OUT "<kml xmlns=\"http://earth.google.com/kml/2.1\">\n";
print OUT "<Document>\n";
print OUT "<Style id='small'>\n";
print OUT "	<IconStyle>\n";
print OUT "		<scale>0.5</scale>\n";
print OUT "		<Icon><href>http://maps.google.com/mapfiles/kml/paddle/grn-blank.png</href></Icon>\n";
print OUT "	</IconStyle>\n";
print OUT "</Style>\n";
print OUT "<Style id='medium'>\n";
print OUT "	<IconStyle>\n";
print OUT "		<scale>1.0</scale>\n";
print OUT "		<Icon><href>http://maps.google.com/mapfiles/kml/paddle/grn-blank.png</href></Icon>\n";
print OUT "	</IconStyle>\n";
print OUT "</Style>\n";
print OUT "<Style id='large'>\n";
print OUT "	<IconStyle>\n";
print OUT "		<scale>1.5</scale>\n";
print OUT "		<Icon><href>http://maps.google.com/mapfiles/kml/paddle/grn-blank.png</href></Icon>\n";
print OUT "	</IconStyle>\n";
print OUT "</Style>\n";
print OUT "<Style id='gigantic'>\n";
print OUT "	<IconStyle>\n";
print OUT "		<scale>2.0</scale>\n";
print OUT "		<Icon><href>http://maps.google.com/mapfiles/kml/paddle/grn-blank.png</href></Icon>\n";
print OUT "	</IconStyle>\n";
print OUT "</Style>\n";
print OUT "<Folder>\n";
print OUT "	<name>GeoIP $filter</name>\n";

# Go through GeoLiteCity-Location file printing out data
open(LOC, "GeoLiteCity-Location.csv") || die "[!!!] Couldn't open GeoLiteCity-Location.csv\n";
while(<LOC>) {
	s/\"//g;
	my ($locId,$country,$region,$city,$postalCode,$latitude,$longitude,$dmaCode,$areaCode) = split(/,/);

	# skip headers and filtered locations
	if($city eq 'city' || $city eq '') { next; }
	if(defined $filter && ($country ne $filter) && ($city !~ $filter)) { next; }

	my (@ranges) = split(/\|/,$blocks[$locId]);
	pop @ranges; #remove last empty | to avoid 0.0.0.0-0.0.0.0

	my $description = "<![CDATA[\n";
	foreach (@ranges) {
		my ($startIpNum, $endIpNum) = split(/-/);
		chomp($startIpNum);
		$description .= inet_ntoa(pack('N',$startIpNum))."
- ".inet_ntoa(pack('N',$endIpNum))."<br>\n";
	}
	$description .= "]]>\n";

	# skip cities with 0 assigned ips
	unless(@ranges) { next; }

	# Add proper styling to the icon depending on the number of IPs in the area
	my $size_style = "small";
	if($#ranges < 10) { $size_style = "small"; }
	elsif($#ranges < 100) { $size_style = "medium"; }
	elsif($#ranges < 1000) { $size_style = "large"; }
	else { $size_style = "gigantic"; }

	print OUT "	<Placemark>\n";
	print OUT "		<name>$city, $country</name>\n";
	print OUT "		<description>".$description."</description>\n";
	print OUT "		<styleUrl>#$size_style</styleUrl>\n";
	print OUT "		<Point>\n";
	print OUT "			<coordinates>$longitude,$latitude</coordinates>\n";
	print OUT "		</Point>\n";
	print OUT "	</Placemark>\n";

	$counter++;
}
close LOC;

print OUT "	</Folder>\n";
print OUT "</Document>\n";
print OUT "</kml>";

close OUT;

print "[ * ] Generated $counter listings\n";	

Retrieved from "http://midnightresearch.com/wiki/index.php/Geoip2kml"

This page has been accessed 8,580 times. This page was last modified on 6 October 2007, at 21:58.


Find

Browse
Main Page
Community portal
Current events
Recent changes
Random page
Help
Edit
Edit this page
Editing help
This page
Discuss this page
New section
Printable version
Context
Page history
What links here
Related changes
My pages
Log in / create account
Special pages
New pages
File list
Statistics
More…