From d32344d735b978fb7d30a9fcc4ad1141879c5433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Thu, 14 Nov 2013 15:35:43 +0200 Subject: main/varnish: add plugin to do maxmind geoip lookups --- main/varnish/maxminddb.vcl | 76 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 main/varnish/maxminddb.vcl (limited to 'main/varnish/maxminddb.vcl') diff --git a/main/varnish/maxminddb.vcl b/main/varnish/maxminddb.vcl new file mode 100644 index 0000000000..b1cd732232 --- /dev/null +++ b/main/varnish/maxminddb.vcl @@ -0,0 +1,76 @@ +# Maxmind GeoIP2 API bindings +# Copyright (c) 2013 Timo Teräs +# GPLv2 applies + +# Use from your VCL by adding to your vcl_recv(): +# call maxminddb_lookup; + +# You also need to modify the cc_command parameter to include +# Maxmind database library (-lmaxminddb). In Alpine Linux this is +# done by uncomminting the relevant VARNISHD_PLUGIN_CFLAGS line in +# /etc/conf.d/varnishd. + +C{ + +#include +#include + +static MMDB_s mmdb; + +static void __attribute__((constructor)) __geoip_on_load(void) +{ + if (MMDB_open("/var/lib/libmaxminddb/GeoLite2-City.mmdb", MMDB_MODE_MMAP, &mmdb) != MMDB_SUCCESS) + mmdb.filename = NULL; +} + +static void __attribute__((destructor)) __geoip_on_unload(void) +{ + if (mmdb.filename != NULL) + MMDB_close(&mmdb); +} + +static inline void __geoip_set_header(struct sess *sp, const char *hdr, MMDB_lookup_result_s *res, char **path) +{ + MMDB_entry_data_s entry; + char buf[64]; + int s; + + s = MMDB_aget_value(&res->entry, &entry, path); + if (s != MMDB_SUCCESS || !entry.has_data) + return; + + if (entry.type != MMDB_DATA_TYPE_UTF8_STRING) + return; + + if (entry.data_size+1 >= sizeof(buf)) + return; + + memcpy(buf, entry.utf8_string, entry.data_size); + buf[entry.data_size] = 0; + + VRT_SetHdr(sp, HDR_REQ, hdr, buf, vrt_magic_string_end); +} + +static void __geoip_set_headers(struct sess *sp) +{ + static const char *continent_path[] = { "continent", "code", NULL }; + static const char *country_path[] = { "country", "iso_code", NULL }; + MMDB_lookup_result_s res; + int mmdb_error; + + if (mmdb.filename == NULL) + return; + + res = MMDB_lookup_sockaddr(&mmdb, (struct sockaddr*) VRT_r_client_ip(sp), &mmdb_error); + if (mmdb_error == MMDB_SUCCESS) { + __geoip_set_header(sp, "\022X-GeoIP-Continent:", &res, continent_path); + __geoip_set_header(sp, "\020X-GeoIP-Country:", &res, country_path); + } +} + +}C + +sub maxminddb_lookup { + C{ __geoip_set_headers(sp); }C + return(lookup); +} -- cgit v1.2.3