Гео-блокировка в nginx — ngx_http_geoip2
Гео-блокировка позволяет разрешить доступ к сайту только из определённых стран. Все остальные получают HTTP 451. Реализуется через модуль ngx_http_geoip2_module и бесплатную базу MaxMind GeoLite2.
Шаг 1 — Установить модуль
apt install libnginx-mod-http-geoip2
Шаг 2 — Скачать базу
Базы берём с GitHub — не нужен аккаунт MaxMind, всегда свежие: github.com/P3TERX/GeoLite.mmdb
mkdir -p /usr/share/GeoIp2 # База городов wget -O /usr/share/GeoIp2/GeoLite2-City.mmdb \ https://github.com/P3TERX/GeoLite.mmdb/raw/download/GeoLite2-City.mmdb # База стран (если нужна только страна — легче) wget -O /usr/share/GeoIp2/GeoLite2-Country.mmdb \ https://github.com/P3TERX/GeoLite.mmdb/raw/download/GeoLite2-Country.mmdb
Шаг 3 — Подключить модуль в nginx.conf
load_module /usr/lib/nginx/modules/ngx_http_geoip2_module.so;
Шаг 4 — Создать geoip2.conf
Файл /etc/nginx/geoip2.conf — подключить базу и задать разрешённые страны:
geoip2 /usr/share/GeoIp2/GeoLite2-City.mmdb {
$geoip2_data_country_code country iso_code;
$geoip2_data_country_name country names en;
}
# 1 — разрешён, 0 — заблокирован
map $geoip2_data_country_code $allowed_country {
default 0;
RU 1; # Россия
AM 1; # Армения
GE 1; # Грузия
US 1; # США
NL 1; # Нидерланды
GB 1; # Великобритания
}
Подключить в nginx.conf внутри блока http {}:
include /etc/nginx/geoip2.conf;
Шаг 5 — Конфиг сайта
Полный пример с прокси на бэкенд (Django, Node и т.д.):
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Страница для заблокированных стран
error_page 451 /geo.html;
location = /geo.html {
root /var/www/errors;
internal;
}
location / {
if ($allowed_country = 0) {
return 451;
}
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
# Редирект HTTP → HTTPS
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
Если сайт отдаёт статику напрямую:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
error_page 451 /geo.html;
location = /geo.html {
root /var/www/errors;
internal;
}
location / {
if ($allowed_country = 0) {
return 451;
}
root /var/www/html;
index index.html;
}
}
Шаг 6 — Перезагрузить nginx
nginx -t && nginx -s reload
Автообновление базы (cron)
База обновляется на GitHub автоматически. Добавить в crontab чтобы всегда была свежая:
0 3 * * 2 wget -q -O /usr/share/GeoIp2/GeoLite2-City.mmdb https://github.com/P3TERX/GeoLite.mmdb/raw/download/GeoLite2-City.mmdb && nginx -s reload
Добавить / убрать страну
Открыть /etc/nginx/geoip2.conf, отредактировать блок map. Коды стран — стандарт ISO 3166-1 alpha-2 (RU, DE, FR, CN...).
nginx -t && nginx -s reload
Проверка
Посмотреть какие страны приходят заблокированными:
awk '{print $10}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20