Géolocalisation par DNS avec Bind

Un petit billet rapide suite à la réception en Alpha test d’un serveur OVH au Canada 🙂

Alors voilà, vous avez votre serveur en Europe et un autre aux USA (je simplifie, hein, ca peut être votre ferme de serveurs dans le Larzac et l’autre dans le Wisconsin).

Si vous avez décidé d’offrir le même service au monde entier, il serait peut-être intéressant de rediriger vos visiteurs américains sur votre serveur aux US et vos visiteurs européens sur celui en Europe, question de latence.

Cette technique, employée depuis très longtemps par les « accélérateurs de contenus » comme Akamaï , a été reprise par les sites à gros trafic comme Google, Yahoo et consorts.

Comment on met cela en place ?

D’abord je considère que vous avez 1 serveur DNS qui tourne sur chacun de vos serveurs (1 aux US, 1 en Europe).

Bien évidemment, on définira ses deux serveurs en NS du domaine que l’on veut géolocaliser.

Pour réussir ce tour de force de géolocalisation, il vous faut une base des adresses IPs mondiales et les pays dans lesquels elles sont attribuées.

L’un des site spécialisé dans ce domaine est Maxmind

Et bonus, ce site offre en téléchargement une base de ses IPs :

http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip

C’est un fichier CSV au contenu plutôt impressionnant qu’il va falloir rendre compréhensible par votre serveur DNS.

Heureusement, Mark, sur son site Phix.me, vous propose un script Bash pour faire cela rapidement.

.

#!/bin/bash
 
[ -f GeoIPCountryCSV.zip ] || wget -T 5 -t 1 http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip
 
echo -n "Creating CBE (Country,Begin,End) CSV file..."
unzip -p GeoIPCountryCSV.zip GeoIPCountryWhois.csv | awk -F \" '{print $10","$6","$8}' > cbe.csv
echo -ne "DONE\nGenerating BIND GeoIP.acl file..."
 
(for c in $(awk -F , '{print $1}' cbe.csv | sort -u)
do
  echo "acl \"$c\" {"
  grep "^$c," cbe.csv | awk -F , 'function s(b,e,l,m,n) {l = int(log(e-b+1)/log(2)); m = 2^32-2^l; n = and(m,e); if (n == and(m,b)) printf "\t%u.%u.%u.%u/%u;\n",b/2^24%256,b/2^16%256,b/2^8%256,b%256,32-l; else {s(b,n-1); s(n,e)}} s($2,$3)'
  echo -e "};\n"
done) > GeoIP.acl
rm -f cbe.csv
echo "DONE"
exit 0

Vous avez maintenant un fichier geo.acl compréhensible par BIND.

On se modifie BIND pour servir un fichier d’enregistrement différent suivant le pays d’origine du visiteur :

named.conf :
include "/opt/bind/GeoIP.acl";

Et pour traiter les visiteurs, nous allons utiliser le système « View » de BIND qui nous permet de servir des réponses différentes suivant l’ip du demandeur.

view "north_america" {
  match-clients { US; CA; MX; };
  zone "guiguiabloc.fr" {
       type master;
       file "/etc/bind/guiguiabloc.us";
       allow-transfer { ipdnsslave; };
       allow-query { any; };
};
};
 
view "south_america" {
  match-clients { AR; CL; BR; PY; PE; EC; CO; VE; BO; UY; };
  recursion no;
zone "guiguiabloc.fr" {
       type master;
       file "/etc/bind/guiguiabloc.us";
       allow-transfer { ipdnsslave; };
       allow-query { any; };
 
};
};
 
view "other" {
  match-clients { any; };
zone "guiguiabloc.fr" {
       type master;
       file "/etc/bind/guiguiabloc.fr";
       allow-transfer { ipdnsslave; };
       allow-query { any; };
};

Et voila, on relance BIND et vous devriez désormais avoir une réponse différente suivant le pays depuis lequel vous êtes (ou pas :p)

En espérant que cela vous soit utile 😀

Tout cela bien expliqué dans la langue de Shakespeare (ou de John Holmes, suivant vos centres d’intérêts… ) :

http://phix.me/geodns/

Ce billet a été posté dans linux, réseau. Bookmark le permalink.

12 commentaires sur “Géolocalisation par DNS avec Bind

  1. Sauf que de cette façon si ton serveur US est KO, tes visiteurs US ne peuvent plus du tout consulter ton site.

    Une cascade de NS serait à mon avis préférable, le dispatch se faisant a priori conformément à la topologie et donc avec une forte probabilité conformément à la géolocalisation

  2. Tout a fait d’accord avec toi, c’est une solution plutot rapide et simple pour un test comme ceux des serveurs offerts par OVH.
    Je te rejoins sur les NS cascadés en frontaux (tu t’en doutes 😉 ) pour une architecture scalable.

  3. Bonjour,

    juste une coquille (du moins à mon avis), dans tes 2 premières views tu as la même directive file.

    😉
    a++

  4. j’imagine plutot que les google et autres gros site utilisent l’anycast pour satisfaire ce besoin….

  5. @toff Les « gros » sites ne jouent pas avec ce genre de technique non.
    Le cascading NS ou l’anycast est plutot utilisé.

  6. Tu dis qu’il faut 2 serveurs DNS ?? mais finalement il n’y a qu’un seul serveur qui analyse l’IP et la redirige vers un fichier de zone sur lui même. donc un seul serveur DNS suffit non?

  7. Au point de vue purement technique, oui. Mais 1 seul serveur DNS pour un domaine c’est pas très RFC compliant… (si en plus le domaine est un .fr tu te feras jeter par le zonecheck de l’afnic)

  8. Bonjour,

    Sauf erreur de ma part, la requête qui arrive sur ton serveur DNS vient rarement du poste utilisateur lui même mais plutôt du serveur DNS transmis par dhcp ou via l’*box de l’internaute.

    Donc au final, tu geodns suivant le serveur DNS qui tape sur le tient et pas suivant le user en lui même non ?

  9. C’est l’ip publique du client qui est matché. (mettre un serveur dns américain ne te fait pas pour autant passer pour un client sur le territoire américain).

  10. Si je mets mon ip fixe dans une ACL et que j’utilise dig sans forcer mon serveur @dns, je ne suis pas matché, par contre si je force le dig directement sur mon serveur dns je suis matché :/

  11. Ca concerne le réseau de l’opérateur principalement la géolocalisation. On ne cherche pas a selectionner un utilisateur de Lorient par rapport a un utilisateur de Pau, mais par pays.
    Je n’ai eu aucun soucis de géolocalisation en utilisant ou mes propres DNS ou les dns de mon opérateur.
    en même temps, tu sembles utiliser le pire opérateur qui existe pour suivre les RFC dns (genre changer les TTL a la volée etc…)