ZIM-НИЙ SAAALEЗимние скидки: до −50% на старт и −20% на продление
до 31.01.2026 Подробнее
Выберите продукт

Nginx allow/deny и IPv6: как ограничить доступ к админке и не заблокировать себя

Разбираем, как в Nginx работают allow/deny для IPv4 и IPv6, какие префиксы указывать и почему «IPv6 allow» часто не совпадает с реальностью. Даю безопасные шаблоны для /admin и отдельного admin-домена, диагностику 403/401, проверку real IP за прокси/CDN и связку с auth_basic/htpasswd.
Nginx allow/deny и IPv6: как ограничить доступ к админке и не заблокировать себя

IPv6 в проде обычно появляется «сам»: его выдаёт провайдер, панель на сервере включает стек по умолчанию, а клиентские устройства охотно ходят по AAAA-записям. Поэтому админка, закрытая только по IPv4, нередко остаётся доступной по IPv6 — даже если вы не публиковали AAAA в DNS или «не планировали использовать v6».

Nginx применяет allow/deny одинаково для IPv4 и IPv6, но на практике ошибки возникают из-за неверного префикса, неожиданного реального адреса клиента (CDN/балансировщик) и неподходящего location. Ниже — рабочие шаблоны и проверенные приёмы, чтобы не отрезать себя и действительно закрыть админку.

Зачем учитывать IPv6 в allow/deny

Главная причина — «ложная безопасность». Админка может быть недоступна по IPv4, но полностью открыта по IPv6-адресу сервера. Это особенно частая история на VDS, где IPv6 выдаётся автоматически, а администратор проверяет доступ только со своего IPv4.

Вторая причина — «ложные блокировки»: вы разрешили один IPv6-адрес (/128), а у провайдера он сменился (SLAAC, privacy extensions) или у вас несколько устройств в одном /64. В итоге «свои» начинают получать 403.

Если вы сейчас как раз наводите порядок в IPv6 на сервере, полезно держать под рукой материал про адресацию и выдачу префиксов: SLAAC, DHCPv6 и маршрутизация IPv6 на сервере.

Как Nginx применяет allow/deny: порядок и контекст

Директивы allow/deny проверяются на уровне контекста, где вы их объявили: http, server, location. Внутри одного контекста Nginx читает правила сверху вниз и применяет первое совпадение. Если совпадений нет — доступ разрешён, пока вы явно не указали deny all.

Первое совпавшее правило «побеждает». Поэтому типовая схема для админки — сначала allow, потом deny all.

Базовый шаблон: разрешить своим, запретить остальным

Самая предсказуемая схема — allowlist адресов/сетей и запрет «всем остальным» в конце:

location /admin/ {
    allow 203.0.113.10;
    allow 198.51.100.0/24;
    deny all;
}

Этот же шаблон применим к IPv6 — меняется только формат адресов и префиксы.

На практике такие ACL чаще всего настраивают на отдельном сервере или фронтенде перед приложением. Если админка крутится на выделенном окружении, удобнее делать это на VDS, чтобы правила были изолированы от остальных сайтов.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Пример конфигурации Nginx с allow/deny для IPv6-подсети

IPv6 в allow/deny: синтаксис и правильные префиксы

IPv6-адреса указываются в обычном виде; подсети — в CIDR с префиксом (/64, /56, /128 и т.д.). Nginx сам определит, какое семейство адресов у клиента, и сопоставит с правилами.

Разрешить один IPv6-адрес (хост)

location /admin/ {
    allow 2001:db8:abcd:1234::10;
    deny all;
}

Формально это эквивалент /128. Если хотите подчеркнуть «строго один адрес», укажите префикс явно:

location /admin/ {
    allow 2001:db8:abcd:1234::10/128;
    deny all;
}

Разрешить клиентскую сеть /64

Для домашней/офисной IPv6-сети чаще всего практичнее разрешать весь /64. Так вы не потеряете доступ при смене адреса на интерфейсе или из-за privacy extensions.

location /admin/ {
    allow 2001:db8:abcd:1234::/64;
    deny all;
}

Смешанный allowlist: IPv4 + IPv6

location /admin/ {
    allow 203.0.113.10;
    allow 198.51.100.0/24;
    allow 2001:db8:abcd:1234::/64;
    deny all;
}

Почему «разрешил IPv6, а не работает»

