1. Présentation

Le module Apache GeoIP, développé et maintenu par la société MaxMind, vous permet non seulement de connaître la provenance de manière relativement fiable d'un visiteur mais de la faire intervenir dans vos développements ou encore dans la configuration du serveur.

La société MaxMind ne fournit pas seulement des modules pour les différentes versions du serveur web Apache mais aussi des bibliothèques pour divers langages (C - la base "commune", PHP, Perl, Java, etc). Cependant, une intégration au niveau du serveur lui-même présente quelques avantages et pré-requis.

L'unique condition préalable est de pouvoir accéder au serveur (donc de disposer des droits) pour pouvoir installer ce module et reconfigurer Apache.

Par contre, les enjeux sont multiples :

  • Les informations relatives à la géolocalisation sont transmises sous forme de variable d'environnement au langage serveur employé. Leur récupération n'en est que plus aisée et ceci offre une certaine indépendance : il n'y a ainsi nul besoin d'installer une bibliothèque pour chaque langage que vous pourriez être amené à utiliser sur votre serveur ;
  • Apache devient alors capable d'interagir en fonction de la localisation du client. Il peut ainsi directement effectuer un filtrage des clients, les rediriger, ...

2. Mise en place

Ici ne sera présentée que l'installation du module sous forme dynamique afin de pouvoir l'activer ou désactiver à volonté et pour une mise en place rapide (nous évitant une recompilation complète d'Apache).

2.1. A partir des sources

Il est nécessaire de télécharger trois choses avant de commencer :

  • La bibliothèque C, dépendance requise au module que nous compilerons dans un deuxième temps :

     
    Sélectionnez
    
    cd ~
    wget http://www.maxmind.com/download/geoip/api/c/GeoIP-1.4.5.tar.gz
    

    Vérifier éventuellement qu'il n'existe pas de versions plus récentes que ce soit maintenant pour la bibliothèque C comme pour les sources du module que nous abordons ci-dessous.

  • Les sources du module propres aux versions de la branche 2 d'Apache :

     
    Sélectionnez
    
    wget http://www.maxmind.com/download/geoip/api/mod_geoip2/mod_geoip2_1.2.5.tar.gz
    
  • Enfin, télécharger une base de données mise à disposition gratuitement (donc plus limitée). Il en existe deux : celle de base dont vous ne pourrez tirer que le pays du client et une seconde fournissant des informations plus précises puisque capable de vous donner la ville et la région de l'internaute.

     
    Sélectionnez
    
    # La base "pays" uniquement
    wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
     
    # La base "villes allégée"
    wget http://www.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
    

    La fiabilité des bases de données mises gratuitement à votre disposition est estimée à 98% pour celle des pays et à 69% en ce qui concerne celle des villes. Avec une perte supplémentaire d'environ 1,5% tous les mois si vous ne téléchargez pas sa nouvelle version paraissant de manière mensuelle.

Procédons à leur installation :

  1. Comme mentionné plus haut, un certain ordre doit être respecté : il faut commencer par l'API C de GeoIP puisque le module repose sur celle-ci.

    Décompressez l'archive :

     
    Sélectionnez
    
    tar xzf GeoIP-1.4.5.tar.gz -C /usr/local/src
    

    Puis procédez à la compilation et installation (requérant les droits administrateur) :

     
    Sélectionnez
    
    cd /usr/local/src/GeoIP-1.4.5/
    ./configure --prefix=/usr/local/geoip
    make
    make install
    

    Pour compiler cette bibliothèque vous devrez posséder sur votre système les fichiers d'entête de la bibliothèque zlib. Si ce n'est pas le cas, cherchez un paquet éponyme suffixé de dev ou devel puis installez-le.

  2. Vient ensuite le tour du module Apache. Détarez les sources de celui-ci ...

     
    Sélectionnez
    
    tar xzf ~/mod_geoip2_1.2.5.tar.gz -C /usr/local/src
    

    ... puis passez à sa compilation.

     
    Sélectionnez
    
    cd /usr/local/src/mod_geoip2_1.2.5/
    apxs2 -i -a -L/usr/local/geoip/lib -I/usr/local/geoip/include -lGeoIP -c mod_geoip.c
    

    Pour cette étape il vous sera nécessaire de posséder les fichiers d'entête d'Apache. Ceux qui ont donc installé leur serveur sous forme de paquet binaire auront sans doute à chercher un paquet nommé sur le modèle apache2(-threaded|mpm)-dev(el) ou encore httpd-dev(el).

    Suivant votre système, la commande apxs2 pourra être plus simplement appelée apxs.

    La commande apxs2, telle qu'elle a été utilisée ci-dessus suppose que le répertoire où elle est située figure comme valeur de la variable d'environnement PATH. A défaut, il est possible d'en préciser son chemin.

  3. Décompressez la base que vous avez récupérée plus tôt à l'aide de gunzip :

     
    Sélectionnez
    
    gunzip GeoIP.dat.gz
    # ou suivant la base choisie
    gunzip GeoLiteCity.dat.gz
    

    Pour la déplacer vers un répertoire plus "approprié" :

     
    Sélectionnez
    
    cp ~/GeoIP.dat /usr/local/geoip/share/GeoIP/
    # ou suivant la base choisie
    cp ~/GeoLiteCity.dat /usr/local/geoip/share/GeoIP/
    

    Pour la suite, assurez-vous que cette base est accessible en lecture de tous (surtout de l'utilisateur sous lequel fonctionne Apache).

Nous pouvons maintenant passer à la configuration d'Apache. Vérifiez tout d'abord la présence d'une ligne LoadModule ressemblant à celle ci-dessous (chemin à adapter) qui chargera notre nouveau module :

 
Sélectionnez

LoadModule geoip_module /usr/lib/apache2/modules/mod_geoip.so

Rajoutez-la à la suite des autres si elle se fait porter absente. Gardez le fichier ouvert en vue de placer une ligne LoadFile avant la précédente, nécessaire au bon fonctionnement du module, afin qu'Apache puisse auparavant charger la librairie geoip duquel dépend le module :

 
Sélectionnez

LoadFile /usr/local/geoip/lib/libGeoIP.so

Puis activez et configurez à présent notre module par la mention des lignes suivantes :

 
Sélectionnez

<IfModule mod_geoip.c>
    GeoIPEnable On
    GeoIPDBFile /usr/local/geoip/share/GeoIP/GeoIP.dat # ou /usr/local/geoip/share/GeoIP/GeoLiteCity.dat
</IfModule>

A ce stade vous devriez relancer le serveur et vérifier le bon fonctionnement du tout en poursuivant directement à la partie intitulée .

2.2. Exemple de Debian Etch pour une installation à partir des paquets binaires prévus

Dans la mesure où votre système prévoit des paquets pour le module GeoIP, vous avez tout intérêt à les privilégier : son installation n'en sera que plus rapide et plus facile.

Dans le cas de Debian, cela peut se résumer à la commande suivante :

 
Sélectionnez

aptitude install libapache2-mod-geoip

Debian vous installera uniquement la base de données "pays". Si vous prévoyez d'en utiliser une autre ou une version plus à jour, il vous faudra éventuellement décommenter la directive GeoIPDBFile du fichier /etc/apache2/mods-available/geoip.conf en retirant le caractère dièse (#) apparaissant en début de ligne et en modifier la valeur pour pointer sur la vôtre.

Normalement le module devrait être actif par défaut à l'issue de son installation. Assurez-vous en, en contrôlant la présence des liens symboliques geoip.conf et geoip.load dans le répertoire /etc/apache2/mods-enabled ou exécutez la commande a2enmod, qui le fera pour vous dans le cas contraire :

 
Sélectionnez

a2enmod geoip

Enfin, (re)démarrer le serveur web :

 
Sélectionnez

/etc/init.d/apache2 force-reload

3. Utilisation

Les variables d'environnement pour la base de données de type "pays" sont :

  • GEOIP_COUNTRY_CODE : code international du pays (suivant la norme ISO 3166)
  • GEOIP_COUNTRY_NAME : nom complet du pays (en anglais)

Si GeoIP est incapable de déterminer la provenance de l'utilisateur, les variables ne seront pas définies.

En ce qui concerne la base de données "allégée des villes", viennent s'ajouter à la liste précédente :

  • GEOIP_REGION : un code indiquant la région (voir les valeurs plus bas ainsi que leur correspondance pour la France)
  • GEOIP_CITY : la ville
  • GEOIP_DMA_CODE : code DMA (Designated Market Area) attribué à une zone où les fréquences (télévision, radio, etc) sont identiques (concerne les Etats Unis, valeur par défaut : 0)
  • GEOIP_AREA_CODE : indice téléphonique représentant une zone précise (concerne les Etats Unis, valeur par défaut : 0)
  • GEOIP_LATITUDE : la latitude
  • GEOIP_LONGITUDE : la longitude
  • GEOIP_POSTAL_CODE : le code postal (concerne uniquement les Etats Unis, ne sera pas définie pour tout autre pays)

Les valeurs de la variable GEOIP_REGION pour les différentes régions françaises avec leur correspondance sont :

Région Code
Alsace C1
Aquitaine 97
Auvergne 98
Basse-Normandie 99
Bourgogne A1
Bretagne A2
Centre A3
Champagne-Ardenne A4
Corse A5
Franche-Comté A6
Haute-Normandie A7
Île-de-France A8
Languedoc-Roussillon A9
Limousin B1
Lorraine B2
Midi-Pyrénées B3
Nord-Pas-de-Calais B4
Pays de la Loire B5
Picardie B6
Poitou-Charentes B7
Provence-Alpes-Côte d'Azur B8
Rhône-Alpes B9

3.1. Par l'usage d'un langage de programmation côté serveur

La récupération des différentes "variables" créées par le module de géolocalisation dépendent de la manière dont ce dernier a été configuré. En effet, suivant la valeur de sa directive GeoIPOutput, elles ne seront pas accessibles de la même manière.

  • Lorsque GeoIPOutput a pour valeur Notes, les variables relatives à la géolocalisation du client ne sont créées que dans la table interne d'Apache appelée Notes. Ce n'est pas, de ce fait, la méthode la plus facile pour ensuite les atteindre avec un langage serveur ;
  • En revanche, avec la valeur Env, toutes ces variables sont exportées à la manière des variables d'environnement système. Cette forme facilite fortement leur usage, quel que soit le langage employé côté serveur, comme nous le verrons ci-dessous ;
  • Enfin, la valeur All (par défaut), est à recommander puisque toutes ces variables seront définies deux fois, selon les méthodes des deux points précédents. Ainsi il n'y a plus lieu de se demander par quel moyen y avoir recourt.

3.1.1. PHP

Etant donné qu'il est plus courant d'utiliser PHP en tant que module Apache, vous disposez alors sans doute de l'extension apache qui fournit, entre autres, la fonction apache_note. Ainsi que GeoIPOutput ait pour valeur Notes ou All, vous serez en mesure d'exploiter toutes les variables GEOIP.

Cependant, beaucoup trouveront certainement plus naturel de trouver ces informations dans le tableau superglobal $_SERVER. Chose possible dès lors que GeoIPOutput sera positionné à All ou Env.

Ci-dessous, un code PHP listant l'ensemble des variables GEOIP, dans l'hypothèse où elles vous sont mises à disposition comme des variables d'environnement :

 
Sélectionnez

foreach ($_SERVER as $k => $v) {
    if (stripos($k, 'GEOIP') !== FALSE) {
        printf('%s : %s<br />', $k, $v);
    }
}

3.1.2. Ruby

Par contre dans le cas de Ruby, il sera sans doute plus facile de trouver ces variables dans le hash ENV, recensant, comme son nom l'indique, toutes les variables d'environnement (ce qui implique que GeoIPOutput a pour valeur Env ou bien All) du fait de son utilisation CGI. Le code équivalent au script PHP présenté ci-dessus pourrait s'écrire de la sorte :

 
Sélectionnez

ENV.each do |k,v|
    puts "#{k} => #{v}" if k ~= /GEOIP/i
end

3.1.3. Perl

Pour des raisons autant de facilité que de portabilité, seule la méthode visant à exploiter l'exportation de ces variables comme variable d'environnement sera présentée (impliquant de nouveau GeoIPOutput à Env ou All). Vous les trouverez donc dans le hachage %ENV :

 
Sélectionnez

foreach (keys(%ENV)) {
    print "$_ => $ENV{$_}$/" if $_ =~ /GEOIP/i;
}

3.1.4. Autres langages

Nous vous invitons, pour ce qui est des autres langages, à consulter leurs documentations respectives ou à vous orienter sur les forums.

3.2. Dans le cadre de la configuration du serveur seul

3.2.1. Première application : interdire l'accès à certains utilisateurs étrangers

Une première application, allant à l'encontre des principes d'accessibilité et de liberté d'Internet, pourrait être de bloquer des utilisateurs faisant partie de tel ou tel pays voir, pourquoi pas, de n'autoriser que ceux de pays prédéterminés.

En guise d'exemple, nous souhaitons bloquer les internautes russes et chinois. Se présentent deux possibilités :

  • En introduisant une variable d'environnement :

     
    Sélectionnez
    
    SetEnvIf GEOIP_COUNTRY_CODE ^CN|RU$ FORBIDDEN=1
     
    Deny from env=FORBIDDEN
    

    Notre variable d'environnement FORBIDDEN ne sera créée que si l'on sait que le client est russe (code pays "RU") ou chinois (de code "CN") d'après le module GeoIP. Le fait que cette variable soit dans ces conditions définie, lui vaudra un blocage (le serveur retournera la page d'erreur 403 au lieu de la page attendue).

  • A l'aide du module de réécriture :

     
    Sélectionnez
    
    RewriteEngine on
    RewriteCond %{ENV:GEOIP_COUNTRY_CODE} ^CN|RU$
    RewriteRule .* - [F]
    

    Strictement la même chose, écrite avec des règles de réécriture. En réalité, le module a été quelque peu détourné de son but premier : le tiret fourni en deuxième paramètre de la directive RewriteRule indique qu'il ne faut pas effectuer de réécriture et c'est l'option F (pour forbidden, située entre les crochets, qui va retourner l'erreur 403 pour nos clients identifiés comme russes et chinois.

3.2.2. Deuxième application : redirection suivant le lieu de connexion

Pour ce second exemple d'application, l'objectif consiste à distinguer la provenance de l'utilisateur afin d'éventuellement rediriger celui-ci sur la page qui lui serait potentiellement la plus intéressante. Ici, nous supposerons qu'il s'agit d'un site dédié à la région Corse (code associé : A5 - voir le tableau plus haut ; de domaine corse.fr).

Si l'utilisateur est reconnu comme étant local, nous le redirigerons sur la page vie-pratique.html fournissant diverses informations utiles et actualisées lorsqu'il demandera pour la première fois le document d'index (index.html). Ce premier passage sera marqué par un cookie, expirant après une heure, dans le but de ne pas entraver sa navigation.

On pourrait schématiser cette opération par l'algorithme suivant :

 
Sélectionnez

si GEOIP_REGION = "A5" et page_courante = "/index.html" et non cookie_defini("local")
    alors
        créer_cookie("local", "1", ".corse.fr", 60, "/")
        /**
         * Paramètres :
         * - nom du cookie
         * - sa valeur
         * - le nom de domaine auquel il est associé
         * - durée en minutes avant expiration
         * - le chemin sur lequel il s'applique
         **/
        redirection("/vie-pratique.html")
fsi

Qui se traduirait à l'aide d'une règle de réécriture :

 
Sélectionnez

RewriteEngine on
 
RewriteCond %{ENV:GEOIP_REGION} =A5                                            # Règle n°1
RewriteCond %{HTTP_COOKIE} !\blocal\b                                          # Règle n°2
RewriteRule ^(:?index.html)?$ /vie-pratique.html [L,CO=local:1:.corse.fr:60:/] # Règle n°3

La première règle permet d'indiquer que seules les connexions établies depuis la région Corse, c'est-à-dire lorsque GEOIP_REGION est égal à A5, sont concernées.

La deuxième vérifie qu'un cookie nommé local n'a pas été créé. Si tel était le cas, on n'abandonnerait là la lecture de la règle, l'internaute ne serait pas redirigé.

Enfin l'opération de réécriture ou redirection, qui sera appliquée si les conditions précédentes ont été remplies et que le document demandé est la page d'index. A ce moment on en profite pour marquer la redirection en créant le cookie (option CO).

4. Epilogue

Bien qu'il existe de multiples solutions pour l'usage de l'"API" GeoIP, prenons pour preuve PHP qui se décline en une extension, en une bibliothèque écrite en PHP pur ou un paquet PEAR. Nous espérons, au travers de cet article, avoir montré tout l'intérêt de la déporter au sein du serveur web. D'autant plus, qu'un module est disponible pour chacune des branches d'Apache (l'installation du module pour une version 1.3 étant sensiblement identique).

Liens Developpez en relation :
Liens externes :

5. Remerciements

Nous tenons à remercier RideKick pour sa relecture attentive.