Skip to content

Commit

Permalink
header_rewrite: allow for use of maxminddb as source of geo truth
Browse files Browse the repository at this point in the history
  • Loading branch information
randall committed Apr 9, 2021
1 parent a5a8523 commit 20ef2aa
Show file tree
Hide file tree
Showing 11 changed files with 456 additions and 195 deletions.
10 changes: 7 additions & 3 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -1697,12 +1697,16 @@ AC_SUBST(use_hwloc)
#
AC_CHECK_HEADERS([GeoIP.h], [
AC_CHECK_LIB([GeoIP], [GeoIP_new], [
AC_SUBST([GEO_LIBS], ["-lGeoIP"])
AC_SUBST([GEOIP_LIBS], ["-lGeoIP"])
AC_SUBST(has_geoip, 1)
], [
AC_SUBST([GEO_LIBS], [""])
AC_SUBST([GEOIP_LIBS], [""])
AC_SUBST(has_geoip, 0)
])
])

AM_CONDITIONAL([HAS_GEOIP], [test "x${has_geoip}" = "x1" ])

#
# Check for libmaxmind. This is the maxmind v2 API where GeoIP is the legacy
# v1 dat file based API
Expand All @@ -1717,7 +1721,7 @@ AC_CHECK_HEADERS([maxminddb.h], [
])
])

AM_CONDITIONAL([BUILD_MAXMIND_ACL_PLUGIN], [test "x${has_maxmind}" = "x1" ])
AM_CONDITIONAL([HAS_MAXMINDDB], [test "x${has_maxmind}" = "x1" ])

# Right now, the healthcheck plugins requires inotify_init (and friends)
AM_CONDITIONAL([BUILD_HEALTHCHECK_PLUGIN], [ test "$ac_cv_func_inotify_init" = "yes" ])
Expand Down
4 changes: 3 additions & 1 deletion plugins/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ include esi/Makefile.inc
include generator/Makefile.inc
include compress/Makefile.inc
include header_rewrite/Makefile.inc
if BUILD_HEALTHCHECK_PLUGIN
include healthchecks/Makefile.inc
endif
include libloader/Makefile.inc
if HAS_LUAJIT
include lua/Makefile.inc
Expand Down Expand Up @@ -70,7 +72,7 @@ include experimental/hook-trace/Makefile.inc
include experimental/icap/Makefile.inc
include experimental/inliner/Makefile.inc

if BUILD_MAXMIND_ACL_PLUGIN
if HAS_MAXMINDDB
include experimental/maxmind_acl/Makefile.inc
endif

Expand Down
2 changes: 1 addition & 1 deletion plugins/experimental/geoip_acl/Makefile.inc
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ experimental_geoip_acl_geoip_acl_la_SOURCES = \
experimental/geoip_acl/acl.cc \
experimental/geoip_acl/geoip_acl.cc

experimental_geoip_acl_geoip_acl_la_LIBADD = $(GEO_LIBS)
experimental_geoip_acl_geoip_acl_la_LIBADD = $(GEOIP_LIBS)
26 changes: 24 additions & 2 deletions plugins/header_rewrite/Makefile.inc
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,38 @@ header_rewrite_header_rewrite_la_SOURCES = \
header_rewrite/value.cc \
header_rewrite/value.h

if HAS_MAXMINDDB
header_rewrite_header_rewrite_la_SOURCES += header_rewrite/conditions_geo_maxmind.cc
endif

if HAS_GEOIP
header_rewrite_header_rewrite_la_SOURCES += header_rewrite/conditions_geo_geoip.cc
endif

header_rewrite_parser_la_SOURCES = \
header_rewrite/parser.cc \
header_rewrite/parser.h

header_rewrite_header_rewrite_la_LIBADD = \
header_rewrite/parser.la \
$(GEO_LIBS)
header_rewrite/parser.la

if HAS_GEOIP
header_rewrite_header_rewrite_la_LIBADD += $(GEOIP_LIBS)
endif

