Настройка GeoIP ACL в HAProxy в два шага

от автора


Hello Planets by Augustinas Raginskis

Иногда возникает задача управления трафиком в зависимости от географического положения клиента. Возможные области применения — блокировка некоторых локаций либо перенаправление трафика на итоговый сервер в зависимости от локации клиента. Традиционно подобные вещи реализуются при помощи библиотек GeoIP компании MaxMind. В статье расскажу, как это сделать.

Настройка доступа к библиотекам MaxMind

Раньше не нужно было настраивать доступ, так как MaxMind предоставляли часть своих библиотек для прямого скачивания по ссылке. Однако сейчас функция прямого скачивания без регистрации недоступна. Поэтому сначала нужно зарегистрироваться здесь, заполнив форму:

После этого шага вам на почту придет письмо с дальнейшими инструкциями:

Перейдите по ссылке для создания пароля:

После завершения регистрации вы попадете в личный кабинет:

Чтобы скачивать файлы MaxMind напрямую, необходимо выписать лицензию на сайте. Для этого нужно перейти по ссылке My License Key:

Далее:

Далее:

На экране отобразится номер лицензии, который нужно сохранить — потом увидеть его будет нельзя, только выписывать новую лицензию:

Теперь, с номером лицензии, можно скачивать файлы баз данных GeoIP. Как это сделать написано тут.

Дальше переходим по ссылке: https://www.maxmind.com/en/accounts/current/geoip/downloads, и нажимаем линк Get permalinks напротив базы данных GeoLite2 Country: CSV Format:

В следующем окне указаны ссылки на скачивание:

Обратите внимание, что нужно заменить YOUR_LICENSE_KEY на вашу лицензию, которую вы выписали ранее. 

На этом настройка получения базы GeoIP закончена, переходим непосредственно к настройке.

Настройка HAProxy

HAProxy не умеет работать напрямую с базами MaxMind, однако умеет строить ACL на основе списков сетей. Вот как это описывается в конфиге HAProxy:

frontend frontend-https     bind *:80  # GeoIP ACL     acl acl_SNG src -f /etc/haproxy/geoip/SNG.txt

Содержимое файла /etc/haproxy/geoip/SNG.txt:

... 188.215.252.0/22 188.237.0.0/16 188.240.70.0/24 188.244.16.0/20 191.96.60.0/23 192.121.87.0/24 193.8.167.0/24 193.16.111.0/24 193.17.78.0/24 ...

То есть файл SNG.txt содержит в себе список сетей, которые попадут в ACL.

Перед нами стоит задача автоматизировать создание файла со списком сетей из баз данных MaxMind.

Сформулируем задачу, которую мы хотим решить: необходимо, чтобы трафик из России, Беларуси и Украины шел на один бэкенд, а трафик из других локаций уходил на другой бэкенд. Для решения этой задачи напишем shell-скрипт. Скрипт будет состоять из нескольких этапов.

Сначала получим свежую копию базы данных MaxMind в формате csv:

# Download geoip2 lite csv database wget  "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country-CSV&license_key=${MAXMIND_LICENSE}&suffix=zip" -qO geoip2lite.zip  && unzip -j geoip2lite.zip

Здесь ${MAXMIND_LICENSE} — это номер лицензии, который мы выписали ранее на сайте MaxMind.

После выполнения команды содержимое архива будет выглядеть так:

root@ash:/tmp/geo2lite# ls -1 COPYRIGHT.txt GeoLite2-Country-Blocks-IPv4.csv GeoLite2-Country-Blocks-IPv6.csv GeoLite2-Country-Locations-de.csv GeoLite2-Country-Locations-en.csv GeoLite2-Country-Locations-es.csv GeoLite2-Country-Locations-fr.csv GeoLite2-Country-Locations-ja.csv GeoLite2-Country-Locations-pt-BR.csv GeoLite2-Country-Locations-ru.csv GeoLite2-Country-Locations-zh-CN.csv LICENSE.txt README.txt

Нас интересуют два файла — GeoLite2-Country-Blocks-IPv4.csv, содержащий информацию о принадлежности сетей ipv4 странам, и GeoLite2-Country-Locations-en.csv, содержащий соответствия названий стран цифровым кодам.

Соответственно, если нам нужно получить все сети, принадлежащие России, мы для начала получаем код России:

root@ash:/tmp/geo2lite# cat GeoLite2-Country-Locations-en.csv | grep  Russia 2017370,en,EU,Europe,RU,Russia,0

Здесь 2017370 — это искомый код.

Теперь по нему можно определить сети. 

