Source code for bridgedb.geo
#
#
# This file is part of BridgeDB, a Tor bridge distribution system.
#
# :authors: see AUTHORS file
# :copyright: (c) 2007-2015, The Tor Project, Inc.
# :license: 3-Clause BSD, see LICENSE for licensing information
"""
Boilerplate setup for GeoIP. GeoIP allows us to look up the country code
associated with an IP address. This is a "pure" python version which interacts
with the Maxmind GeoIP API (version 1). It requires, in Debian, the libgeoip-dev
and geoip-database packages.
"""
import logging
from os.path import isfile
from ipaddr import IPv4Address, IPv6Address
# IPv4 database
GEOIP_DBFILE = '/usr/share/GeoIP/GeoIP.dat'
# IPv6 database
GEOIPv6_DBFILE = '/usr/share/GeoIP/GeoIPv6.dat'
try:
# Make sure we have the database before trying to import the module:
if not (isfile(GEOIP_DBFILE) and isfile(GEOIPv6_DBFILE)): # pragma: no cover
raise EnvironmentError("Could not find %r. On Debian-based systems, "
"please install the geoip-database package."
% GEOIP_DBFILE)
import pygeoip
geoip = pygeoip.GeoIP(GEOIP_DBFILE, flags=pygeoip.MEMORY_CACHE)
geoipv6 = pygeoip.GeoIP(GEOIPv6_DBFILE, flags=pygeoip.MEMORY_CACHE)
logging.info("GeoIP databases loaded")
except Exception as err: # pragma: no cover
logging.warn("Error while loading geoip module: %r" % err)
geoip = None
geoipv6 = None
[docs]def getCountryCode(ip):
"""Return the two-letter country code of a given IP address.
:type ip: :class:`ipaddr.IPAddress`
:param ip: An IPv4 OR IPv6 address.
:rtype: ``None`` or str
:returns: If the GeoIP databases are loaded, and the **ip** lookup is
successful, then this returns a two-letter country code. Otherwise,
this returns ``None``.
"""
addr = None
version = None
try:
addr = ip.compressed
version = ip.version
except AttributeError as err:
logging.warn("Wrong type passed to getCountryCode: %s" % str(err))
return None
# GeoIP has two databases: one for IPv4 addresses, and one for IPv6
# addresses. This will ensure we use the correct one.
db = None
# First, make sure we loaded GeoIP properly.
if None in (geoip, geoipv6):
logging.warn("GeoIP databases aren't loaded; can't look up country code")
return None
else:
if version == 4:
db = geoip
else:
db = geoipv6
# Look up the country code of the address.
countryCode = db.country_code_by_addr(addr)
if countryCode:
logging.debug("Looked up country code: %s" % countryCode)
return countryCode
else:
logging.debug("Country code was not detected. IP: %s" % addr)
return None