Почти всегда причина одна из этих:

  • клиент приходит через обратный прокси/CDN, и $remote_addr — это адрес прокси, а не клиента;
  • правила лежат не в том location, либо матчится другой, более специфичный location;
  • указан неверный префикс (например, ожидали /64, а разрешили слишком узко);
  • клиент реально идёт по IPv4 (или наоборот), а правила заданы только для одного семейства;
  • в конфиге есть более ранний запрет (например, deny all в другом блоке), который перекрывает ожидаемое поведение.

Проверяем, какой IP видит Nginx: $remote_addr и X-Forwarded-For

Прежде чем править ACL «вслепую», зафиксируйте, какой адрес Nginx считает адресом клиента. Самый быстрый способ — временно добавить отладочный лог-формат:

log_format acl_debug '$remote_addr - $http_x_forwarded_for - $host "$request"';
access_log /var/log/nginx/acl_debug.log acl_debug;

Сделайте несколько запросов из «разрешённой» сети и посмотрите лог:

tail -n 50 /var/log/nginx/acl_debug.log

Если там видны адреса балансировщика/прокси — ваши allow/deny сейчас фильтруют именно прокси. Варианта два: либо режете доступ на уровне прокси, либо настраиваете восстановление реального IP через real_ip_header, set_real_ip_from и при необходимости real_ip_recursive.

Не доверяйте IP-заголовкам «от всех». В set_real_ip_from указывайте только собственные прокси/балансировщики, иначе клиент сможет подставить нужный адрес и обойти ACL.

Если вы используете специфичные схемы доступа для IPv6 (например, NAT64/DNS64), полезно заранее понимать, как именно клиентская сторона выходит к вашему сервису: NAT64/DNS64 на VDS: что ломается и как диагностировать.

Два слоя защиты: allow/deny + nginx basic auth (auth_basic)

IP-allowlist — хороший первый барьер, но для админок почти всегда стоит включать второй слой: basic auth. Это спасает в ситуациях, когда allowlist слишком широк (например, офисный Wi‑Fi), адрес «утёк», или вы временно открыли доступ для диагностики.

Как сочетать auth_basic с ACL

Практичный порядок — сначала IP-фильтр, затем basic auth. Тогда «чужие» даже не увидят окно ввода логина/пароля и получат 403:

location /admin/ {
    allow 203.0.113.10;
    allow 2001:db8:abcd:1234::/64;
    deny all;

    auth_basic "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd;
}

Создаём файл htpasswd

Чаще всего используют утилиту htpasswd (пакет apache2-utils или httpd-tools).

sudo apt-get update
sudo apt-get install -y apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd admin

Добавить второго пользователя без пересоздания файла:

sudo htpasswd /etc/nginx/.htpasswd ops

Права на файл — так, чтобы воркеры Nginx могли читать, а остальные пользователи на сервере нет:

sudo chown root:nginx /etc/nginx/.htpasswd
sudo chmod 640 /etc/nginx/.htpasswd

Группа может быть www-data или nginx — ориентируйтесь на пользователя/группу, под которыми работают воркеры.

Если админка доступна по HTTPS (а так и должно быть), заранее проверьте корректность сертификата и цепочки. При необходимости можно выпустить и установить SSL-сертификаты для отдельного admin-домена.

FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

Где размещать правила: server или location

Если закрываете только админ-раздел — размещайте правила в точном location для админки. Если админка вынесена на отдельный домен/поддомен — часто удобнее закрыть весь server.

Закрыть весь vhost (удобно для отдельного admin-домена)

server {
    listen 443 ssl;
    server_name admin.example.com;

    allow 203.0.113.10;
    allow 2001:db8:abcd:1234::/64;
    deny all;

    auth_basic "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd;

    location / {
        proxy_pass http://backend;
    }
}

Закрыть только часть сайта (/wp-admin/ или /panel/)

location ~ ^/(wp-admin|panel)/ {
    allow 198.51.100.0/24;
    allow 2001:db8:abcd:1234::/64;
    deny all;

    auth_basic "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd;
}

С regex-location будьте аккуратны: проверьте, что не закрыли лишнее и не оставили обходные URI. Для некоторых CMS безопаснее использовать несколько точных location без регулярных выражений.

Схема прокси и балансировщика, из-за которых меняется видимый IP клиента

IPv6 и прокси/CDN: почему ACL часто «ломается»

Если Nginx стоит за CDN, облачным балансировщиком или внутренним reverse proxy, то $remote_addr будет адресом ближайшего прокси. В этом случае allowlist «по IP клиента» не сработает, пока вы не настроите real IP и не ограничите доверие заголовкам источниками прокси.

