company_banner

Настройка 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
    Mail.ru Group
    Строим Интернет

    Комментарии 4

      +1
      Хорошо бы сделать свой сервис GeoIP. Наверняка в закромах компания что-то пользует.
        0
        Возможно, но мне об этом неизвестно )
          0
          Так если оно в «закромах», думаете просто так?
          0
          не в курсе что в закромах, но, если честно, не вижу особого смысла

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое