Гео-блокировка в 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

Комментарии

Комментариев пока нет.