mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Replace GeoIP Legacy DB support with MaxMind DB support
This updates the "lookup_location" and "lookup_asn" BIFs to use libmaxminddb. The motivation for this is that MaxMind is discontinuing GeoLite Legacy databases: no updates after April 1, 2018, no downloads after January 2, 2019. It's also noted that all GeoIP Legacy databases may be discontinued as they are superseded by GeoIP2.
This commit is contained in:
parent
2502e48a01
commit
1ae7d3b349
7 changed files with 363 additions and 228 deletions
|
@ -140,11 +140,11 @@ include_directories(BEFORE
|
|||
# Optional Dependencies
|
||||
|
||||
set(USE_GEOIP false)
|
||||
find_package(LibGeoIP)
|
||||
if (LIBGEOIP_FOUND)
|
||||
find_package(LibMMDB)
|
||||
if (LibMMDB_FOUND)
|
||||
set(USE_GEOIP true)
|
||||
include_directories(BEFORE ${LibGeoIP_INCLUDE_DIR})
|
||||
list(APPEND OPTLIBS ${LibGeoIP_LIBRARY})
|
||||
include_directories(BEFORE ${LibMMDB_INCLUDE_DIR})
|
||||
list(APPEND OPTLIBS ${LibMMDB_LIBRARY})
|
||||
endif ()
|
||||
|
||||
set(USE_KRB5 false)
|
||||
|
@ -323,7 +323,7 @@ message(
|
|||
"\nBroctl: ${INSTALL_BROCTL}"
|
||||
"\nAux. Tools: ${INSTALL_AUX_TOOLS}"
|
||||
"\n"
|
||||
"\nGeoIP: ${USE_GEOIP}"
|
||||
"\nlibmaxminddb: ${USE_GEOIP}"
|
||||
"\nKerberos: ${USE_KRB5}"
|
||||
"\ngperftools found: ${HAVE_PERFTOOLS}"
|
||||
"\n tcmalloc: ${USE_PERFTOOLS_TCMALLOC}"
|
||||
|
|
9
NEWS
9
NEWS
|
@ -356,6 +356,15 @@ Changed Functionality
|
|||
- The string_to_pattern() built-in (and the now-deprecated merge_pattern()
|
||||
built-in) is no longer restricted to only be called at initialization time.
|
||||
|
||||
- GeoIP Legacy Database support has been replaced with GeoIP2 MaxMind DB
|
||||
format support.
|
||||
|
||||
- This updates the "lookup_location" and "lookup_asn" BIFs to use
|
||||
libmaxminddb. The motivation for this is that MaxMind is discontinuing
|
||||
GeoLite Legacy databases: no updates after April 1, 2018, no downloads
|
||||
after January 2, 2019. It's also noted that all GeoIP Legacy databases
|
||||
may be discontinued as they are superseded by GeoIP2.
|
||||
|
||||
Removed Functionality
|
||||
---------------------
|
||||
|
||||
|
|
|
@ -111,12 +111,6 @@
|
|||
/* Define if KRB5 is available */
|
||||
#cmakedefine USE_KRB5
|
||||
|
||||
/* Whether the found GeoIP API supports IPv6 Country Edition */
|
||||
#cmakedefine HAVE_GEOIP_COUNTRY_EDITION_V6
|
||||
|
||||
/* Whether the found GeoIP API supports IPv6 City Edition */
|
||||
#cmakedefine HAVE_GEOIP_CITY_EDITION_REV0_V6
|
||||
|
||||
/* Use Google's perftools */
|
||||
#cmakedefine USE_PERFTOOLS_DEBUG
|
||||
|
||||
|
|
4
configure
vendored
4
configure
vendored
|
@ -72,7 +72,7 @@ Usage: $0 [OPTION]... [VAR=VALUE]...
|
|||
(a required Broker dependency)
|
||||
|
||||
Optional Packages in Non-Standard Locations:
|
||||
--with-geoip=PATH path to the libGeoIP install root
|
||||
--with-geoip=PATH path to the libmaxminddb install root
|
||||
--with-krb5=PATH path to krb5 install root
|
||||
--with-perftools=PATH path to Google Perftools install root
|
||||
--with-jemalloc=PATH path to jemalloc install root
|
||||
|
@ -252,7 +252,7 @@ while [ $# -ne 0 ]; do
|
|||
append_cache_entry BISON_EXECUTABLE PATH $optarg
|
||||
;;
|
||||
--with-geoip=*)
|
||||
append_cache_entry LibGeoIP_ROOT_DIR PATH $optarg
|
||||
append_cache_entry LibMMDB_ROOT_DIR PATH $optarg
|
||||
;;
|
||||
--with-krb5=*)
|
||||
append_cache_entry LibKrb5_ROOT_DIR PATH $optarg
|
||||
|
|
|
@ -8,11 +8,13 @@ GeoLocation
|
|||
.. rst-class:: opening
|
||||
|
||||
During the process of creating policy scripts the need may arise
|
||||
to find the geographic location for an IP address. Bro has support
|
||||
to find the geographic location for an IP address. Bro had support
|
||||
for the `GeoIP library <http://www.maxmind.com/app/c>`__ at the
|
||||
policy script level beginning with release 1.3 to account for this
|
||||
need. To use this functionality, you need to first install the libGeoIP
|
||||
software, and then install the GeoLite city database before building
|
||||
policy script level from release 1.3 to 2.5.X to account for this
|
||||
need. Starting with release 2.6 GeoIP support requires `libmaxminddb
|
||||
<https://github.com/maxmind/libmaxminddb/releases>`__.
|
||||
To use this functionality, you need to first install the libmaxminddb
|
||||
software, and then install the GeoLite2 city database before building
|
||||
Bro.
|
||||
|
||||
.. contents::
|
||||
|
@ -20,85 +22,91 @@ GeoLocation
|
|||
Install libGeoIP
|
||||
----------------
|
||||
|
||||
Before building Bro, you need to install libGeoIP.
|
||||
Before building Bro, you need to install libmaxminddb.
|
||||
|
||||
* FreeBSD:
|
||||
|
||||
.. console::
|
||||
|
||||
sudo pkg install GeoIP
|
||||
sudo pkg install libmaxminddb
|
||||
|
||||
* RPM/RedHat-based Linux:
|
||||
|
||||
.. console::
|
||||
|
||||
sudo yum install GeoIP-devel
|
||||
sudo yum install libmaxminddb-devel
|
||||
|
||||
* DEB/Debian-based Linux:
|
||||
|
||||
.. console::
|
||||
|
||||
sudo apt-get install libgeoip-dev
|
||||
sudo apt-get install libmaxminddb-dev
|
||||
|
||||
* Mac OS X:
|
||||
|
||||
You need to install from your preferred package management system
|
||||
(e.g. MacPorts, Fink, or Homebrew). The name of the package that you need
|
||||
may be libgeoip, geoip, or geoip-dev, depending on which package management
|
||||
system you are using.
|
||||
may be libmaxminddb, maxminddb, or libmaxminddb-dev, depending on which
|
||||
package management system you are using.
|
||||
|
||||
|
||||
GeoIPLite Database Installation
|
||||
-------------------------------
|
||||
GeoLite2-City Database Installation
|
||||
-----------------------------------
|
||||
|
||||
A country database for GeoIPLite is included when you do the C API
|
||||
install, but for Bro, we are using the city database which includes
|
||||
cities and regions in addition to countries.
|
||||
Bro can use the city or country database. The city database includes cities
|
||||
and regions in addition to countries.
|
||||
|
||||
`Download <http://www.maxmind.com/app/geolitecity>`__ the GeoLite city
|
||||
binary database:
|
||||
`Download <http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz>`__
|
||||
the GeoLite2 city binary database:
|
||||
|
||||
.. console::
|
||||
|
||||
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
|
||||
gunzip GeoLiteCity.dat.gz
|
||||
wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz
|
||||
tar zxf GeoLite2-City.tar.gz
|
||||
|
||||
Next, the file needs to be renamed and put in the GeoIP database directory.
|
||||
This directory should already exist and will vary depending on which platform
|
||||
and package you are using. For FreeBSD, use ``/usr/local/share/GeoIP``. For
|
||||
Linux, use ``/usr/share/GeoIP`` or ``/var/lib/GeoIP`` (choose whichever one
|
||||
already exists).
|
||||
Next, the file "GeoLite2-City_YYYYMMDD/GeoLite2-City.mmdb" needs to be renamed
|
||||
and put in the GeoIP database directory. This directory should already exist
|
||||
and will vary depending on which platform and package you are using. For
|
||||
FreeBSD, use ``/usr/local/share/GeoIP``. For Linux, use ``/usr/share/GeoIP``
|
||||
or ``/var/lib/GeoIP`` (choose whichever one already exists).
|
||||
|
||||
.. console::
|
||||
|
||||
mv GeoLiteCity.dat <path_to_database_dir>/GeoIPCity.dat
|
||||
|
||||
Note that there is a separate database for IPv6 addresses, which can also
|
||||
be installed if you want GeoIP functionality for IPv6.
|
||||
mv <extracted subdir>/GeoLite2-City.mmdb <path_to_database_dir>/GeoLite2-City.mmdb
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
Before using the GeoIP functionality, it is a good idea to verify that
|
||||
everything is setup correctly. After installing libGeoIP and the GeoIP city
|
||||
database, and building Bro, you can quickly check if the GeoIP functionality
|
||||
works by running a command like this:
|
||||
everything is setup correctly. After installing libmaxminddb and the GeoIP
|
||||
city database, and building Bro, you can quickly check if the GeoIP
|
||||
functionality works by running a command like this:
|
||||
|
||||
.. console::
|
||||
|
||||
bro -e "print lookup_location(8.8.8.8);"
|
||||
|
||||
If you see an error message similar to "Failed to open GeoIP City database",
|
||||
then you may need to either rename or move your GeoIP city database file (the
|
||||
error message should give you the full pathname of the database file that
|
||||
Bro is looking for).
|
||||
If you see an error message similar to "Failed to open GeoIP location
|
||||
database", then you may need to either rename or move your GeoIP
|
||||
location database file. Bro looks for location database files in the
|
||||
following order by default:
|
||||
|
||||
/usr/share/GeoIP/GeoLite2-City.mmdb
|
||||
/var/lib/GeoIP/GeoLite2-City.mmdb
|
||||
/usr/local/share/GeoIP/GeoLite2-City.mmdb
|
||||
/usr/local/var/GeoIP/GeoLite2-City.mmdb
|
||||
/usr/share/GeoIP/GeoLite2-Country.mmdb
|
||||
/var/lib/GeoIP/GeoLite2-Country.mmdb
|
||||
/usr/local/share/GeoIP/GeoLite2-Country.mmdb
|
||||
/usr/local/var/GeoIP/GeoLite2-Country.mmdb
|
||||
|
||||
If you see an error message similar to "Bro was not configured for GeoIP
|
||||
support", then you need to rebuild Bro and make sure it is linked against
|
||||
libGeoIP. Normally, if libGeoIP is installed correctly then it should
|
||||
automatically be found when building Bro. If this doesn't happen, then
|
||||
you may need to specify the path to the libGeoIP installation
|
||||
(e.g. ``./configure --with-geoip=<path>``).
|
||||
support", then you either need to rebuild Bro and make sure it is linked
|
||||
against libmaxminddb or else set the :bro:see:`mmdb_dir`` value
|
||||
correctly. Normally, if libmaxminddb is installed correctly then it
|
||||
should automatically be found when building Bro. If this doesn't
|
||||
happen, then you may need to specify the path to the libmaxminddb
|
||||
installation (e.g. ``./configure --with-geoip=<path>``).
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
|
|
@ -872,6 +872,9 @@ type geo_location: record {
|
|||
longitude: double &optional; ##< Longitude.
|
||||
} &log;
|
||||
|
||||
## The directory containing MaxMind DB (*.mmdb) files to use for GeoIP support.
|
||||
const mmdb_dir: string = "" &redef;
|
||||
|
||||
## Computed entropy values. The record captures a number of measures that are
|
||||
## computed in parallel. See `A Pseudorandom Number Sequence Test Program
|
||||
## <http://www.fourmilab.ch/random>`_ for more information, Bro uses the same
|
||||
|
|
485
src/bro.bif
485
src/bro.bif
|
@ -3599,77 +3599,269 @@ function lookup_hostname%(host: string%) : addr_set
|
|||
%%{
|
||||
#ifdef USE_GEOIP
|
||||
extern "C" {
|
||||
#include <GeoIPCity.h>
|
||||
#include <maxminddb.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
}
|
||||
|
||||
static GeoIP* open_geoip_db(GeoIPDBTypes type)
|
||||
class MMDB {
|
||||
public:
|
||||
MMDB(const char* filename);
|
||||
|
||||
~MMDB();
|
||||
|
||||
MMDB_lookup_result_s Lookup(const struct sockaddr* const sa);
|
||||
|
||||
private:
|
||||
MMDB_s mmdb;
|
||||
};
|
||||
|
||||
MMDB::MMDB(const char *filename)
|
||||
{
|
||||
GeoIP* geoip = 0;
|
||||
int status = MMDB_open(filename, MMDB_MODE_MMAP, &mmdb);
|
||||
|
||||
if ( GeoIP_db_avail(type) )
|
||||
geoip = GeoIP_open_type(type, GEOIP_MEMORY_CACHE);
|
||||
|
||||
return geoip;
|
||||
if ( MMDB_SUCCESS != status )
|
||||
{
|
||||
throw std::runtime_error(MMDB_strerror(status));
|
||||
}
|
||||
}
|
||||
|
||||
static GeoIP* open_geoip_city_db()
|
||||
MMDB::~MMDB()
|
||||
{
|
||||
GeoIP* geoip = open_geoip_db(GEOIP_CITY_EDITION_REV0);
|
||||
|
||||
if ( ! geoip )
|
||||
geoip = open_geoip_db(GEOIP_CITY_EDITION_REV1);
|
||||
|
||||
if ( ! geoip )
|
||||
{
|
||||
string rev0_path = GeoIPDBFileName[GEOIP_CITY_EDITION_REV0];
|
||||
string rev1_path = GeoIPDBFileName[GEOIP_CITY_EDITION_REV1];
|
||||
string db_path = rev0_path;
|
||||
|
||||
// Maybe in the future the revisions won't share a common default path.
|
||||
if ( rev0_path != rev1_path )
|
||||
db_path = rev0_path + " or " + rev1_path;
|
||||
|
||||
reporter->Info("Failed to open GeoIP City database: %s",
|
||||
db_path.c_str());
|
||||
MMDB_close(&mmdb);
|
||||
}
|
||||
|
||||
return geoip;
|
||||
MMDB_lookup_result_s MMDB::Lookup(const struct sockaddr* const sa)
|
||||
{
|
||||
int mmdb_error;
|
||||
MMDB_lookup_result_s result = MMDB_lookup_sockaddr(&mmdb, sa, &mmdb_error);
|
||||
|
||||
if ( MMDB_SUCCESS != mmdb_error )
|
||||
{
|
||||
throw std::runtime_error(MMDB_strerror(mmdb_error));
|
||||
}
|
||||
|
||||
static GeoIP* open_geoip_city_db_v6()
|
||||
{
|
||||
GeoIP* geoip = 0;
|
||||
|
||||
// Both city edition revisions for IPv6 show up in libGeoIP 1.4.7.
|
||||
#ifdef HAVE_GEOIP_CITY_EDITION_REV0_V6
|
||||
geoip = open_geoip_db(GEOIP_CITY_EDITION_REV0_V6);
|
||||
|
||||
if ( ! geoip )
|
||||
geoip = open_geoip_db(GEOIP_CITY_EDITION_REV1_V6);
|
||||
|
||||
if ( ! geoip )
|
||||
{
|
||||
string rev0_path = GeoIPDBFileName[GEOIP_CITY_EDITION_REV0_V6];
|
||||
string rev1_path = GeoIPDBFileName[GEOIP_CITY_EDITION_REV1_V6];
|
||||
string db_path = rev0_path;
|
||||
|
||||
// Maybe in the future the revisions won't share a common default path.
|
||||
if ( rev0_path != rev1_path )
|
||||
db_path = rev0_path + " or " + rev1_path;
|
||||
|
||||
reporter->Info("Failed to open GeoIP Cityv6 database: %s",
|
||||
db_path.c_str());
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
return geoip;
|
||||
std::unique_ptr<MMDB> mmdb_loc;
|
||||
std::unique_ptr<MMDB> mmdb_asn;
|
||||
|
||||
static bool mmdb_open(const char* filename, bool asn)
|
||||
{
|
||||
struct stat buf;
|
||||
|
||||
if ( 0 != stat(filename, &buf) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if ( asn )
|
||||
{
|
||||
mmdb_asn.reset(new MMDB(filename));
|
||||
}
|
||||
else
|
||||
{
|
||||
mmdb_loc.reset(new MMDB(filename));
|
||||
}
|
||||
}
|
||||
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
reporter->Info("Failed to open MaxMind DB: %s [%s]", filename,
|
||||
e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool mmdb_open_loc(const char* filename)
|
||||
{
|
||||
return mmdb_open(filename, false);
|
||||
}
|
||||
|
||||
static bool mmdb_open_asn(const char* filename)
|
||||
{
|
||||
return mmdb_open(filename, true);
|
||||
}
|
||||
|
||||
static bool mmdb_lookup(const IPAddr& addr, MMDB_lookup_result_s& result,
|
||||
bool asn)
|
||||
{
|
||||
struct sockaddr_storage ss = {0};
|
||||
|
||||
if ( IPv4 == addr.GetFamily() )
|
||||
{
|
||||
struct sockaddr_in* sa = (struct sockaddr_in*)&ss;
|
||||
sa->sin_family = AF_INET;
|
||||
addr.CopyIPv4(&sa->sin_addr);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
struct sockaddr_in6* sa = (struct sockaddr_in6*)&ss;
|
||||
sa->sin6_family = AF_INET6;
|
||||
addr.CopyIPv6(&sa->sin6_addr);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
result = asn ? mmdb_asn->Lookup((struct sockaddr*)&ss)
|
||||
: mmdb_loc->Lookup((struct sockaddr*)&ss);
|
||||
}
|
||||
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
reporter->Info("MaxMind DB lookup location error [%s]",
|
||||
e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
return result.found_entry;
|
||||
}
|
||||
|
||||
static bool mmdb_lookup_loc(const IPAddr& addr, MMDB_lookup_result_s& result)
|
||||
{
|
||||
return mmdb_lookup(addr, result, false);
|
||||
}
|
||||
|
||||
static bool mmdb_lookup_asn(const IPAddr& addr, MMDB_lookup_result_s& result)
|
||||
{
|
||||
return mmdb_lookup(addr, result, true);
|
||||
}
|
||||
|
||||
static Val* mmdb_getvalue(MMDB_entry_data_s* entry_data, int status,
|
||||
int data_type )
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case MMDB_SUCCESS:
|
||||
if ( entry_data->has_data )
|
||||
{
|
||||
switch (data_type)
|
||||
{
|
||||
case MMDB_DATA_TYPE_UTF8_STRING:
|
||||
return new StringVal(entry_data->data_size,
|
||||
entry_data->utf8_string);
|
||||
break;
|
||||
|
||||
case MMDB_DATA_TYPE_DOUBLE:
|
||||
return new Val(entry_data->double_value, TYPE_DOUBLE);
|
||||
break;
|
||||
|
||||
case MMDB_DATA_TYPE_UINT32:
|
||||
return new Val(entry_data->uint32, TYPE_COUNT);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR:
|
||||
// key doesn't exist, nothing to do
|
||||
break;
|
||||
|
||||
default:
|
||||
reporter->Info("MaxMind DB error [%s]", MMDB_strerror(status));
|
||||
break;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool mmdb_try_open_loc ()
|
||||
{
|
||||
// City database is always preferred over Country database.
|
||||
auto mmdb_dir_val = global_scope()->Lookup("mmdb_dir")->ID_Val();
|
||||
std::string mmdb_dir = mmdb_dir_val->AsString()->CheckString();
|
||||
|
||||
if ( ! mmdb_dir.empty() )
|
||||
{
|
||||
auto d = mmdb_dir + "/GeoLite2-City.mmdb";
|
||||
|
||||
if ( mmdb_open_loc(d.data()) )
|
||||
return true;
|
||||
|
||||
d = mmdb_dir + "/GeoLite2-Country.mmdb";
|
||||
|
||||
if ( mmdb_open_loc(d.data()) )
|
||||
return true;;
|
||||
}
|
||||
|
||||
return mmdb_open_loc("/usr/share/GeoIP/GeoLite2-City.mmdb")
|
||||
|| mmdb_open_loc("/var/lib/GeoIP/GeoLite2-City.mmdb")
|
||||
|| mmdb_open_loc("/usr/local/share/GeoIP/GeoLite2-City.mmdb")
|
||||
|| mmdb_open_loc("/usr/local/var/GeoIP/GeoLite2-City.mmdb")
|
||||
|| mmdb_open_loc("/usr/share/GeoIP/GeoLite2-Country.mmdb")
|
||||
|| mmdb_open_loc("/var/lib/GeoIP/GeoLite2-Country.mmdb")
|
||||
|| mmdb_open_loc("/usr/local/share/GeoIP/GeoLite2-Country.mmdb")
|
||||
|| mmdb_open_loc("/usr/local/var/GeoIP/GeoLite2-Country.mmdb");
|
||||
}
|
||||
|
||||
static bool mmdb_try_open_asn ()
|
||||
{
|
||||
auto mmdb_dir_val = global_scope()->Lookup("mmdb_dir")->ID_Val();
|
||||
std::string mmdb_dir = mmdb_dir_val->AsString()->CheckString();
|
||||
|
||||
if ( ! mmdb_dir.empty() )
|
||||
{
|
||||
auto d = mmdb_dir + "/GeoLite2-ASN.mmdb";
|
||||
|
||||
if ( mmdb_open_asn(d.data()) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return mmdb_open_asn("/usr/share/GeoIP/GeoLite2-ASN.mmdb")
|
||||
|| mmdb_open_asn("/var/lib/GeoIP/GeoLite2-ASN.mmdb")
|
||||
|| mmdb_open_asn("/usr/local/share/GeoIP/GeoLite2-ASN.mmdb")
|
||||
|| mmdb_open_asn("/usr/local/var/GeoIP/GeoLite2-ASN.mmdb");
|
||||
}
|
||||
|
||||
#endif
|
||||
%%}
|
||||
|
||||
## Initializes MMDB for later use of lookup_location.
|
||||
## Requires Bro to be built with ``libmaxminddb``.
|
||||
##
|
||||
## f: The filename of the MaxMind City or Country DB.
|
||||
##
|
||||
## Returns: A boolean indicating whether the db was successfully opened.
|
||||
##
|
||||
## .. bro:see:: lookup_asn
|
||||
function mmdb_open_location_db%(f: string%) : bool
|
||||
%{
|
||||
#ifdef USE_GEOIP
|
||||
return new Val(mmdb_open_loc(f->CheckString()), TYPE_BOOL);
|
||||
#else
|
||||
return new Val(0, TYPE_BOOL);
|
||||
#endif
|
||||
%}
|
||||
|
||||
## Initializes MMDB for later use of lookup_asn.
|
||||
## Requires Bro to be built with ``libmaxminddb``.
|
||||
##
|
||||
## f: The filename of the MaxMind ASN DB.
|
||||
##
|
||||
## Returns: A boolean indicating whether the db was successfully opened.
|
||||
##
|
||||
## .. bro:see:: lookup_asn
|
||||
function mmdb_open_asn_db%(f: string%) : bool
|
||||
%{
|
||||
#ifdef USE_GEOIP
|
||||
return new Val(mmdb_open_asn(f->CheckString()), TYPE_BOOL);
|
||||
#else
|
||||
return new Val(0, TYPE_BOOL);
|
||||
#endif
|
||||
%}
|
||||
|
||||
## Performs a geo-lookup of an IP address.
|
||||
## Requires Bro to be built with ``libgeoip``.
|
||||
## Requires Bro to be built with ``libmaxminddb``.
|
||||
##
|
||||
## a: The IP address to lookup.
|
||||
##
|
||||
|
@ -3681,104 +3873,52 @@ function lookup_location%(a: addr%) : geo_location
|
|||
RecordVal* location = new RecordVal(geo_location);
|
||||
|
||||
#ifdef USE_GEOIP
|
||||
static bool geoip_initialized = false;
|
||||
static GeoIP* geoip = 0;
|
||||
static GeoIP* geoip_v6 = 0;
|
||||
static bool have_city_db = false;
|
||||
static bool have_cityv6_db = false;
|
||||
GeoIPRecord* gir = 0;
|
||||
const char* cc = 0;
|
||||
|
||||
if ( ! geoip_initialized )
|
||||
if ( ! mmdb_loc )
|
||||
{
|
||||
geoip_initialized = true;
|
||||
geoip = open_geoip_city_db();
|
||||
|
||||
if ( ! geoip )
|
||||
if ( ! mmdb_try_open_loc() )
|
||||
{
|
||||
geoip = open_geoip_db(GEOIP_COUNTRY_EDITION);
|
||||
string db_path = GeoIPDBFileName[GEOIP_COUNTRY_EDITION];
|
||||
|
||||
if ( ! geoip )
|
||||
builtin_error(fmt("Failed fall back to GeoIP Country "
|
||||
"database: %s",
|
||||
GeoIPDBFileName[GEOIP_COUNTRY_EDITION]));
|
||||
else
|
||||
reporter->Info("Fell back to GeoIP Country database");
|
||||
}
|
||||
else
|
||||
have_city_db = true;
|
||||
|
||||
geoip_v6 = open_geoip_city_db_v6();
|
||||
|
||||
if ( geoip_v6 )
|
||||
have_cityv6_db = true;
|
||||
|
||||
#ifdef HAVE_GEOIP_COUNTRY_EDITION_V6
|
||||
if ( ! geoip_v6 )
|
||||
{
|
||||
geoip_v6 = open_geoip_db(GEOIP_COUNTRY_EDITION_V6);
|
||||
|
||||
if ( ! geoip_v6 )
|
||||
reporter->Info("Failed to open GeoIPv6 Country database: %s",
|
||||
GeoIPDBFileName[GEOIP_COUNTRY_EDITION_V6]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( ! geoip_v6 )
|
||||
builtin_error("Can't open GeoIPv6 City/Country database");
|
||||
}
|
||||
|
||||
#ifdef HAVE_GEOIP_COUNTRY_EDITION_V6
|
||||
if ( geoip_v6 && a->AsAddr().GetFamily() == IPv6 )
|
||||
{
|
||||
geoipv6_t ga;
|
||||
a->AsAddr().CopyIPv6(&ga);
|
||||
if ( have_cityv6_db )
|
||||
gir = GeoIP_record_by_ipnum_v6(geoip_v6, ga);
|
||||
else
|
||||
cc = GeoIP_country_code_by_ipnum_v6(geoip_v6, ga);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
if ( geoip && a->AsAddr().GetFamily() == IPv4 )
|
||||
{
|
||||
const uint32* bytes;
|
||||
a->AsAddr().GetBytes(&bytes);
|
||||
if ( have_city_db )
|
||||
gir = GeoIP_record_by_ipnum(geoip, ntohl(*bytes));
|
||||
else
|
||||
cc = GeoIP_country_code_by_ipnum(geoip, ntohl(*bytes));
|
||||
}
|
||||
|
||||
if ( gir )
|
||||
{
|
||||
if ( gir->country_code )
|
||||
location->Assign(0, new StringVal(gir->country_code));
|
||||
|
||||
if ( gir->region )
|
||||
location->Assign(1, new StringVal(gir->region));
|
||||
|
||||
if ( gir->city )
|
||||
location->Assign(2, new StringVal(gir->city));
|
||||
|
||||
if ( gir->latitude )
|
||||
location->Assign(3, new Val(gir->latitude,
|
||||
TYPE_DOUBLE));
|
||||
|
||||
if ( gir->longitude )
|
||||
location->Assign(4, new Val(gir->longitude,
|
||||
TYPE_DOUBLE));
|
||||
|
||||
GeoIPRecord_delete(gir);
|
||||
|
||||
builtin_error("Failed to open GeoIP location database");
|
||||
return location;
|
||||
}
|
||||
}
|
||||
|
||||
else if ( cc )
|
||||
MMDB_lookup_result_s result;
|
||||
|
||||
if ( mmdb_lookup_loc(a->AsAddr(), result) )
|
||||
{
|
||||
location->Assign(0, new StringVal(cc));
|
||||
MMDB_entry_data_s entry_data;
|
||||
int status;
|
||||
|
||||
// Get Country ISO Code
|
||||
status = MMDB_get_value(&result.entry, &entry_data,
|
||||
"country", "iso_code", nullptr);
|
||||
location->Assign(0, mmdb_getvalue(&entry_data, status,
|
||||
MMDB_DATA_TYPE_UTF8_STRING));
|
||||
|
||||
// Get Major Subdivision ISO Code
|
||||
status = MMDB_get_value(&result.entry, &entry_data,
|
||||
"subdivisions", "0", "iso_code", nullptr);
|
||||
location->Assign(1, mmdb_getvalue(&entry_data, status,
|
||||
MMDB_DATA_TYPE_UTF8_STRING));
|
||||
|
||||
// Get City English Name
|
||||
status = MMDB_get_value(&result.entry, &entry_data,
|
||||
"city", "names", "en", nullptr);
|
||||
location->Assign(2, mmdb_getvalue(&entry_data, status,
|
||||
MMDB_DATA_TYPE_UTF8_STRING));
|
||||
|
||||
// Get Location Latitude
|
||||
status = MMDB_get_value(&result.entry, &entry_data,
|
||||
"location", "latitude", nullptr);
|
||||
location->Assign(3, mmdb_getvalue(&entry_data, status,
|
||||
MMDB_DATA_TYPE_DOUBLE));
|
||||
|
||||
// Get Location Longitude
|
||||
status = MMDB_get_value(&result.entry, &entry_data,
|
||||
"location", "longitude", nullptr);
|
||||
location->Assign(4, mmdb_getvalue(&entry_data, status,
|
||||
MMDB_DATA_TYPE_DOUBLE));
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
|
@ -3792,64 +3932,45 @@ function lookup_location%(a: addr%) : geo_location
|
|||
}
|
||||
#endif
|
||||
|
||||
// We can get here even if we have GeoIP support if we weren't
|
||||
// We can get here even if we have MMDB support if we weren't
|
||||
// able to initialize it or it didn't return any information for
|
||||
// the address.
|
||||
|
||||
return location;
|
||||
%}
|
||||
|
||||
## Performs an AS lookup of an IP address.
|
||||
## Requires Bro to be built with ``libgeoip``.
|
||||
## Performs an ASN lookup of an IP address.
|
||||
## Requires Bro to be built with ``libmaxminddb``.
|
||||
##
|
||||
## a: The IP address to lookup.
|
||||
##
|
||||
## Returns: The number of the AS that contains *a*.
|
||||
## Returns: The number of the ASN that contains *a*.
|
||||
##
|
||||
## .. bro:see:: lookup_location
|
||||
function lookup_asn%(a: addr%) : count
|
||||
%{
|
||||
#ifdef USE_GEOIP
|
||||
static GeoIP* geoip_asn = 0;
|
||||
static bool geoip_asn_initialized = false;
|
||||
char* gir = 0;
|
||||
|
||||
if ( ! geoip_asn_initialized )
|
||||
if ( ! mmdb_asn )
|
||||
{
|
||||
geoip_asn_initialized = true;
|
||||
geoip_asn = open_geoip_db(GEOIP_ASNUM_EDITION);
|
||||
|
||||
if ( ! geoip_asn )
|
||||
builtin_error(fmt("Can't open GeoIP ASNUM database: %s",
|
||||
GeoIPDBFileName[GEOIP_ASNUM_EDITION]));
|
||||
}
|
||||
|
||||
if ( geoip_asn )
|
||||
if ( ! mmdb_try_open_asn() )
|
||||
{
|
||||
// IPv6 support showed up in 1.4.5.
|
||||
#ifdef HAVE_GEOIP_COUNTRY_EDITION_V6
|
||||
if ( a->AsAddr().GetFamily() == IPv6 )
|
||||
{
|
||||
geoipv6_t ga;
|
||||
a->AsAddr().CopyIPv6(&ga);
|
||||
gir = GeoIP_name_by_ipnum_v6(geoip_asn, ga);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
if ( a->AsAddr().GetFamily() == IPv4 )
|
||||
{
|
||||
const uint32* bytes;
|
||||
a->AsAddr().GetBytes(&bytes);
|
||||
gir = GeoIP_name_by_ipnum(geoip_asn, ntohl(*bytes));
|
||||
builtin_error("No open GeoIP ASN database");
|
||||
return new Val(0, TYPE_COUNT);
|
||||
}
|
||||
}
|
||||
|
||||
if ( gir )
|
||||
MMDB_lookup_result_s result;
|
||||
|
||||
if ( mmdb_lookup_asn(a->AsAddr(), result) )
|
||||
{
|
||||
// Move the pointer +2 so we don't return
|
||||
// the first two characters: "AS".
|
||||
return new Val(atoi(gir+2), TYPE_COUNT);
|
||||
MMDB_entry_data_s entry_data;
|
||||
int status;
|
||||
|
||||
// Get Autonomous System Number
|
||||
status = MMDB_get_value(&result.entry, &entry_data,
|
||||
"autonomous_system_number", nullptr);
|
||||
Val* asn = mmdb_getvalue(&entry_data, status, MMDB_DATA_TYPE_UINT32);
|
||||
return asn == nullptr ? new Val(0, TYPE_COUNT) : asn;
|
||||
}
|
||||
|
||||
#else // not USE_GEOIP
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue