Geolocation of IP addresses using GeoIP and Google Maps

awghOctober 22, 2010

People mean totally different things when they use the word “hack”.

To me, hacking is what Dr. Frankenstein did just before he created his monster.

Today’s creation will glue a few parts together to make a web site that will show the geographical location of an IP address on Google Maps. This script also lets the user look up the geolocation by DNS hostname.

The advantage of my approach over some others on the net is that this method is totally free and requires no API key. I’ve also made it portable to shared hosting sites, and it will run just as easily on Linux, OSX or Windows web servers.

Screenshot of iplocate.php in action

First, an ingredients list:

A web server or web hosting site that supports PHP.

A copy of the latest version of MaxMind’s GeoIP City database, which provides the mappings from IP to map coordinates in latitude and longitude. You can download the latest free version here.

The scripts require two PEAR modules: Net_DNS and Net_GeoIP. If you are running this on your own server, just use ‘pear install Net_DNS Net_GeoIP’. If you are on Dreamhost, you can follow the awesome instructions on David Yin’s blog to get Pear installed first.

Once you have everything ready, all you need to do is download this PHP script, and customize it in a few places:

If you are on Dreamhost, and you had to install Pear in your home directory, uncomment the Dreamhost section at the top of the file (and replace the path with the real path to the “php” subdirectory of your Pear installation. If you followed David Yin’s instructions above, the path will be:/home/USERNAME/pear/php

Replace the fake path on this line:$geoip = Net_GeoIP::getInstance("/FIX-THIS-PATH/GeoLiteCity.dat");
with the real path to your GeoIP City database file.

Replace the fake IP addresses on this line:$resolver->nameservers = array('YOUR.FIRST.DNS.HERE','YOUR.SECOND.DNS.HERE','YOUR.THIRD.DNS.HERE');
with the real DNS servers that you want to use for looking up hostnames.

Finally, copy the edited file into the documents folder of your web server (make sure that it has a .php extension) and point your browser at it!

You should now be able to enter an IP address or a hostname and have it pull up a Google Map of the correct coordinates! If the hostname lookups don’t work off the bat, double-check step 2 above and try uncommenting the two DNS debugging lines in the PHP file. Remember to give it DNS servers relative to your web server.

At this point, you might be wondering why I’m posting the PHP code instead of simply hosting this page myself. Turns out that Maxmind’s license for the free GeoIP database forbids you from providing a publicly-available interface that allows translating IP addresses into coordinates. The only way to do this (legally) using the free database is to either run this on an internal web server (not accessible to the public) or to password-protect the page using .htaccess files.

Obviously, this could be easily extended to add some stuff like plotting multiple different records from the DNS queries instead of just the first hit. Another idea is to make it spit out KML so that it would just magically work with Google Earth as well. I will leave that to you (or perhaps to some kindly strangers down in the comments).

Also, the hostname lookup feature reveals something interesting when you use it on edge-cached domains or clouds, but I’ll leave that for the home experimenter to explore.

Thanks so much. Great tut. Some FYIs from someone who went about this who is a web designer and rather a noob at command line stuff and networking.

1.) Instead of using David’s post, I used Dreamhost’s official page on installing PEAR, but it’s basically the same thing. http://wiki.dreamhost.com/PEAR

2.) Instead of using “pear install Net_DNS Net_GeoIP”, I used what DH says on their page: “pear install pear/Net_DNS” and “pear install pear/” Not sure if there’s a difference. In any case, I did get a warning saying that Net_DNS has been deprecated in favor of Net_DNS2. Seems to work fine though.

3.) When you said to replace the DNS names with the “ones you want to use for looking up hostnames,” I didn’t know what you were referring to, but just tried putting in my web server’s hostnames. That works so I’m guessing they’re one in the same. Since you’ve talked a lot about DH you might want to mention there that they are NS1.DREAMHOST.COM to NS3.DREAMHOST.COM.

Again, thanks so much for this. Looks and works great. Love the google API implementation too.