if HAS_MAXMINDDB
header_rewrite_header_rewrite_la_LIBADD += $(MAXMINDDB_LIBS)
endif

check_PROGRAMS += header_rewrite/header_rewrite_test
header_rewrite_header_rewrite_test_SOURCES = \
header_rewrite/header_rewrite_test.cc
header_rewrite_header_rewrite_test_LDADD = \
header_rewrite/parser.la
if HAS_GEOIP
header_rewrite_header_rewrite_test_LDADD += $(GEOIP_LIBS)
endif

if HAS_MAXMINDDB
header_rewrite_header_rewrite_test_LDADD += $(MAXMINDDB_LIBS)
endif
153 changes: 9 additions & 144 deletions plugins/header_rewrite/conditions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@
See the License for the specific language governing permissions and
limitations under the License.
*/

//////////////////////////////////////////////////////////////////////////////////////////////
// conditions.cc: Implementation of the condition classes
//
//

#include <sys/time.h>
#include <unistd.h>
#include <arpa/inet.h>
Expand Down Expand Up @@ -740,151 +742,9 @@ ConditionNow::eval(const Resources &res)
return static_cast<const MatcherType *>(_matcher)->test(now);
}

// ConditionGeo: Geo-based information (integer). See ConditionGeoCountry for the string version.
#if HAVE_GEOIP_H
const char *
ConditionGeo::get_geo_string(const sockaddr *addr) const
{
const char *ret = "(unknown)";
int v = 4;

if (addr) {
switch (_geo_qual) {
// Country database
case GEO_QUAL_COUNTRY:
switch (addr->sa_family) {
case AF_INET:
if (gGeoIP[GEOIP_COUNTRY_EDITION]) {
uint32_t ip = ntohl(reinterpret_cast<const struct sockaddr_in *>(addr)->sin_addr.s_addr);

ret = GeoIP_country_code_by_ipnum(gGeoIP[GEOIP_COUNTRY_EDITION], ip);
}
break;
case AF_INET6: {
if (gGeoIP[GEOIP_COUNTRY_EDITION_V6]) {
geoipv6_t ip = reinterpret_cast<const struct sockaddr_in6 *>(addr)->sin6_addr;

v = 6;
ret = GeoIP_country_code_by_ipnum_v6(gGeoIP[GEOIP_COUNTRY_EDITION_V6], ip);
}
} break;
default:
break;
}
TSDebug(PLUGIN_NAME, "eval(): Client IPv%d seems to come from Country: %s", v, ret);
break;

// ASN database
case GEO_QUAL_ASN_NAME:
switch (addr->sa_family) {
case AF_INET:
if (gGeoIP[GEOIP_ASNUM_EDITION]) {
uint32_t ip = ntohl(reinterpret_cast<const struct sockaddr_in *>(addr)->sin_addr.s_addr);

ret = GeoIP_name_by_ipnum(gGeoIP[GEOIP_ASNUM_EDITION], ip);
}
break;
case AF_INET6: {
if (gGeoIP[GEOIP_ASNUM_EDITION_V6]) {
geoipv6_t ip = reinterpret_cast<const struct sockaddr_in6 *>(addr)->sin6_addr;

v = 6;
ret = GeoIP_name_by_ipnum_v6(gGeoIP[GEOIP_ASNUM_EDITION_V6], ip);
}
} break;
default:
break;
}
TSDebug(PLUGIN_NAME, "eval(): Client IPv%d seems to come from ASN Name: %s", v, ret);
break;

default:
break;
}
}

return ret ? ret : "(unknown)";
}

