Intégrer la géolocalisation à Apache 2 sous Linux
Date de publication : 10/02/2009 , Date de mise à jour : 19/02/2009
Par
Jean-Yves Lacour (Site professionnel)
julp (Autres articles)
Connaître la situation géographique des clients possède plus régulièrement
un but statistique. Or, il peut s'avérer utile de pouvoir prendre en compte
cet élément au niveau de la configuration du serveur même, ainsi que par
les langages exécutés au niveau du serveur.
1. Présentation
2. Mise en place
2.1. A partir des sources
2.2. Exemple de Debian Etch pour une installation à partir des paquets binaires prévus
3. Utilisation
3.1. Par l'usage d'un langage de programmation côté serveur
3.1.1. PHP
3.1.2. Ruby
3.1.3. Perl
3.1.4. Autres langages
3.2. Dans le cadre de la configuration du serveur seul
3.2.1. Première application : interdire l'accès à certains utilisateurs étrangers
3.2.2. Deuxième application : redirection suivant le lieu de connexion
4. Epilogue
5. Remerciements
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 :
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 :
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.
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
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 :
-
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 :
tar xzf GeoIP-1.4.5.tar.gz -C /usr/local/src
|
Puis procédez à la compilation et installation (requérant les
droits administrateur) :
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.
|
-
Vient ensuite le tour du module Apache. Détarez les sources
de celui-ci ...
tar xzf ~/mod_geoip2_1.2.5.tar.gz -C /usr/local/src
|
... puis passez à sa compilation.
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.
|
-
Décompressez la base que vous avez récupérée plus tôt à l'aide
de gunzip :
gunzip GeoIP.dat.gz
gunzip GeoLiteCity.dat.gz
|
Pour la déplacer vers un répertoire plus "approprié" :
cp ~/GeoIP.dat /usr/local/geoip/share/GeoIP/
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 :
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 :
LoadFile /usr/local/geoip/lib/libGeoIP.so
|
Puis activez et configurez à présent notre module par la
mention des lignes suivantes :
<IfModule mod_geoip.c>
GeoIPEnable On
GeoIPDBFile /usr/local/geoip/share/GeoIP/GeoIP.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
Utilisation.
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 :
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 :
Enfin, (re)démarrer le serveur web :
/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 :
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 :
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 :
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 :
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 :
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 :
si GEOIP_REGION = "A5" et page_courante = "/index.html" et non cookie_defini("local")
alors
créer_cookie("local", "1", ".corse.fr", 60, "/")
redirection("/vie-pratique.html")
fsi
|
Qui se traduirait à l'aide d'une règle de réécriture :
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.


Copyright ©
2008
Developpez LLC. Tous droits réservés Developpez LLC.
Aucune reproduction, même partielle, ne peut être faite de ce site et de
l'ensemble de son contenu : textes, documents et images sans l'autorisation
expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à 3 ans
de prison et jusqu'à 300 000 E de dommages et intérêts.
Cette page est déposée à la
SACD.