This is a subject that comes up often. I've trawled all the answers, most of which contribute useful bits of information but none of which give the whole picture.
I've tried to do the best I can with what I've found here and elsewhere, but would be very happy to hear from anyone who can see what I've missed out (and what bugs I've included).
The source code is at:
http://www.feralchildren.com/getcountry.html
One of the comments lies; it doesn't (yet) check for leading zeros in the IP address. I also haven't bothered with HTTP_X_COMING_FROM or HTTP_COMING_FROM since I'm not convinced anything ever sets these.
To try it out visit:
http://www.feralchildren.com/input3.php
It should work for some caches and proxies, but not an anonymizer, of course. You'll also fool it if you're located in Burkina Faso and dial an ISP in the Ukraine.