mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Merge branch 'topic/feature/upstream/geoip' of https://github.com/corelight/bro
* 'topic/feature/upstream/geoip' of https://github.com/corelight/bro: Replace GeoIP Legacy DB support with MaxMind DB support
This commit is contained in:
commit
a71d84c968
7 changed files with 363 additions and 228 deletions
|
@ -140,11 +140,11 @@ include_directories(BEFORE
|
||||||
# Optional Dependencies
|
# Optional Dependencies
|
||||||
|
|
||||||
set(USE_GEOIP false)
|
set(USE_GEOIP false)
|
||||||
find_package(LibGeoIP)
|
find_package(LibMMDB)
|
||||||
if (LIBGEOIP_FOUND)
|
if (LibMMDB_FOUND)
|
||||||
set(USE_GEOIP true)
|
set(USE_GEOIP true)
|
||||||
include_directories(BEFORE ${LibGeoIP_INCLUDE_DIR})
|
include_directories(BEFORE ${LibMMDB_INCLUDE_DIR})
|
||||||
list(APPEND OPTLIBS ${LibGeoIP_LIBRARY})
|
list(APPEND OPTLIBS ${LibMMDB_LIBRARY})
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
set(USE_KRB5 false)
|
set(USE_KRB5 false)
|
||||||
|
@ -327,7 +327,7 @@ message(
|
||||||
"\nBroctl: ${INSTALL_BROCTL}"
|
"\nBroctl: ${INSTALL_BROCTL}"
|
||||||
"\nAux. Tools: ${INSTALL_AUX_TOOLS}"
|
"\nAux. Tools: ${INSTALL_AUX_TOOLS}"
|
||||||
"\n"
|
"\n"
|
||||||
"\nGeoIP: ${USE_GEOIP}"
|
"\nlibmaxminddb: ${USE_GEOIP}"
|
||||||
"\nKerberos: ${USE_KRB5}"
|
"\nKerberos: ${USE_KRB5}"
|
||||||
"\ngperftools found: ${HAVE_PERFTOOLS}"
|
"\ngperftools found: ${HAVE_PERFTOOLS}"
|
||||||
"\n tcmalloc: ${USE_PERFTOOLS_TCMALLOC}"
|
"\n tcmalloc: ${USE_PERFTOOLS_TCMALLOC}"
|
||||||
|
|
9
NEWS
9
NEWS
|
@ -358,6 +358,15 @@ Changed Functionality
|
||||||
- The string_to_pattern() built-in (and the now-deprecated merge_pattern()
|
- 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.
|
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
|
Removed Functionality
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
|
|
@ -111,12 +111,6 @@
|
||||||
/* Define if KRB5 is available */
|
/* Define if KRB5 is available */
|
||||||
#cmakedefine USE_KRB5
|
#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 */
|
/* Use Google's perftools */
|
||||||
#cmakedefine USE_PERFTOOLS_DEBUG
|
#cmakedefine USE_PERFTOOLS_DEBUG
|
||||||
|
|
||||||
|
|
4
configure
vendored
4
configure
vendored
|
@ -72,7 +72,7 @@ Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
(a required Broker dependency)
|
(a required Broker dependency)
|
||||||
|
|
||||||
Optional Packages in Non-Standard Locations:
|
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-krb5=PATH path to krb5 install root
|
||||||
--with-perftools=PATH path to Google Perftools install root
|
--with-perftools=PATH path to Google Perftools install root
|
||||||
--with-jemalloc=PATH path to jemalloc 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
|
append_cache_entry BISON_EXECUTABLE PATH $optarg
|
||||||
;;
|
;;
|
||||||
--with-geoip=*)
|
--with-geoip=*)
|
||||||
append_cache_entry LibGeoIP_ROOT_DIR PATH $optarg
|
append_cache_entry LibMMDB_ROOT_DIR PATH $optarg
|
||||||
;;
|
;;
|
||||||
--with-krb5=*)
|
--with-krb5=*)
|
||||||
append_cache_entry LibKrb5_ROOT_DIR PATH $optarg
|
append_cache_entry LibKrb5_ROOT_DIR PATH $optarg
|
||||||
|
|
|
@ -8,11 +8,13 @@ GeoLocation
|
||||||
.. rst-class:: opening
|
.. rst-class:: opening
|
||||||
|
|
||||||
During the process of creating policy scripts the need may arise
|
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
|
for the `GeoIP library <http://www.maxmind.com/app/c>`__ at the
|
||||||
policy script level beginning with release 1.3 to account for this
|
policy script level from release 1.3 to 2.5.X to account for this
|
||||||
need. To use this functionality, you need to first install the libGeoIP
|
need. Starting with release 2.6 GeoIP support requires `libmaxminddb
|
||||||
software, and then install the GeoLite city database before building
|
<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.
|
Bro.
|
||||||
|
|
||||||
.. contents::
|
.. contents::
|
||||||
|
@ -20,85 +22,91 @@ GeoLocation
|
||||||
Install libGeoIP
|
Install libGeoIP
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
Before building Bro, you need to install libGeoIP.
|
Before building Bro, you need to install libmaxminddb.
|
||||||
|
|
||||||
* FreeBSD:
|
* FreeBSD:
|
||||||
|
|
||||||
.. console::
|
.. console::
|
||||||
|
|
||||||
sudo pkg install GeoIP
|
sudo pkg install libmaxminddb
|
||||||
|
|
||||||
* RPM/RedHat-based Linux:
|
* RPM/RedHat-based Linux:
|
||||||
|
|
||||||
.. console::
|
.. console::
|
||||||
|
|
||||||
sudo yum install GeoIP-devel
|
sudo yum install libmaxminddb-devel
|
||||||
|
|
||||||
* DEB/Debian-based Linux:
|
* DEB/Debian-based Linux:
|
||||||
|
|
||||||
.. console::
|
.. console::
|
||||||
|
|
||||||
sudo apt-get install libgeoip-dev
|
sudo apt-get install libmaxminddb-dev
|
||||||
|
|
||||||
* Mac OS X:
|
* Mac OS X:
|
||||||
|
|
||||||
You need to install from your preferred package management system
|
You need to install from your preferred package management system
|
||||||
(e.g. MacPorts, Fink, or Homebrew). The name of the package that you need
|
(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
|
may be libmaxminddb, maxminddb, or libmaxminddb-dev, depending on which
|
||||||
system you are using.
|
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
|
Bro can use the city or country database. The city database includes cities
|
||||||
install, but for Bro, we are using the city database which includes
|
and regions in addition to countries.
|
||||||
cities and regions in addition to countries.
|
|
||||||
|
|
||||||
`Download <http://www.maxmind.com/app/geolitecity>`__ the GeoLite city
|
`Download <http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz>`__
|
||||||
binary database:
|
the GeoLite2 city binary database:
|
||||||
|
|
||||||
.. console::
|
.. console::
|
||||||
|
|
||||||
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
|
wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz
|
||||||
gunzip GeoLiteCity.dat.gz
|
tar zxf GeoLite2-City.tar.gz
|
||||||
|
|
||||||
Next, the file needs to be renamed and put in the GeoIP database directory.
|
Next, the file "GeoLite2-City_YYYYMMDD/GeoLite2-City.mmdb" needs to be renamed
|
||||||
This directory should already exist and will vary depending on which platform
|
and put in the GeoIP database directory. This directory should already exist
|
||||||
and package you are using. For FreeBSD, use ``/usr/local/share/GeoIP``. For
|
and will vary depending on which platform and package you are using. For
|
||||||
Linux, use ``/usr/share/GeoIP`` or ``/var/lib/GeoIP`` (choose whichever one
|
FreeBSD, use ``/usr/local/share/GeoIP``. For Linux, use ``/usr/share/GeoIP``
|
||||||
already exists).
|
or ``/var/lib/GeoIP`` (choose whichever one already exists).
|
||||||
|
|
||||||
.. console::
|
.. console::
|
||||||
|
|
||||||
mv GeoLiteCity.dat <path_to_database_dir>/GeoIPCity.dat
|
mv <extracted subdir>/GeoLite2-City.mmdb <path_to_database_dir>/GeoLite2-City.mmdb
|
||||||
|
|
||||||
Note that there is a separate database for IPv6 addresses, which can also
|
|
||||||
be installed if you want GeoIP functionality for IPv6.
|
|
||||||
|
|
||||||
Testing
|
Testing
|
||||||
-------
|
-------
|
||||||
|
|
||||||
Before using the GeoIP functionality, it is a good idea to verify that
|
Before using the GeoIP functionality, it is a good idea to verify that
|
||||||
everything is setup correctly. After installing libGeoIP and the GeoIP city
|
everything is setup correctly. After installing libmaxminddb and the GeoIP
|
||||||
database, and building Bro, you can quickly check if the GeoIP functionality
|
city database, and building Bro, you can quickly check if the GeoIP
|
||||||
works by running a command like this:
|
functionality works by running a command like this:
|
||||||
|
|
||||||
.. console::
|
.. console::
|
||||||
|
|
||||||
bro -e "print lookup_location(8.8.8.8);"
|
bro -e "print lookup_location(8.8.8.8);"
|
||||||
|
|
||||||
If you see an error message similar to "Failed to open GeoIP City database",
|
If you see an error message similar to "Failed to open GeoIP location
|
||||||
then you may need to either rename or move your GeoIP city database file (the
|
database", then you may need to either rename or move your GeoIP
|
||||||
error message should give you the full pathname of the database file that
|
location database file. Bro looks for location database files in the
|
||||||
Bro is looking for).
|
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
|
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
|
support", then you either need to rebuild Bro and make sure it is linked
|
||||||
libGeoIP. Normally, if libGeoIP is installed correctly then it should
|
against libmaxminddb or else set the :bro:see:`mmdb_dir`` value
|
||||||
automatically be found when building Bro. If this doesn't happen, then
|
correctly. Normally, if libmaxminddb is installed correctly then it
|
||||||
you may need to specify the path to the libGeoIP installation
|
should automatically be found when building Bro. If this doesn't
|
||||||
(e.g. ``./configure --with-geoip=<path>``).
|
happen, then you may need to specify the path to the libmaxminddb
|
||||||
|
installation (e.g. ``./configure --with-geoip=<path>``).
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
|
|
|
@ -872,6 +872,9 @@ type geo_location: record {
|
||||||
longitude: double &optional; ##< Longitude.
|
longitude: double &optional; ##< Longitude.
|
||||||
} &log;
|
} &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 entropy values. The record captures a number of measures that are
|
||||||
## computed in parallel. See `A Pseudorandom Number Sequence Test Program
|
## computed in parallel. See `A Pseudorandom Number Sequence Test Program
|
||||||
## <http://www.fourmilab.ch/random>`_ for more information, Bro uses the same
|
## <http://www.fourmilab.ch/random>`_ for more information, Bro uses the same
|
||||||
|
|
471
src/bro.bif
471
src/bro.bif
|
@ -3599,77 +3599,269 @@ function lookup_hostname%(host: string%) : addr_set
|
||||||
%%{
|
%%{
|
||||||
#ifdef USE_GEOIP
|
#ifdef USE_GEOIP
|
||||||
extern "C" {
|
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) )
|
if ( MMDB_SUCCESS != status )
|
||||||
geoip = GeoIP_open_type(type, GEOIP_MEMORY_CACHE);
|
{
|
||||||
|
throw std::runtime_error(MMDB_strerror(status));
|
||||||
return geoip;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GeoIP* open_geoip_city_db()
|
MMDB::~MMDB()
|
||||||
{
|
{
|
||||||
GeoIP* geoip = open_geoip_db(GEOIP_CITY_EDITION_REV0);
|
MMDB_close(&mmdb);
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
return geoip;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GeoIP* open_geoip_city_db_v6()
|
MMDB_lookup_result_s MMDB::Lookup(const struct sockaddr* const sa)
|
||||||
{
|
{
|
||||||
GeoIP* geoip = 0;
|
int mmdb_error;
|
||||||
|
MMDB_lookup_result_s result = MMDB_lookup_sockaddr(&mmdb, sa, &mmdb_error);
|
||||||
|
|
||||||
// Both city edition revisions for IPv6 show up in libGeoIP 1.4.7.
|
if ( MMDB_SUCCESS != mmdb_error )
|
||||||
#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];
|
throw std::runtime_error(MMDB_strerror(mmdb_error));
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return geoip;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
#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.
|
## 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.
|
## a: The IP address to lookup.
|
||||||
##
|
##
|
||||||
|
@ -3681,104 +3873,52 @@ function lookup_location%(a: addr%) : geo_location
|
||||||
RecordVal* location = new RecordVal(geo_location);
|
RecordVal* location = new RecordVal(geo_location);
|
||||||
|
|
||||||
#ifdef USE_GEOIP
|
#ifdef USE_GEOIP
|
||||||
static bool geoip_initialized = false;
|
if ( ! mmdb_loc )
|
||||||
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 )
|
|
||||||
{
|
{
|
||||||
geoip_initialized = true;
|
if ( ! mmdb_try_open_loc() )
|
||||||
geoip = open_geoip_city_db();
|
|
||||||
|
|
||||||
if ( ! geoip )
|
|
||||||
{
|
{
|
||||||
geoip = open_geoip_db(GEOIP_COUNTRY_EDITION);
|
builtin_error("Failed to open GeoIP location database");
|
||||||
string db_path = GeoIPDBFileName[GEOIP_COUNTRY_EDITION];
|
return location;
|
||||||
|
|
||||||
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
|
MMDB_lookup_result_s result;
|
||||||
if ( geoip_v6 && a->AsAddr().GetFamily() == IPv6 )
|
|
||||||
|
if ( mmdb_lookup_loc(a->AsAddr(), result) )
|
||||||
{
|
{
|
||||||
geoipv6_t ga;
|
MMDB_entry_data_s entry_data;
|
||||||
a->AsAddr().CopyIPv6(&ga);
|
int status;
|
||||||
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 )
|
// Get Country ISO Code
|
||||||
{
|
status = MMDB_get_value(&result.entry, &entry_data,
|
||||||
const uint32* bytes;
|
"country", "iso_code", nullptr);
|
||||||
a->AsAddr().GetBytes(&bytes);
|
location->Assign(0, mmdb_getvalue(&entry_data, status,
|
||||||
if ( have_city_db )
|
MMDB_DATA_TYPE_UTF8_STRING));
|
||||||
gir = GeoIP_record_by_ipnum(geoip, ntohl(*bytes));
|
|
||||||
else
|
|
||||||
cc = GeoIP_country_code_by_ipnum(geoip, ntohl(*bytes));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( gir )
|
// Get Major Subdivision ISO Code
|
||||||
{
|
status = MMDB_get_value(&result.entry, &entry_data,
|
||||||
if ( gir->country_code )
|
"subdivisions", "0", "iso_code", nullptr);
|
||||||
location->Assign(0, new StringVal(gir->country_code));
|
location->Assign(1, mmdb_getvalue(&entry_data, status,
|
||||||
|
MMDB_DATA_TYPE_UTF8_STRING));
|
||||||
|
|
||||||
if ( gir->region )
|
// Get City English Name
|
||||||
location->Assign(1, new StringVal(gir->region));
|
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));
|
||||||
|
|
||||||
if ( gir->city )
|
// Get Location Latitude
|
||||||
location->Assign(2, new StringVal(gir->city));
|
status = MMDB_get_value(&result.entry, &entry_data,
|
||||||
|
"location", "latitude", nullptr);
|
||||||
|
location->Assign(3, mmdb_getvalue(&entry_data, status,
|
||||||
|
MMDB_DATA_TYPE_DOUBLE));
|
||||||
|
|
||||||
if ( gir->latitude )
|
// Get Location Longitude
|
||||||
location->Assign(3, new Val(gir->latitude,
|
status = MMDB_get_value(&result.entry, &entry_data,
|
||||||
TYPE_DOUBLE));
|
"location", "longitude", nullptr);
|
||||||
|
location->Assign(4, mmdb_getvalue(&entry_data, status,
|
||||||
|
MMDB_DATA_TYPE_DOUBLE));
|
||||||
|
|
||||||
if ( gir->longitude )
|
|
||||||
location->Assign(4, new Val(gir->longitude,
|
|
||||||
TYPE_DOUBLE));
|
|
||||||
|
|
||||||
GeoIPRecord_delete(gir);
|
|
||||||
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if ( cc )
|
|
||||||
{
|
|
||||||
location->Assign(0, new StringVal(cc));
|
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3792,64 +3932,45 @@ function lookup_location%(a: addr%) : geo_location
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
// able to initialize it or it didn't return any information for
|
||||||
// the address.
|
// the address.
|
||||||
|
|
||||||
return location;
|
return location;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
## Performs an AS lookup of an IP address.
|
## Performs an ASN 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.
|
## 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
|
## .. bro:see:: lookup_location
|
||||||
function lookup_asn%(a: addr%) : count
|
function lookup_asn%(a: addr%) : count
|
||||||
%{
|
%{
|
||||||
#ifdef USE_GEOIP
|
#ifdef USE_GEOIP
|
||||||
static GeoIP* geoip_asn = 0;
|
if ( ! mmdb_asn )
|
||||||
static bool geoip_asn_initialized = false;
|
|
||||||
char* gir = 0;
|
|
||||||
|
|
||||||
if ( ! geoip_asn_initialized )
|
|
||||||
{
|
{
|
||||||
geoip_asn_initialized = true;
|
if ( ! mmdb_try_open_asn() )
|
||||||
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 )
|
|
||||||
{
|
|
||||||
// IPv6 support showed up in 1.4.5.
|
|
||||||
#ifdef HAVE_GEOIP_COUNTRY_EDITION_V6
|
|
||||||
if ( a->AsAddr().GetFamily() == IPv6 )
|
|
||||||
{
|
{
|
||||||
geoipv6_t ga;
|
builtin_error("No open GeoIP ASN database");
|
||||||
a->AsAddr().CopyIPv6(&ga);
|
return new Val(0, TYPE_COUNT);
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( gir )
|
MMDB_lookup_result_s result;
|
||||||
|
|
||||||
|
if ( mmdb_lookup_asn(a->AsAddr(), result) )
|
||||||
{
|
{
|
||||||
// Move the pointer +2 so we don't return
|
MMDB_entry_data_s entry_data;
|
||||||
// the first two characters: "AS".
|
int status;
|
||||||
return new Val(atoi(gir+2), TYPE_COUNT);
|
|
||||||
|
// 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
|
#else // not USE_GEOIP
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue