Aug 082011
 

In diesem Artikel geht es um eine Mobile Weiche, welche mit dem HTTP Beschleuniger Varnish realisiert wird. Varnish entscheidet anhand des User Agents im Webbrowser und des Herkunftslands der IP, auf welche Seite der Besucher weitergeleitet wird. Um das Herkunftsland zu ermitteln verwenden wir GeoIP.

Ein gewisses Grundwissen mit Varnish wird hierbei vorausgesetzt. Falls dies nicht der Fall ist, empfehle ich, folgende Seite zu besuchen: https://www.varnish-cache.org/docs/3.0/

1) Installation

Die Installation ist schnell erledigt, da fast alles bereits in den Paketquellen von Ubuntu enthalten ist.

Varnish und GeoIP installieren

apt-get install varnish geoip-bin libnet-ip-perl libgeo-ipfree-perl
libgeo-ip-perl libgeoip-dev

Quellcode von GeoIP Plugin herunterladen

wget https://www.varnish-cache.org/trac/raw-attachment/wiki/
GeoipUsingInlineC/GeoIP-plugin-2.tar.gz 

Entpacken

tar xf GeoIP-plugin-2.tar.gz
cd GeoIP-plugin/lib/

Kompilieren   

make

Falls das Plugin funktioniert sollte folgende Ausgabe von

make test

entstehen:

GeoIP plugin loaded successfully.
Testing IPs:
195.110.128.11 => IT (OK)
157.166.224.25 => US (OK)
212.58.224.138 => GB (OK)
80.91.37.210 => NO (OK)
192.168.0.1 => Unknown (OK)
(null) => Unknown (OK)

Das kompilierte Plugin in das Verzeichniss von Varnish kopieren

cp geoip_plugin.so /etc/varnish/

Ab nun sollten alle Voraussetzungen erfüllt sein und wir können uns der Konfiguration zuwenden.

2) Konfiguration

Varnish (siehe Bild, Station 1) überprüft, ob der HTTP User Agent einem mobilen Endgerät zugeordnet werden kann oder nicht. Dies geschieht in der Varnish-Konfiguration mit der Funktion detect_device.

Falls es ein mobiler User ist, senden wir ihn zur Länderweiche (siehe Bild, Station 2), andernfalls senden wir ihn an das default Backend (siehe Bild, Station 3). Das GeoIP-Plugin setzt den HTTP Header X-Country-Code anhand der IP-Adresse mit dem jeweiligen Ländercode.

Die Länderweiche (siehe Bild, Station 2) entscheidet mit Hilfe des HTTP Headers X-Country-Code welches Backend verwendet werden soll: Falls der Ländercode DE, AT oder CH ist, wird das deutsche Backend (Station 4) verwendet, andernfalls ist das mobile Backend nicht deutsch (Station 5).


# Mobile weiche mithilfe von Varnish und GeoIP
# Lade das Plugin /etc/varnish/geoip_plugin.so
C{
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>

static const char* (*get_country_code)(char* ip) = NULL;
__attribute__((constructor)) void
load_module()
{
const char* symbol_name = "get_country_code";
/* Lade unser kompiliertes Plugin*/
const char* plugin_name = "/etc/varnish/geoip_plugin.so";
void* handle = NULL; /* Erstelle Dateihandle */
handle = dlopen( plugin_name, RTLD_NOW );
if (handle != NULL) { /* Falls die Datei existiert */
get_country_code = dlsym( handle, symbol_name );
if (get_country_code == NULL) /*  Plugin funktioniert nicht*/
fprintf( stderr, "nError: Could not load GeoIP plugin:n%snn", dlerror() );
else /*  Plugin funktioniert */
printf( "GeoIP plugin loaded successfully.n");
}
else /* Falls die Datei nicht existiert */
fprintf( stderr, "nError: Could not load GeoIP plugin:n%snn", dlerror() );
}
}C

# PC Clients allgemein
backend default {
.host = "127.0.0.1";
.port = "80";
}
# Mobile Clients die keine Deutsche Sprache sprechen
backend mobile_lang_en {
.host = "127.0.0.1";
.port = "81";
}
# Mobile Clients, welche Deutsch sprechen
backend mobile_lang_de {
.host = "127.0.0.1";
.port = "82";
}

sub vcl_recv {
# GeoIP Herkunftsland ermitteln und HTTP Header X-Country-Code setzen.
C{
VRT_SetHdr(sp, HDR_REQ, "�17X-Country-Code:", (*get_country_code)( VRT_IP_string
(sp, VRT_r_client_ip(sp)) ), vrt_magic_string_end);
}C
#No-Cache nur verarbeiten wenn die Seite nicht über einen Proxy und nicht
#vom MSN-Bot aufgerufen wird
if (req.http.Cache-Control ~ "no-cache") {
if (! (req.http.Via || req.http.User-Agent ~ "bot|MSIE")) {
purge_url(req.url);
}
}
# Herausfinden ob mobile oder pc User
call detect_device;
# Das Backend anhand von HTTP Header X-Device sowie X-Country-Code bestimmen
call routing;
}
# Entscheidung welches Backend verwendet werden muss.
sub routing {
# Falls ein nicht Mobile User verbindet, verwende default backend.
if (req.http.X-Device == "pc") {
return(pass);
}
if (req.http.X-Device == "mobile") {
# Falls Herkunftsland DE, CH oder AT, schicke Traffic auf Mobile Deutsche Weiche
if (req.http.X-Country-Code == "DE" || req.http.X-Country-Code == "AT" ||
req.http.X-Country-Code == "CH") {
set req.backend = mobile_lang_de;
}
# Fall nicht Herkunftsland DE oder AT, schicke Traffic auf Mobile Englische Weiche
else {
set req.backend = mobile_lang_en;
}
}
}
# Setze Header X-Device je nach Browseragent
# Der Browseragent verrät uns ob es sich um ein Mobile User handelt.
sub detect_device {
# Gehe davon ersteinmal aus, dass es ein normaler PC User ist
set req.http.X-Device = "pc";
# LG Handys enthalten LG- im Agentenstring
if (req.http.User-Agent ~ "LG-"){
set req.http.X-Device = "mobile";
}
# Dies hier sind die populärsten Agentenstrings
if (req.http.User-Agent ~ "iPhone" || req.http.User-Agent ~ "Android" ||
req.http.User-Agent ~ "Symbian" || req.http.User-Agent ~ "^BlackBerry" ||
req.http.User-Agent ~ "^SonyEricsson" || req.http.User-Agent ~ "^Nokia" ||
req.http.User-Agent ~ "^SAMSUNG" ||
req.http.User-Agent ~ "^LG" || req.http.User-Agent ~ "   webOS" ||
req.http.User-Agent ~ "Windows Phone") {
set req.http.X-Device = "mobile";
}
# Palm Telefon Useragent string
if (req.http.User-Agent ~ "^PalmSource"){
set req.http.X-Device = "mobile";
}
# Andere bekannte Handy Browseragenten
if ( req.http.user-agent ~
"(.*Blackberry.*|.*BlackBerry.*|.*Blazer.*|.*Ericsson.*|.*htc.*|.*Huawei.*
|.*iPhone.*|.*iPod.*|.*MobilePhone.*|.*Motorola.*|.*nokia.*|.*Novarra.*
|.*O2.*|.*Palm.*|.*Samsung.*|.*Sanyo.*|.*Smartphone.*
|.*SonyEricsson.*|.*Symbian.*|.*Toshiba.*|.*Treo.*|.*vodafone.*
|.*Xda.*|^Alcatel.*|^Amoi.*|^ASUS.*|^Audiovox.*|^AU-MIC.*
|^BenQ.*|^Bird.*|^CDM.*|^DoCoMo.*|^dopod.*|^Fly.*|^Haier.*
|^HP.*iPAQ.*|^i-mobile.*|^KDDI.*|^KONKA.*|^KWC.*|^Lenovo.*|^LG.*
|^NEWGEN.*|^Panasonic.*|^PANTECH.*|^PG.*|^Philips.*|^portalmmm.*
|^PPC.*|^PT.*|^Qtek.*|^Sagem.*|^SCH.*|^SEC.*|^Sendo.*|^SGH.*|^Sharp.*
|^SIE.*|^SoftBank.*|^SPH.*|^UTS.*|^Vertu.*|.*Opera.Mobi.*|.*Windows.CE.*
|^ZTE.*|.*LG.*|.*SAMSUNG.*|.*webOS|^Nokia*)"){
set req.http.X-Device = "mobile";
}
# Falls es sich um Tablets handelt, verwende das normale Backend
if (req.http.User-Agent ~ "(.*GT-P1000M.*|.*Xoom.*
|.*GT-P7100 Build/HRI83.*|.*A500 Build/HRI66.*
|.*iPad.*|.*iPod.*)") {
set req.http.X-Device = "pc";
}
}

Die Konfigurationsdatei kann hier heruntergeladen werden.

3) Fazit

Varnish ist ein solider HTTP-Beschleuniger, welcher zu deutlich mehr imstande ist, als man denkt.

Dank der Plugin-Funktionalität der eigenen Skriptsprache VCL, sowie C-Code Unterstützung innerhalb einer Konfigurationsdatei, ist es möglich, eine zuverlässige mobile Weiche in kurzer Zeit zu erstellen.

In eigener Sache:
Funktionen mit Hilfe von C in den Varnish einzubauen ist nicht immer ganz trivial. Um Ziele für Mobiluser auf einzelnen Domains leichter verwalten zu können haben wir uns ein Webinterface geschrieben, dass viele Weiterleitungsmöglichkeiten abbildet. Auf unserer Hosting-Seite finden sich zum Beispiel fertige Webserver mit Varnish und Mobiluser Targeting. (aw)

  2 Antworten zu “Mobile Weichen mit Varnish und GeoIP”

  1. Hi,
    danke für den Artikel – super interessant. Wie aktuell und genau ist diese GEO IP DB? Wie oft muss/sollte man diese aktualiseren?
    Grüße
    Andy

  2. Hi Andy,
    die Ländererkennung ist schon in der frei verfügbaren Datenbank sehr genau. Wenn ein Projekt höhere Anforderungen hat, kannst Du Dir bei MaxMind (http://www.maxmind.com/) bessere Datenbanken holen die regelmäßig aktualisiert werden.

 Antworten

Du kannst diese HTML Tags und Attribute benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(Pflichtfeld)

(Pflichtfeld)

© 2017 LAMP solutions GmbH