root@ash:/tmp/geo2lite# cat GeoLite2-Country-Blocks-IPv4.csv | grep 2017370 ... 217.147.16.0/20,2017370,2017370,,0,0 217.148.48.0/20,2017370,2017370,,0,0 217.148.192.0/19,2017370,2017370,,0,0 217.149.16.0/20,2017370,2017370,,0,0 217.149.176.0/20,2017370,2017370,,0,0 217.150.0.0/18,2017370,2017370,,0,0 217.150.72.0/21,2017370,2017370,,0,0 217.150.192.0/20,2017370,2017370,,0,0

Обратите внимание, что число 2017370 встречается в каждой строке два раза. Обратимся к описанию формата файла:

root@ash:/tmp/geo2lite# cat GeoLite2-Country-Blocks-IPv4.csv | head -n 1 network,geoname_id,registered_country_geoname_id,represented_country_geo name_id,is_anonymous_proxy,is_satellite_provider

Здесь registered_country_geoname_id — код страны, за которой зарегистрирована сеть, а represented_country_geoname_id — код страны, из которой происходит роутинг сети. 

Возможна ситуация, когда сеть зарегистрирована, например за Россией, а роутинг происходит из Голландии. Как поступать в такой ситуации, решайте сами, я выбирал только сети, зарегистрированные и маршрутизируемые из запрашиваемой страны.

Соответственно, выбирая нужные сети из файла GeoLite2-Country-Blocks-IPv4.csv, можно сформировать файл для HAProxy ACL.

Сама работа с ACL в HAProxy:

frontend frontend # GeoIP ACL     acl acl_SNG src -f /etc/haproxy/geoip/SNG.txt      use_backend backend1 if acl_SNG     default_backend backend2

Соответственно, если IP-адрес источника будет из сети, описанной в файле SNG.txt, то запрос уйдет на backend1, в противном случае — на backend2.

Для автоматизации операций был написан скрипт:

root@ash:~# cat haproxy_geoip_list.sh #!/bin/bash #----------------------------------------------------------------------------------------------------------------------- # Variables TMPDIR="/tmp/geo2lite" MAXMIND_LICENSE="xxxxxxxxxxxxx" LOCATIONS="Russia Ukraine Belarus" HAPROXY_PATH="/etc/haproxy/geoip" HAPROXY_FILE="SNG.txt" #----------------------------------------------------------------------------------------------------------------------- mkdir -p ${TMPDIR} pushd ${TMPDIR} # Download geoip2 lite csv database wget  "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country-CSV&license_key=${MAXMIND_LICENSE}&suffix=zip" -qO geoip2lite.zip  && unzip -j geoip2lite.zip if [ $? -gt 0 ]; then  logger -t "haproxy_geoip" "Download not success."  exit 1 fi  exit for COUNTRY in ${LOCATIONS}; do  echo "# ${COUNTRY}"  COUNTRY_CODE=`cat GeoLite2-Country-Locations-en.csv | grep -i  "${COUNTRY}" | awk -F "," '{print $1}'`  grep ",${COUNTRY_CODE}," GeoLite2-Country-Blocks-IPv4.csv | awk -F ","  '{print $1}' done > ${HAPROXY_FILE}  # Check file if [ ! -s ${HAPROXY_FILE} ]; then     logger -t "haproxy_geoip" "File is not exist"     exit 1 fi  if [ -s ${HAPROXY_PATH}/${HAPROXY_FILE} ]; then     MD5_FILE=`md5sum ${HAPROXY_PATH}/${HAPROXY_FILE} | awk '{print $1}'` fi  MD5_TMPFILE=`md5sum ${HAPROXY_FILE} | awk '{print $1}'`  if [ "${MD5_TMPFILE}" != "${MD5_FILE}" ]; then  logger -t "haproxy_geoip" "File ${HAPROXY_FILE} is changed"  cp ${HAPROXY_PATH}/${HAPROXY_FILE}  ${HAPROXY_PATH}/${HAPROXY_FILE}.backup  mv ${HAPROXY_FILE} ${HAPROXY_PATH}/${HAPROXY_FILE}  # Test new haprpoxy cfg  /usr/sbin/haproxy -c -f /etc/haproxy/haproxy.cfg  if [ $? -gt 0 ]; then   logger -t "haproxy_geoip" "New file is corrupted, replace by older one from backup."   mv ${HAPROXY_PATH}/${HAPROXY_FILE}.backup  ${HAPROXY_PATH}/${HAPROXY_FILE}  fi fi  popd rm -rf "${TMPDIR}"

Перед запуском не забудьте заполнить секцию Variables под ваши нужды.

Удачи!

Написано при поддержке Mail.ru Cloud Solutions

Что еще почитать

  1. Как ограничить частоту запросов в HAProxy: пошаговая инструкция.
  2. Лучшие практики и рекомендации для запуска контейнеров и Kubernetes в производственных средах.
  3. Наш телеграм-канал о цифровой трансформации и IT

ссылка на оригинал статьи https://habr.com/ru/company/mailru/blog/502168/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *