aboutsummaryrefslogtreecommitdiffstats
path: root/main/varnish/maxminddb.vcl
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2013-11-14 15:35:43 +0200
committerTimo Teräs <timo.teras@iki.fi>2013-11-14 15:39:09 +0200
commitd32344d735b978fb7d30a9fcc4ad1141879c5433 (patch)
tree0580961253e8344a5b1963bf2aa443deffda5d9b /main/varnish/maxminddb.vcl
parent6fd658a9994c9d1d1aa3447bddc8c1a15744e766 (diff)
downloadaports-d32344d735b978fb7d30a9fcc4ad1141879c5433.tar.bz2
aports-d32344d735b978fb7d30a9fcc4ad1141879c5433.tar.xz
main/varnish: add plugin to do maxmind geoip lookups
Diffstat (limited to 'main/varnish/maxminddb.vcl')
-rw-r--r--main/varnish/maxminddb.vcl76
1 files changed, 76 insertions, 0 deletions
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 <maxminddb.h>
+#include <string.h>
+
+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);
+}