Привет! Сегодня хотим поделиться простым способом защиты от L7 DDoS-атак.  Есть и другие варианты, но описанный в статье — лёгкий и быстрый.

В 2022 году был момент, когда мониторинги показали, что в определённое время на сайты наших клиентов, среди которых были и государственные организации, совершаются L7 DDoS-атаки. Надо было этому противостоять.

Самое быстрое и  простое, что приходило на ум — это запрет доступа к сайтам для всех пользователей не из России. Это действительно не сложно. Геоблокировка осуществляется через Nginx, а главная  задача заключается в сопоставлении адреса клиента и его вероятного физического местонахождения (страна источника).

Возможно, вы тоже знаете про замечательный сервис, который работает с 2002 года: MaxMind. Он ведёт базу данных IP-адресов и их месторасположения. Всё хорошо, но есть нюанс: MaxMind сообщил, что прекращает поддержку баз данных GeoIP Legacy с 31 мая 2022 г. и переходит на новой стандарт базы данных GeoIP2. Кроме того, он вроде как ушёл из России.

Суть письма

Уважаемый пользователь GeoLite!

В целях соблюдения санкций США в отношении определённых российских организаций MaxMind реализует своё право прекратить ваш бесплатный доступ к базам данных или веб-сервисам GeoLite2 в соответствии с разделом 10 (b) Лицензионного соглашения с конечным пользователем GeoLite2. 

Учётная запись больше не будет иметь доступа к базам данных или веб-сервисам GeoLite2 в понедельник, 25 апреля 2022 г.

Сначала попробовал зарегистрироваться в MaxMind из РФ (с почтовым доменом RU), но при регистрации нельзя было выбрать Россию.

Выбрал Турцию — ошибка (возможно, вы используете VPN или PROXY). Ну, дело привычное — использую все те же данные, но с турецкого IP. Регистрация пройдена успешно, можно входить в личный кабинет и скачивать актуальные базы Geo2Lite.

Есть и второй способ получения баз Geolite/Geo2lite бесплатно, без регистрации и СМС. Имею в виду сервис GeoIP Legacy. С мая 2022 года один хороший человек регулярно конвертирует базы с Geo2 в Geo, указывая дату обновления текущей БД.

Для версии Geo2 есть второй хороший человек, который делится в репозитории базами, но, к сожалению, без указания даты актуализации.

Итак, с вопросом о том, где брать базы данных, мы разобрались. Дальше нужно понять, какая ОС стоит на сервере, куда будем устанавливать модуль GeoIP для Nginx.

Если же у нас Ubuntu 20/22, то модули для GeoIP и geo GeoIP2 уже есть в стандартных репах:

libnginx-mod-http-geoip2
libnginx-mod-http-geoip

Ставятся просто: apt install libnginx-mod-http-geoip2 либо apt install libnginx-mod-http-geoip

Если стоит, допустим CentOS 8, то в стандартных репах отсутствует нужный нам модуль. Придётся перекомпиливать Nginx, чтобы добавить модуль geoip2. Кстати, модуль geoip2 отсутствует в исходниках Nginx, так как он есть только в платной версии Nginx Plus.

Но сам модуль есть на гитхабе, оттуда его и возьмём.

Существует два варианта сборки. 

  • Первый: собрать со статическим модулем и пересобрать весь бинарник Nginx.

  • Второй: собрать только динамический модуль и подключить его в конфиг, не пересобирая весь Nginx.

В любом случае рекомендуется после обновления Nginx заново пересобирать модуль для новой версии Nginx. Более логичным выглядит решение скомпилить только динамический модуль.

Все операции выполняем на CentOS 8.

Клонируем репу с модулем GeoIP2:

git clone https://github.com/leev/ngx_http_geoip2_module.git 

Ставим библиотеку MaxMind в CentOS 8, которая есть в репах, yum install libmaxminddb.x86_64, либо собираем по инструкции.

Далее нужен исходник Nginx нашей версии. Узнать его можно командой nginx -v

В моем случае это выглядит так:  nginx version: nginx/1.14.1

Скачаем исходник нашей версии Nginx

wget http://nginx.org/download/nginx-1.14.1.tar.gz
tar -xvf  nginx-1.14.1.tar.gz
cd nginx-1.14.1/

получаем вывод с nginx -V, копируем всё после --prefix=/... и добавляем  --add-module=/root/ngx_http_geoip2_module (путь к модулю, скачанного с гитхаба).

У меня получилась такая строка:

Вывод

./configure --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-file-aio --with-ipv6 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-http_auth_request_module --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-debug --with-cc-opt='-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E' --add-dynamic-module=/root/ngx_http_geoip2_module

Дальше будут появляться сообщения, что не получается выполнить сборку из-за нехватки определенных библиотек. В моём случае получился такой список:

