Fixes for GeoIP support (addresses #538).

- Missing GeoIP databases now generate warnings/errors that go through
  the reporter framework instead of hitting GeoIP's internal use of
  stderr

- lookup_location now just queries for country code if the city database
  was not loaded, which gets rid of invalid database type errors.

- lookup_location now leaves missing fields uninitialized in the
  returned geo_location record value.  Updated existing scripts to
  check for initialized fields in geo_location records before use.

- Fixed support for GeoIP's IPv6 API and databases
This commit is contained in:
Jon Siwek 2011-08-30 17:02:07 -05:00
parent 005b1505b8
commit 13a09aa488
5 changed files with 99 additions and 43 deletions

View file

@ -16,6 +16,8 @@
# LIBGEOIP_FOUND System has GeoIP libraries and headers
# LibGeoIP_LIBRARY The GeoIP library
# LibGeoIP_INCLUDE_DIR The location of GeoIP headers
# HAVE_GEOIP_COUNTRY_EDITION_V6 Whether the API support IPv6 country edition
# HAVE_GEOIP_CITY_EDITION_REV0_V6 Whether the API supports IPv6 city edition
find_path(LibGeoIP_ROOT_DIR
NAMES include/GeoIPCity.h
@ -45,6 +47,20 @@ find_package_handle_standard_args(LibGeoIP DEFAULT_MSG
LibGeoIP_INCLUDE_DIR
)
if (LIBGEOIP_FOUND)
include(CheckCXXSourceCompiles)
set(CMAKE_REQUIRED_INCLUDES ${LibGeoIP_INCLUDE_DIR})
check_cxx_source_compiles("
#include <GeoIPCity.h>
int main() { GEOIP_COUNTRY_EDITION_V6; return 0; }
" HAVE_GEOIP_COUNTRY_EDITION_V6)
check_cxx_source_compiles("
#include <GeoIPCity.h>
int main() { GEOIP_CITY_EDITION_REV0_V6; return 0; }
" HAVE_GEOIP_CITY_EDITION_REV0_V6)
set(CMAKE_REQUIRED_INCLUDES)
endif ()
mark_as_advanced(
LibGeoIP_ROOT_DIR
LibGeoIP_LIBRARY

View file

@ -114,6 +114,12 @@
/* GeoIP geographic lookup functionality */
#cmakedefine USE_GEOIP
/* 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

View file

@ -25,11 +25,13 @@ event log_smtp(rec: Info)
ip = rec$x_originating_ip;
loc = lookup_location(ip);
if ( loc$country_code in suspicious_origination_countries ||
if ( (loc?$country_code &&
loc$country_code in suspicious_origination_countries) ||
ip in suspicious_origination_networks )
{
NOTICE([$note=Suspicious_Origination,
$msg=fmt("An email originated from %s (%s).", loc$country_code, ip),
$msg=fmt("An email originated from %s (%s).",
loc?$country_code ? loc$country_code : "", ip),
$id=rec$id]);
}
}
@ -38,11 +40,12 @@ event log_smtp(rec: Info)
ip = rec$path[|rec$path|-1];
loc = lookup_location(ip);
if ( loc$country_code in suspicious_origination_countries ||
if ( (loc?$country_code &&
loc$country_code in suspicious_origination_countries) ||
ip in suspicious_origination_networks )
{
NOTICE([$note=Suspicious_Origination,
$msg=fmt("Based up Received headers, email originated from %s (%s).", loc$country_code, ip),
$msg=fmt("Based up Received headers, email originated from %s (%s).", loc?$country_code ? loc$country_code : "", ip),
$id=rec$id]);
}
}

View file

@ -33,7 +33,7 @@ event SSH::heuristic_successful_login(c: connection) &priority=5
# Add the location data to the SSH record.
c$ssh$remote_location = location;
if ( location$country_code in watched_countries )
if ( location?$country_code && location$country_code in watched_countries )
{
NOTICE([$note=Login_From_Watched_Country,
$conn=c,

View file

@ -3019,6 +3019,18 @@ function syslog%(s: string%): any
extern "C" {
#include <GeoIPCity.h>
}
static GeoIP* open_geoip_db(GeoIPDBTypes type)
{
GeoIP* geoip = 0;
if ( GeoIP_db_avail(type) )
geoip = GeoIP_open_type(type, GEOIP_MEMORY_CACHE);
if ( ! geoip )
reporter->Warning("Failed to open GeoIP database: %s",
GeoIPDBFileName[type]);
return geoip;
}
#endif
%%}
@ -3031,82 +3043,103 @@ function lookup_location%(a: addr%) : geo_location
static GeoIP* geoip = 0;
static GeoIP* geoip_v6 = 0;
static bool geoip_initialized = false;
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;
geoip = GeoIP_open_type(GEOIP_CITY_EDITION_REV0,
GEOIP_MEMORY_CACHE);
geoip = open_geoip_db(GEOIP_CITY_EDITION_REV0);
if ( ! geoip )
{
builtin_error("can't initialize GeoIP City database.. trying Country version");
geoip = GeoIP_open_type(GEOIP_COUNTRY_EDITION,
GEOIP_MEMORY_CACHE);
geoip = open_geoip_db(GEOIP_COUNTRY_EDITION);
if ( ! geoip )
builtin_error("can't initialize GeoIP Country database");
builtin_error("Can't initialize GeoIP City/Country database");
else
reporter->Warning("Fell back to GeoIP Country database");
}
else
have_city_db = true;
#ifdef BROv6
#ifdef GEOIP_COUNTRY_EDITION_V6
geoip_v6 = GeoIP_open_type(GEOIP_COUNTRY_EDITION_V6,
GEOIP_MEMORY_CACHE);
#ifdef HAVE_GEOIP_CITY_EDITION_REV0_V6
geoip_v6 = open_geoip_db(GEOIP_CITY_EDITION_REV0_V6);
if ( geoip_v6 ) have_cityv6_db = true;
#endif
#ifdef HAVE_GEOIP_COUNTRY_EDITION_V6
if ( ! geoip_v6 )
builtin_error("can't initialize the GeoIPv6 Country database");
geoip_v6 = open_geoip_db(GEOIP_COUNTRY_EDITION_V6);
#endif
if ( ! geoip_v6 )
builtin_error("Can't initialize GeoIPv6 City/Country database");
#endif
}
#ifdef BROv6
#ifdef GEOIP_COUNTRY_EDITION_V6
#ifdef HAVE_GEOIP_COUNTRY_EDITION_V6
if ( geoip_v6 && ! is_v4_addr(a) )
gir = GeoIP_record_by_ipnum_v6(geoip_v6, geoipv6_t(a));
{
geoipv6_t ga;
memcpy(&ga, a, 16);
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 && is_v4_addr(a) )
{
uint32 addr = to_v4_addr(a);
if ( have_city_db )
gir = GeoIP_record_by_ipnum(geoip, ntohl(addr));
else
cc = GeoIP_country_code_by_ipnum(geoip, ntohl(addr));
}
#else
if ( geoip )
{
if ( have_city_db )
gir = GeoIP_record_by_ipnum(geoip, ntohl(a));
else
cc = GeoIP_country_code_by_ipnum(geoip, ntohl(a));
}
#endif
if ( gir )
{
if ( gir->country_code )
location->Assign(0, new StringVal(gir->country_code));
else
location->Assign(0, new StringVal(""));
if ( gir->region )
location->Assign(1, new StringVal(gir->region));
else
location->Assign(1, new StringVal(""));
if ( gir->city )
location->Assign(2, new StringVal(gir->city));
else
location->Assign(2, new StringVal(""));
if ( gir->latitude )
location->Assign(3, new Val(gir->latitude,
TYPE_DOUBLE));
else
location->Assign(3, new Val(0.0, TYPE_DOUBLE));
if ( gir->longitude )
location->Assign(4, new Val(gir->longitude,
TYPE_DOUBLE));
else
location->Assign(4, new Val(0.0, TYPE_DOUBLE));
GeoIPRecord_delete(gir);
return location;
}
else if (cc)
{
location->Assign(0, new StringVal(cc));
return location;
}
#else
static int missing_geoip_reported = 0;
@ -3120,11 +3153,6 @@ function lookup_location%(a: addr%) : geo_location
// We can get here even if we have GeoIP support if we weren't
// able to initialize it or it didn't return any information for
// the address.
location->Assign(0, new StringVal(""));
location->Assign(1, new StringVal(""));
location->Assign(2, new StringVal(""));
location->Assign(3, new Val(0.0, TYPE_DOUBLE));
location->Assign(4, new Val(0.0, TYPE_DOUBLE));
return location;
%}
@ -3139,10 +3167,9 @@ function lookup_asn%(a: addr%) : count
if ( ! geoip_asn_initialized )
{
geoip_asn_initialized = true;
geoip_asn = GeoIP_open_type(GEOIP_ASNUM_EDITION,
GEOIP_MEMORY_CACHE);
geoip_asn = open_geoip_db(GEOIP_ASNUM_EDITION);
if ( ! geoip_asn )
builtin_error("can't initialize GeoIP ASNUM database");
builtin_error("Can't initialize GeoIP ASNUM database");
}
if ( geoip_asn )
@ -3150,9 +3177,13 @@ function lookup_asn%(a: addr%) : count
#ifdef BROv6
// IPv6 support showed up in 1.4.5.
#ifdef GEOIP_COUNTRY_EDITION_V6
#ifdef HAVE_GEOIP_COUNTRY_EDITION_V6
if ( ! is_v4_addr(a) )
gir = GeoIP_name_by_ipnum_v6(geoip_asn, geoipv6_t(a));
{
geoipv6_t ga;
memcpy(&ga, a, 16);
gir = GeoIP_name_by_ipnum_v6(geoip_asn, ga);
}
else
#endif
if ( is_v4_addr(a) )