3 # This file is part of BridgeDB, a Tor bridge distribution system.
5 # :authors: see AUTHORS file
6 # :copyright: (c) 2007-2017, The Tor Project, Inc.
7 # :license: 3-Clause BSD, see LICENSE for licensing information
10 Boilerplate setup for GeoIP. GeoIP allows us to look up the country code
11 associated with an IP address. This is a "pure" python version which interacts
12 with the Maxmind GeoIP API (version 1). It requires, in Debian, the libgeoip-dev
13 and geoip-database packages.
17 from os
.path
import isfile
19 from ipaddr
import IPv4Address
, IPv6Address
22 GEOIP_DBFILE
= '/usr/share/GeoIP/GeoIP.dat'
24 GEOIPv6_DBFILE
= '/usr/share/GeoIP/GeoIPv6.dat'
26 # Make sure we have the database before trying to import the module:
27 if not (isfile(GEOIP_DBFILE
) and isfile(GEOIPv6_DBFILE
)): # pragma: no cover
28 raise EnvironmentError("Could not find %r. On Debian-based systems, "
29 "please install the geoip-database package."
33 geoip
= pygeoip
.GeoIP(GEOIP_DBFILE
, flags
=pygeoip
.MEMORY_CACHE
)
34 geoipv6
= pygeoip
.GeoIP(GEOIPv6_DBFILE
, flags
=pygeoip
.MEMORY_CACHE
)
35 logging
.info("GeoIP databases loaded")
36 except Exception as err
: # pragma: no cover
37 logging
.warn("Error while loading geoip module: %r" % err
)
42 def getCountryCode(ip
):
43 """Return the two-letter country code of a given IP address.
45 :type ip: :class:`ipaddr.IPAddress`
46 :param ip: An IPv4 OR IPv6 address.
47 :rtype: ``None`` or str
49 :returns: If the GeoIP databases are loaded, and the **ip** lookup is
50 successful, then this returns a two-letter country code. Otherwise,
51 this returns ``None``.
58 except AttributeError as err
:
59 logging
.warn("Wrong type passed to getCountryCode: %s" % str(err
))
62 # GeoIP has two databases: one for IPv4 addresses, and one for IPv6
63 # addresses. This will ensure we use the correct one.
65 # First, make sure we loaded GeoIP properly.
66 if None in (geoip
, geoipv6
):
67 logging
.warn("GeoIP databases aren't loaded; can't look up country code")
75 # Look up the country code of the address.
76 countryCode
= db
.country_code_by_addr(addr
)
78 logging
.debug("Looked up country code: %s" % countryCode
)
81 logging
.debug("Country code was not detected. IP: %s" % addr
)