HAProxy est un reverse proxy tcp et http(s), souvent utilisé en frontal d'applications web. Il est simple à installer, fiable, léger et performant.
Il permet de faire du partage de charge, des sticky sessions, du filtrage par IP, des ré-écritures (URL, entêtes,...), de présenter les certificats HTTPS et bien d'autres choses encore.
Cependant HAProxy n'a pas de fonction native de géolocalisation, mais lui ajouter cette possibilité n'est pas si compliqué comme nous allons le voir ici.
Ajouter un entête HTTP contenant le code du pays d'origine de l'IP du client permet non seulement d'écrire des ACL HAProxy qui utilisent cette information, mais également de la transmettre aux éventuels reverse proxys suivants et aux serveurs applicatifs eux-mêmes.
HAProxy peut utiliser comme source de données des fichiers de type clé-valeur (appelés maps), qu'il charge en mémoire et qui permettent de très bonnes performances, même avec un grand nombre d'entrées.
Ajouter l'entête X-Country se fait en une seule simple ligne de configuration:
http-request set-header X-Country %[src,map_ip(ip2location.lst)]
Elle indique au logiciel de fixer l'entête "X-Country" à partir de la valeur correspondante à la clé "src". Dans HAProxy "src" est une variable automatiquement renseignée avec l'IP du client. La fonction map_ip recherche dans le fichier ip2location.lst la clé de type IP et retourne la valeur associée.
Voilà, c'est fini.
Il suffit maintenant de se procurer le contenu du fichier ip2location.lst.
Le format attendu du fichier ip2location.lst est une suite de lignes CIDR CODE-PAYS du type:
1.0.4.0/22 AU
1.0.8.0/21 CN
1.0.16.0/20 JP
1.0.32.0/19 CN
Il existe plusieurs fournisseurs de base de données de géolocalisation, notamment gratuites dans leurs versions lite, par exemple GeoIP, ou ip2location.
Dans la suite nous allons utiliser la base lite d'ip2location.
Pour pouvoir télécharger cette base, il est nécessaire de créer un compte sur le site et d'obtenir un token. Ce token permet de télécharger la base soit au format binaire soit au format CSV (c'est celui-ci qui nous convient le mieux).
Un extrait du contenu CSV est le suivant:
"16777216","16777471","US","United States of America"
"16777472","16778239","CN","China"
"16778240","16779263","AU","Australia"
Mouais... bon déjà la dernière colonne ne nous interesse pas des masses. Après la première et seconde colonne sont de toute évident l'IP de début et de fin d'une plage au format numérique (les 4 octets de l'IP formant un nombre donc).
Comme HAProxy attend un CIDR et non une plage il va nous falloir retravailler le fichier. Heureusement, HAProxy est fourni avec un petit outil (en tous cas dans la Debian) appelé iprange et qui va faire le plus gros du travail.
L'outil est fourni sous forme de code source C, dans le répertoire /usr/share/doc/haproxy/contrib/iprange.
Pour le compiler il suffit de faire:
apt install gcc
cd /usr/share/doc/haproxy/contrib/iprange/
gunzip iprange.c.gz
gcc -o /usr/local/bin/iprange iprange.c
apt autoremove --purge gcc
L'outil attend une suite de lignes commençant chacune par deux IP formant une plage (séparées par des espaces, des tabulations ou des virgules ). Il transforme alors ces deux IP en notation CIDR et reprend le reste de la ligne sans modification.
Générer notre fichier ip2location.lst est donc relativement facile:
iprange < IP2LOCATION-LITE-DB1.CSV |sed 's/,/ /g'|awk '{print $1 " " $2}'|tr -d '"' > /etc/haproxy/ip2location.lst
On obtient un fichier du type:
0.0.0.0/8 -
1.0.0.0/24 US
1.0.1.0/24 CN
1.0.2.0/23 CN
Evidemment il est alors possible d'automatiser les opérations pour mettre à jour la liste régulièrement.