Привет! Сегодня хотим поделиться простым способом защиты от 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>
Таким нехитрым способом можно защитить сайты от внешних угроз, если нужно быстрое решение. Нам помогло, атаки сошли на нет. Спасибо за внимание!