Заметки программиста

Настройка GeoIP

Давайте доработаем вашу GeoIP-блокировку в Nginx так, чтобы:

  1. Разрешить ботов Google и Yandex (даже если они из-за границы).
  2. Логировать все попытки доступа из запрещённых стран — для анализа и отладки.

🎯 Итоговая логика

  • Если запрос от Googlebot / YandexBotразрешить.
  • Иначе, если страна не в списке разрешённыхзаписать в лог и вернуть 403 (или 444).
  • Если страна разрешена → обычный доступ.

🔧 Шаг 1: Настройка GeoIP + определение ботов

Убедитесь, что у вас уже есть в /etc/nginx/nginx.conf (внутри http):

geoip2 /etc/nginx/geoip/GeoLite2-Country.mmdb {
    auto_reload 5m;
    $geoip2_data_country_code source=$remote_addr country iso_code;
}

map $geoip2_data_country_code $allowed_country {
    default no;
    RU yes;
    UA yes;
    BY yes;
    KZ yes;
    # Добавьте другие, если нужно
}

🤖 Шаг 2: Определяем ботов по User-Agent

Добавьте в http:

# Определяем, является ли запрос от бота
map $http_user_agent $is_bot {
    default 0;
    "~*Googlebot" 1;
    "~*Google.*snippet" 1;
    "~*YandexBot" 1;
    "~*YandexImages" 1;
    "~*Yandex" 1;  # осторожно: может быть ложно-положительным
}

⚠️ Важно: User-Agent легко подделать.
Но для легитимных ботов это нормально — они всегда идентифицируют себя честно.

🔒 Для безопасности: не разрешайте критические пути (например, /admin) даже ботам — ограничьте это отдельно.


📝 Шаг 3: Создайте отдельный лог для заблокированных запросов

Создайте файл лога:

sudo touch /var/log/nginx/geoip-blocked.log
sudo chown www-data:adm /var/log/nginx/geoip-blocked.log
sudo chmod 644 /var/log/nginx/geoip-blocked.log

Добавьте в http секцию новый формат лога:

log_format geoip_blocked '$remote_addr - $http_user_agent - $geoip2_data_country_code [$time_local] "$request" $status';

🚦 Шаг 4: Блокировка с логированием и исключениями

Теперь в нужном server (или через ISPConfig → «nginx Directives») добавьте:

# Блокируем всё, кроме ботов и разрешённых стран
if ($allowed_country = no) {
    set $block_geo 1;
}
if ($is_bot = 1) {
    set $block_geo 0;
}
if ($block_geo = 1) {
    access_log /var/log/nginx/geoip-blocked.log geoip_blocked;
    return 403;  # или 444, если не хотите логировать в основном access.log
}

💡 Почему set $block_geo?
Потому что в Nginx нельзя использовать if внутри if, но можно комбинировать через переменные.


🔄 Альтернатива: более надёжная проверка ботов (по IP)

Google и Yandex публикуют официальные IP-диапазоны своих ботов. Это намного надёжнее, чем User-Agent.

Для Google:

  • Список: https://www.google.com/supported_domains → но лучше использовать DNS:
  dig TXT _netblocks.google.com
  dig TXT _netblocks2.google.com
  dig TXT _netblocks3.google.com

Для Yandex:

  • https://yandex.com/support/webmaster/robot-workings/check-yandex-robots.html
  • IP: 5.255.255.0/24, 77.88.55.0/24, 93.158.134.0/23, 95.108.130.0/23, 100.43.80.0/20, 178.154.224.0/22, 2a02:6b8::/32

Но автоматизировать это сложно. Поэтому для простоты оставим User-Agent, но с оговоркой.

Рекомендация: если ваш сайт индексируется, лучше не блокировать ботов вообще, даже из-за границы — иначе сайт пропадёт из поиска!


📊 Шаг 5: Просмотр логов

Посмотреть попытки доступа из-за границы:

tail -f /var/log/nginx/geoip-blocked.log

Пример записи:

91.203.123.45 - Mozilla/5.0 (compatible; AhrefsBot/7.0; +http://ahrefs.com/robot/) - US [07/Oct/2025:17:30:00 +0300] "GET /secret.php HTTP/1.1" 403

🛡️ Шаг 6: (Опционально) Разрешить только официальных ботов

Если хотите максимальной безопасности, создайте отдельный файл с IP-диапазонами:

# /etc/nginx/conf.d/allowed-bots.conf
allow 5.255.255.0/24;   # Yandex
allow 77.88.55.0/24;
allow 93.158.134.0/23;
allow 95.108.130.0/23;
allow 100.43.80.0/20;
allow 178.154.224.0/22;
allow 2a02:6b8::/32;

# Google (пример, лучше обновлять автоматически)
allow 34.0.0.0/15;
allow 35.184.0.0/13;
# ... и т.д.

deny all;

И в server:

location / {
    # Сначала проверяем ботов по IP
    include /etc/nginx/conf.d/allowed-bots.conf;

    # Потом GeoIP
    if ($allowed_country = no) {
        access_log /var/log/nginx/geoip-blocked.log geoip_blocked;
        return 403;
    }

    # ... остальной код
}

Но это требует регулярного обновления IP-списков.


✅ Итоговый конфиг (минимальный рабочий)

В /etc/nginx/nginx.conf (внутри http):

geoip2 /etc/nginx/geoip/GeoLite2-Country.mmdb {
    auto_reload 5m;
    $geoip2_data_country_code source=$remote_addr country iso_code;
}

map $geoip2_data_country_code $allowed_country {
    default no;
    RU yes;
    UA yes;
    BY yes;
    KZ yes;
}

map $http_user_agent $is_bot {
    default 0;
    "~*Googlebot" 1;
    "~*Google.*snippet" 1;
    "~*YandexBot" 1;
    "~*YandexImages" 1;
}

log_format geoip_blocked '$remote_addr - "$http_user_agent" - $geoip2_data_country_code [$time_local] "$request" $status';

В каждом server (или в ISPConfig → nginx Directives):

set $block_geo 0;

if ($allowed_country = no) {
    set $block_geo 1;
}
if ($is_bot = 1) {
    set $block_geo 0;
}
if ($block_geo = 1) {
    access_log /var/log/nginx/geoip-blocked.log geoip_blocked;
    return 403;
}

🧪 Проверка

  1. Зайдите с разрешённого IP → работает.
  2. Зайдите с зарубежного IP → 403 + запись в geoip-blocked.log.
  3. Откройте в браузере с User-Agent Googlebot → доступ разрешён.