yum install gcc gcc-c++ kernel-devel pcre-devel zlib-devel openssl-devel libxslt-devel install libgeoip-dev libgeoip-dev gd gd-devel perl-ExtUtils-Embed -y

Выполняем make modules (именно так, а не make install, чтобы не пересобирать весь Nginx).

и в папке /root/nginx-1.14.1/objs/ngx_http_geoip2_module.so должен появиться наш модуль.

Копируем его в  /usr/share/nginx/modules/ командой cp ngx_http_geoip2_module.so /usr/share/nginx/modules/

Подключаем модуль в конфиге

/etc/nginx/nginx.conf
load_module modules/ngx_http_geoip2_module.so;

В папку /usr/share/GeoIP/ копируем нашу базу GeoLite2-Country.mmdb 

В конфиге http прописываем

geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
        $geoip2_data_country_iso_code country iso_code;
        $geoip2_data_continent_code   continent code;
    }

  #здесь запрещаем доступ всем, кроме разрешенных стран
    map $geoip2_data_country_iso_code $allowed_country {
       default no;
       RU yes;
    }

Наверное, нет смысла копипастить сюда инструкцию по автоматическому обновлению баз Geo2Lite с сервера MaxMind. Если вам она нужна, вот ссылка.

На практике нужно разрешать и другие сети в других странах (либо адреса).

Добавим в тот же конфиг http

  geo $exclusions {

        default 0;

        123.123.123.123 1;  # сюда прописываем сети либо адреса, которым разрешаем независимый доступ
        12.13.11.0/24 1;
    }

В конфиге server указываем 

if ($allowed_country = yes) {
    set $exclusions 1;
}

if ($exclusions = "0") {
    return 403;
}

Не помешает и добавить логи стран, с которых приходят запросы. Для этого в log_format  main нужно добавить $geoip2_data_country_iso_code

Должно получиться что-то вроде такого:

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"' "$geoip2_data_country_iso_code";

Ещё можно поменять страницу для ответа 403

        error_page 403 @not_allowed;
                location @not_allowed {
                 try_files /my_403_error.html 403;
       }

и саму страницу положить в root location. В моём случае это /usr/share/nginx/html/my_403_error.html

Сама страница:
<h1>Oops, error 403. Access denied.</h1>
<p>You do not have permission to access the page, let's try to solve this problem together:</p>
<li>Let us know by mail: mail@domain.com and we will try to solve the problem together.</li>
</ul>

Таким нехитрым способом можно защитить сайты от внешних угроз, если нужно быстрое решение. Нам помогло, атаки сошли на нет. Спасибо за внимание!

Комментарии (6)


  1. xxxphilinxxx
    18.05.2023 07:10
    +4

    Добропорядочные пользователи, находящиеся за рубежом, видимо, тоже лишились доступа к сервису: в голове крутятся выражения "рубить с плеча" и "лес рубят - щепки летят". Ну и если атаки будут с диапазонов айпишников внутри страны - эта защита в нынешнем виде не сработает.


    1. avacha
      18.05.2023 07:10
      +1

      Мне вот ещё другое интересно. В письме MaxMind ссылается на лицензионное соглашение. Получается, что базу данных хостинг использует в нарушение лицензионного соглашения, сиречь пиратскую. Которая, получается, юридически ничем не отличается юридически от пиратского Windows, Office или там AutoCAD. Конечно, можно сказать, что некий Васян выкладывает копии дампов на другой сервис и мы качали не с официального сайта - ну так сборки дистрибутивов Windows Vasya Edition SupaDupa - скачаны с торрента, однако от этого волшебным образом лицензионными не становятся.


    1. Vitaly83vvp
      18.05.2023 07:10

      Основной момент тут `если нужно быстрое решение`. Хотя, сам метод определения по IP далеко не 100% решение. IP пулы продаются и покупаются во всём мире и нет гарантии, что всё будет точным. Даже со своевременным обновлением баз.


  1. zlo1
    18.05.2023 07:10

    Есть сервисы предоставляющие по запросу (web api) не только регион IP, но и принадлежность (резидентность, провайдер) , а также является ли он прокси / VPN / TOR


  1. NikaLapka
    18.05.2023 07:10
    +2

    Ох уж эти базы.., помню как однажды оказался посреди океана... :)


  1. ifap
    18.05.2023 07:10
    +8

    Всё хорошо, но есть нюанс:

    Есть еще такой нюанс, о котором забывают госорганы: россиянин - это не тот, кто сидит дома на печи и ест патриотичные калачи, а гражданин России, который может находиться в моменте и за ее пределами. Скажем, поехали наши туристы в Конго, попали там... в общем, попали, хотят обратиться за помощью в посольство, отправляются на сайт МИДа искать его телефон и видят: пойдите прочь, неруси, вам тут не рады! Того, кто придумал ограничивать досту к госсайтам по географическому признаку, стоило бы судить по новой статье за дискредитацию органов власти.