Минимальная мысль, которую стоит вынести: сначала добейтесь, чтобы в логах и в $remote_addr был реальный адрес клиента (или хотя бы адрес вашего доверенного прокси), и только затем шлифуйте allow/deny.

Как не заблокировать себя: безопасный план изменений

  • Держите вторую активную SSH-сессию, пока тестируете конфиг.
  • Проверяйте синтаксис перед применением изменений:
sudo nginx -t
  • Проверьте порядок: сначала allow, затем deny all.
  • Временно добавьте «аварийный» allow для вашего текущего IPv4 и IPv6 (если используете), а после тестов уберите.
  • Тестируйте «снаружи»: запрос из разрешённой сети и из неразрешённой (например, мобильный интернет).

Диагностика по кодам ответов: 403 и 401

Когда вы комбинируете allow/deny и auth_basic, статусы быстро показывают, что именно сработало:

  • 403 Forbidden — запрос отрезан ACL (или другими правилами доступа), до basic auth могло не дойти.
  • 401 Unauthorized — сработал auth_basic (нужны учётные данные или они неверные).
  • 200/302 — доступ разрешён, дальше уже логика приложения.

Если ожидаете 401, но видите 403 — почти наверняка не совпал IP или сработал более ранний запрет в другом месте конфигурации.

Практические рецепты для защиты admin panel

Рецепт 1: доступ только с офисного IPv6 /64 и одного IPv4

location /admin/ {
    allow 203.0.113.10;
    allow 2001:db8:abcd:1234::/64;
    deny all;

    auth_basic "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd;
}

Рецепт 2: доступ только через VPN-подсети (v4 и v6)

location /panel/ {
    allow 10.10.0.0/16;
    allow fd00:10:10::/48;
    deny all;

    auth_basic "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd;
}

Если у вас есть внутренний IPv6 (ULA) — это часто самый чистый вариант: доступ «из интернета» закрыт полностью, остаётся только VPN.

Рецепт 3: запретить всё, кроме healthcheck (и не забыть IPv6)

location = /healthz {
    allow 203.0.113.0/24;
    allow 2001:db8:1111::/48;
    deny all;
    return 200;
}

location / {
    deny all;
}

Чек-лист перед продом

  • Вы понимаете, какой IP видит Nginx: $remote_addr соответствует клиенту, а не прокси.
  • Для IPv6 выбран корректный префикс (обычно /64 для клиентской сети, /128 для одного адреса).
  • В нужном location правила идут в правильном порядке: allow… затем deny all.
  • auth_basic включён там, где нужен, а auth_basic_user_file доступен воркерам Nginx.
  • Есть план отката и рабочий SSH-доступ на случай блокировки.

Итого

allow/deny в Nginx отлично работает и для IPv6 — если вы фильтруете реальный адрес клиента и правильно выбираете префиксы. Для админки наиболее надёжный и практичный вариант — два слоя: allowlist (IPv4+IPv6) и basic auth через auth_basic/htpasswd. Так вы заметно снижаете поверхность атаки и проще переживаете ошибки в сетях и прокси-настройках.

Поделиться статьей

Вам будет интересно

Apache HTTP/2: h2, ALPN и PHP-FPM через proxy_fcgi — настройка и диагностика OpenAI Статья написана AI (GPT 5)

Apache HTTP/2: h2, ALPN и PHP-FPM через proxy_fcgi — настройка и диагностика

Пошагово включаем HTTP/2 в Apache через mod_http2: как работает h2 и ALPN, какие требования к TLS и MPM, как правильно проксироват ...
Apache HTTP/2 (h2), ALPN и PHP-FPM: настройка и типовые проблемы OpenAI Статья написана AI (GPT 5)

Apache HTTP/2 (h2), ALPN и PHP-FPM: настройка и типовые проблемы

Пошагово включаем HTTP/2 (h2) в Apache: проверяем mod_http2, работу ALPN и настройки TLS, задаём Protocols во vhost’ах и подключае ...
Nginx: allow/deny и IPv6 — как правильно ограничить доступ OpenAI Статья написана AI (GPT 5)

Nginx: allow/deny и IPv6 — как правильно ограничить доступ

Разберём, как в Nginx работают allow/deny с IPv6: порядок обработки правил, CIDR для адресов и подсетей, типовые ошибки dual-stack ...