int64_t
ConditionGeo::get_geo_int(const sockaddr *addr) const
{
int64_t ret = -1;
int v = 4;

if (!addr) {
return 0;
}

switch (_geo_qual) {
// Country Database
case GEO_QUAL_COUNTRY_ISO:
switch (addr->sa_family) {
case AF_INET:
if (gGeoIP[GEOIP_COUNTRY_EDITION]) {
uint32_t ip = ntohl(reinterpret_cast<const struct sockaddr_in *>(addr)->sin_addr.s_addr);

ret = GeoIP_id_by_ipnum(gGeoIP[GEOIP_COUNTRY_EDITION], ip);
}
break;
case AF_INET6: {
if (gGeoIP[GEOIP_COUNTRY_EDITION_V6]) {
geoipv6_t ip = reinterpret_cast<const struct sockaddr_in6 *>(addr)->sin6_addr;

v = 6;
ret = GeoIP_id_by_ipnum_v6(gGeoIP[GEOIP_COUNTRY_EDITION_V6], ip);
}
} break;
default:
break;
}
TSDebug(PLUGIN_NAME, "eval(): Client IPv%d seems to come from Country ISO: %" PRId64, v, ret);
break;

case GEO_QUAL_ASN: {
const char *asn_name = nullptr;

switch (addr->sa_family) {
case AF_INET:
if (gGeoIP[GEOIP_ASNUM_EDITION]) {
uint32_t ip = ntohl(reinterpret_cast<const struct sockaddr_in *>(addr)->sin_addr.s_addr);

asn_name = GeoIP_name_by_ipnum(gGeoIP[GEOIP_ASNUM_EDITION], ip);
}
break;
case AF_INET6:
if (gGeoIP[GEOIP_ASNUM_EDITION_V6]) {
geoipv6_t ip = reinterpret_cast<const struct sockaddr_in6 *>(addr)->sin6_addr;

v = 6;
asn_name = GeoIP_name_by_ipnum_v6(gGeoIP[GEOIP_ASNUM_EDITION_V6], ip);
}
break;
}
if (asn_name) {
// This is a little odd, but the strings returned are e.g. "AS1234 Acme Inc"
while (*asn_name && !(isdigit(*asn_name))) {
++asn_name;
}
ret = strtol(asn_name, nullptr, 10);
}
}
TSDebug(PLUGIN_NAME, "eval(): Client IPv%d seems to come from ASN #: %" PRId64, v, ret);
break;

// Likely shouldn't trip, should we assert?
default:
break;
}

return ret;
}

#else

#ifndef HAVE_GEO_LIB
// No Geo library available, these are just stubs.

const char *
std::string
ConditionGeo::get_geo_string(const sockaddr *addr) const
{
TSError("[%s] No Geo library available!", PLUGIN_NAME);
Expand All @@ -898,6 +758,11 @@ ConditionGeo::get_geo_int(const sockaddr *addr) const
return 0;
}

void
ConditionGeo::initLibrary(const std::string &path)
{
TSError("[%s] No Geo library available!", PLUGIN_NAME);
}
#endif

void
Expand Down
12 changes: 11 additions & 1 deletion plugins/header_rewrite/conditions.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@
#include "lulu.h"
//#include <mdbm.h>

#if HAVE_GEOIP_H
#define HAVE_GEO_LIB 1
#endif

#if HAVE_MAXMINDDB_H
#define HAVE_GEO_LIB 1
#endif

///////////////////////////////////////////////////////////////////////////////
// Condition declarations.
//
Expand Down Expand Up @@ -424,6 +432,8 @@ class ConditionGeo : public Condition
void set_qualifier(const std::string &q) override;
void append_value(std::string &s, const Resources &res) override;

static void initLibrary(const std::string &path);

// Make sure we know if the type is an int-type or a string.
bool
is_int_type() const
Expand All @@ -442,7 +452,7 @@ class ConditionGeo : public Condition

private:
int64_t get_geo_int(const sockaddr *addr) const;
const char *get_geo_string(const sockaddr *addr) const;
std::string get_geo_string(const sockaddr *addr) const;
GeoQualifiers _geo_qual = GEO_QUAL_COUNTRY;
bool _int_type = false;
};
Expand Down
Loading

0 comments on commit 20ef2aa

Please sign in to comment.