Ограничение доступа по IP в Nginx
Пошаговая настройка доступа к сайту или отдельному location в Nginx только с разрешённых IP-адресов и подсетей.
Nginx позволяет разрешать или запрещать доступ к сайту, административному разделу или отдельному URL по IP-адресу клиента.
Такой способ подходит для:
- административных панелей;
- внутренних API;
- служебных страниц;
- тестовых сайтов;
- webhook endpoint;
- страниц мониторинга;
- временно закрытых разделов.
В этой инструкции рассматривается только ограничение доступа по IPv4 и IPv6 с помощью директив allow и deny.
Проверено на: Ubuntu Server 24.04 LTS
Уровень сложности: начальный
Время выполнения: около 10–15 минут
Требуемый доступ: пользователь с правамиsudo
Что будет настроено
После выполнения инструкции можно будет:
- разрешить доступ одному IP;
- разрешить доступ подсети;
- закрыть сайт для остальных клиентов;
- ограничить только отдельный
location; - проверить порядок правил;
- учитывать reverse proxy и
X-Forwarded-For; - диагностировать ошибку
403 Forbidden; - безопасно отменить ограничение.
Важное предупреждение
Ошибка в IP-правилах может заблокировать доступ администратора.
Перед применением:
- оставьте открытую SSH-сессию;
- запишите свой внешний IP;
- проверьте, используется ли VPN;
- учтите динамический IP;
- проверьте наличие reverse proxy;
- создайте резервную копию конфигурации.
Определение текущего IP
С административного компьютера узнайте публичный IP.
В Linux:
curl -4 ifconfig.me
Для IPv6:
curl -6 ifconfig.me
Если команда выполняется через VPN, будет показан адрес VPN.
Проверка адреса в журнале Nginx
Создайте запрос к сайту:
curl -I https://example.com
На сервере:
sudo tail -20 /var/log/nginx/access.log
Если для сайта используется отдельный журнал:
sudo tail -20 /var/log/nginx/example.com.access.log
Первое поле обычно содержит IP клиента.
Базовый принцип allow и deny
Пример:
allow 192.0.2.10;
deny all;
Nginx проверяет правила сверху вниз.
Если IP совпал с allow, доступ разрешён.
Остальные клиенты попадут под:
deny all;
и получат:
403 Forbidden
Разрешение одного IPv4-адреса
Откройте конфигурацию сайта:
sudo nano /etc/nginx/sites-available/example.com
Внутри server добавьте:
server {
listen 80;
listen [::]:80;
server_name example.com;
allow 192.0.2.10;
deny all;
root /var/www/example.com/html;
index index.html;
}
Замените:
192.0.2.10
на разрешённый IP.
Разрешение нескольких IP
allow 192.0.2.10;
allow 198.51.100.25;
allow 203.0.113.15;
deny all;
Порядок важен: deny all должен находиться после разрешающих правил.
Разрешение подсети
Для подсети /24:
allow 192.0.2.0/24;
deny all;
Это разрешает диапазон:
192.0.2.0–192.0.2.255
Для одной рабочей станции лучше указывать конкретный адрес /32.
Разрешение localhost
Для локальных запросов:
allow 127.0.0.1;
allow ::1;
deny all;
Это удобно для:
- локального мониторинга;
- healthcheck;
- внутренних скриптов;
- тестов с самого сервера.
Разрешение IPv6
Пример одного IPv6-адреса:
allow 2001:db8::10;
deny all;
Пример подсети:
allow 2001:db8:100::/64;
deny all;
Если сайт слушает IPv6, не ограничивайтесь только IPv4-правилами.
Ограничение всего виртуального хоста
Правила внутри server применяются ко всему сайту:
server {
server_name admin.example.com;
allow 192.0.2.10;
allow 2001:db8::10;
deny all;
location / {
proxy_pass http://127.0.0.1:3000;
}
}
Ограничение только отдельного location
Пример для /admin/:
server {
server_name example.com;
root /var/www/example.com/html;
location / {
try_files $uri $uri/ =404;
}
location /admin/ {
allow 192.0.2.10;
allow 198.51.100.0/24;
deny all;
try_files $uri $uri/ =404;
}
}
Остальная часть сайта останется публичной.
Ограничение административного API
location /api/admin/ {
allow 192.0.2.10;
deny all;
proxy_pass http://127.0.0.1:3000;
}
Ограничение служебной страницы
location = /status {
allow 127.0.0.1;
allow 192.0.2.10;
deny all;
stub_status;
}
Знак:
=
означает точное совпадение URI.
Создание резервной копии
Перед изменением:
sudo cp /etc/nginx/sites-available/example.com /etc/nginx/sites-available/example.com.before-ip-restriction
Проверьте:
ls -l /etc/nginx/sites-available/example.com*
Проверка конфигурации
sudo nginx -t
Ожидаемый результат:
syntax is ok
test is successful
Применение
sudo systemctl reload nginx
Проверьте:
systemctl status nginx --no-pager
Проверка с разрешённого IP
curl -I https://example.com/admin/
Ожидается обычный ответ приложения или сайта.
Проверка с запрещённого IP
С другой сети:
curl -I https://example.com/admin/
Ожидается:
HTTP/1.1 403 Forbidden
или:
HTTP/2 403
Проверка через локальный запрос
Если разрешён 127.0.0.1:
curl -I -H 'Host: example.com' http://127.0.0.1/admin/
Проверка через временное изменение IP невозможна
Заголовок:
X-Forwarded-For
не меняет реальный IP для обычного Nginx.
Команда:
curl -H 'X-Forwarded-For: 192.0.2.10' https://example.com
не должна использоваться как надёжная проверка, если Nginx не настроен доверять reverse proxy.
Порядок правил
Неправильный вариант:
deny all;
allow 192.0.2.10;
Первое совпавшее правило завершает проверку.
Правильный вариант:
allow 192.0.2.10;
deny all;
deny для отдельных адресов
Можно закрыть только конкретный IP:
deny 198.51.100.25;
allow all;
Но для административных страниц безопаснее whitelist-модель:
allow TRUSTED_IP;
deny all;
Использование include-файла
Если одинаковый список разрешённых IP используется в нескольких сайтах, вынесите его в отдельный файл.
Создайте:
sudo nano /etc/nginx/snippets/allowed-admin-ips.conf
Добавьте:
allow 192.0.2.10;
allow 198.51.100.0/24;
allow 2001:db8:100::/64;
deny all;
Подключите:
location /admin/ {
include /etc/nginx/snippets/allowed-admin-ips.conf;
proxy_pass http://127.0.0.1:3000;
}
Проверка include-файла
sudo nginx -t
Покажите итоговую конфигурацию:
sudo nginx -T |
grep -nE 'allowed-admin-ips|allow |deny '
Комментарии в правилах
# Рабочая станция администратора
allow 192.0.2.10;
# Корпоративная VPN-подсеть
allow 198.51.100.0/24;
deny all;
Комментарии упрощают сопровождение.
Не публикуйте внутренние IP и назначение адресов в открытых репозиториях без необходимости.
Динамический IP администратора
Если IP часто меняется, whitelist по одному адресу неудобен.
Подходящие варианты:
- VPN со статической подсетью;
- WireGuard;
- корпоративный reverse proxy;
- bastion host;
- Zero Trust access;
- Basic Auth как дополнительная защита.
Не разрешайте весь интернет только из-за динамического IP.
Ограничение по VPN-подсети
Пример:
allow 10.10.0.0/24;
deny all;
Пользователь сначала подключается к VPN, затем получает доступ к закрытому сайту.
Это более предсказуемо, чем whitelist домашнего динамического IP.
Nginx за внешним reverse proxy
Если перед Nginx находится:
- CDN;
- балансировщик;
- WAF;
- другой reverse proxy;
Nginx может видеть IP прокси вместо IP клиента.
В журнале будут адреса proxy-сервера.
В таком случае простые allow и deny будут проверять IP ближайшего proxy.
Real IP module
Для восстановления исходного IP клиента используются директивы:
set_real_ip_from PROXY_SUBNET;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
Пример:
set_real_ip_from 192.0.2.0/24;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
После этого allow и deny будут работать с восстановленным адресом клиента.
Важность доверенного proxy
Нельзя использовать:
set_real_ip_from 0.0.0.0/0;
иначе любой клиент сможет подставить произвольный X-Forwarded-For.
Указывайте только реальные адреса доверенного reverse proxy.
Проверка real IP
Проверьте формат access log.
Пример:
log_format realip '$remote_addr - $http_x_forwarded_for - $request';
Создайте запрос через proxy и проверьте журнал.
Настройка логирования real IP является отдельной задачей, но важна для проверки whitelist.
Cloudflare и другие CDN
При использовании CDN нужно:
- получить актуальные IP-сети провайдера;
- настроить
set_real_ip_from; - указать правильный real IP header;
- регулярно обновлять список сетей.
Не копируйте устаревшие диапазоны из случайных источников.
Несколько уровней прокси
При цепочке:
Клиент → CDN → Load Balancer → Nginx
нужно доверять только известным узлам цепочки.
Используйте:
real_ip_recursive on;
только после корректного списка доверенных proxy.
Совмещение IP restriction и Basic Auth
Можно потребовать одновременно:
- разрешённый IP;
- корректный логин и пароль.
Пример логики:
location /admin/ {
allow 192.0.2.10;
deny all;
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://127.0.0.1:3000;
}
Basic Auth рассматривается отдельно.
Директива satisfy
Nginx поддерживает:
satisfy all;
или:
satisfy any;
satisfy all
Требует выполнить все механизмы доступа.
satisfy any
Достаточно пройти хотя бы один.
Для строгой защиты административной панели обычно используют:
satisfy all;
Не добавляйте satisfy any без понимания, иначе пароль может открыть доступ с любого IP.
Журнал отказов
Проверьте error log:
sudo tail -50 /var/log/nginx/example.com.error.log
При блокировке может появиться сообщение:
access forbidden by rule
Поиск блокировок
sudo grep -i 'access forbidden by rule' /var/log/nginx/example.com.error.log |
tail -20
Отдельный access log для закрытого location
Можно создать отдельный location и лог:
location /admin/ {
access_log /var/log/nginx/admin-access.log;
allow 192.0.2.10;
deny all;
proxy_pass http://127.0.0.1:3000;
}
Проверка:
sudo tail -f /var/log/nginx/admin-access.log
Ошибка 403 после включения whitelist
Проверьте:
- фактический IP клиента;
- VPN;
- IPv4 или IPv6;
- порядок
allowиdeny; - real IP module;
- CDN;
- наличие правил в более широком
server; - итоговую конфигурацию.
Команды:
sudo nginx -T |
grep -nE 'allow |deny |set_real_ip_from|real_ip_header'
IPv6 обходит IPv4-ограничение
Если клиент подключается по IPv6, правило только для IPv4 не сработает как ожидается.
Проверьте:
curl -4 -I https://example.com
curl -6 -I https://example.com
Добавьте соответствующие IPv6-правила либо отключите AAAA-запись только после анализа.
Проверка, какой IP видит Nginx
sudo tail -20 /var/log/nginx/example.com.access.log
Создайте новый запрос и сопоставьте время.
Это основной способ подтвердить фактический адрес.
Изменение разрешённого IP
Откройте include-файл или server block.
Замените:
allow OLD_IP;
на:
allow NEW_IP;
Проверьте:
sudo nginx -t
Примените:
sudo systemctl reload nginx
Не удаляйте старый IP до проверки доступа с нового адреса.
Временное разрешение второго IP
Безопасный порядок:
allow OLD_IP;
allow NEW_IP;
deny all;
Проверьте доступ с нового адреса.
После этого удалите старое правило.
Отключение ограничения
Удалите или закомментируйте:
allow ...;
deny all;
Проверьте:
sudo nginx -t
Примените:
sudo systemctl reload nginx
Восстановление резервной копии
sudo cp /etc/nginx/sites-available/example.com.before-ip-restriction /etc/nginx/sites-available/example.com
Проверьте и примените:
sudo nginx -t &&
sudo systemctl reload nginx
Типичные ошибки
deny all расположен первым
Исправьте порядок:
allow TRUSTED_IP;
deny all;
Разрешён внутренний IP вместо публичного
Если пользователь подключается через интернет, Nginx видит публичный IP или IP reverse proxy.
Проверьте access log.
Разрешён IP домашнего роутера, но включён VPN
При VPN внешний IP меняется.
Добавьте VPN-адрес или используйте VPN-подсеть.
Nginx видит только IP CDN
Настройте Real IP module и доверенные сети CDN.
После reload доступ пропал у всех
Используйте открытую SSH-сессию.
Восстановите резервную копию и выполните:
sudo nginx -t &&
sudo systemctl reload nginx
Безопасный порядок настройки
- Определить фактический IP по access log.
- Проверить IPv4 и IPv6.
- Создать резервную копию.
- Добавить
allow. - Добавить
deny all. - Выполнить
nginx -t. - Выполнить reload.
- Проверить доступ с разрешённого IP.
- Проверить блокировку с другой сети.
- Проверить журналы.
- Только после этого закрыть резервную сессию.
Быстрый набор команд
Проверить IP клиента:
sudo tail -20 /var/log/nginx/example.com.access.log
Правила:
allow 192.0.2.10;
deny all;
Проверка:
sudo nginx -t
Применение:
sudo systemctl reload nginx
Поиск отказов:
sudo grep -i 'access forbidden by rule' /var/log/nginx/example.com.error.log |
tail
Итог
После выполнения инструкции:
- определён фактический IP клиента;
- настроен whitelist одного адреса или подсети;
- закрыт весь сайт или отдельный
location; - учтены IPv4 и IPv6;
- рассмотрена работа за reverse proxy;
- проверены разрешённые и запрещённые запросы;
- показано безопасное изменение правил.
Для административных интерфейсов надёжнее сочетать IP whitelist с VPN и отдельной аутентификацией.