Способы разграничения прав доступа в nginx
Проблема ограничения доступа к сайтам, директориям и файлам, которые располагаются на вашем сервере не является редкой и может возникнуть в десятках, если не сотнях случаев: реконструкция или разработка сайта, доступ к которому нужно ограничить его командой до завершения процесса, региональные или локальные проекты, борьба со школохацкерами и т.п.
1. Как при помощи nginx заблокировать доступ с определенного ip к некоторой секции сайта?
Открываем конфигурационный файл вашего сайта:
nano /etc/nginx/sites-available/sitename.com
Находим или создаем локейшн, доступ к которому нужно закрыть с определенного ip, например "111.222.333.444":
location /testdir {
deny 111.222.333.444;
}
После чего нужно не забыть проверить правильность конфигурации командой:
nginx -t
И в обязательном порядке перезагрузить nginx:
sudo servcie nginx restart
Или просто заставить его перечитать конфигурационные файлы:
sudo service nginx reload
Дополнительно вы можете вывести свою страницу ошибки или даже сделать переадресацию на другой сайт:
location /testdir {
error_page 403 = @deny;
deny 111.222.333.444;
}
location @deny {
return 301 http://example.com/comingsoon;
}
Аналогичным образом вы можете отдавать любой HTTP ответ, вместо стандартного "ERROR 403":
location /testdir {
deny 111.222.333.444;
return 444;
}
Ошибка 444 (No Response) — это пользовательский код состояния, используемый для указания nginx на закрытие соединения без отправки ответа клиенту, чаще всего используется для отклонения вредоносных или искаженных запросов.
Действие с IP по условию
В зависимости от определенного IP-адреса NGINX может выполнять различные действия, а не только запрет доступа. Например, перенаправление.
В данном примере мы перенаправляем всех посетителей по пути https://$host$request_uri, кроме запросов с IP-адреса 111.222.333.444.
location / {
...
if ($remote_addr != 111.222.333.444) {
return 301 https://$host$request_uri;
}
...
}
2. Как при помощи nginx заблокировать доступ с нескольких ip адресов к некоторой секции сайта?
Аналогичным образом вы можете отправить шуточный код ошибки "HTTP 418" I’m a teapot (Я - чайник). Этот код был представлен в 1998 году как одна из традиционных первоапрельских шуток IETF в RFC 2324, Hyper Text Coffee Pot Control Protocol. Ожидается, что этот код не будет поддерживаться реальными серверами. Как бы то ни было, реализации существуют. Сервер HTTP Nginx в своей конфигурации использует этот код для имитации поведения goto-like.
deny 111.222.333.444;
deny 111.222.333.555;
deny 111.222.333.666;
deny 111.222.333.777;
1 апреля 1998 года Internet Engineering Task Force (IETF, «Целевая группа по инженерному обеспечению Интернета) представила «протокол для контроля, мониторинга и диагностики кофемашин». В документе среди прочего описывались и ошибки. Проблема за номером 418 описывалась так: если кто-то попытается сварить кофе в чайнике, последний вежливо, но твердо сообщит: «Я – чайник. Ошибка 418».
Шутка прижилась (по крайней мере, в узких кругах). Например, у Google даже сегодня есть соответствующая страница google.com/teapot
3. Как при помощи nginx заблокировать доступ с диапазона или нескольких диапазонов ip адресов к некоторой секции сайта?
В данной ситуации локейшн не представляет ничего особенного и составляется по следующему принципу.
Для запрета доступа с одного диапазона (111.222.111.1-111.222.111.254) ip:
location /testdir {
deny 111.222.111.0/24;
}
Для запрета доступа с нескольких диапазонов ip адресов:
location /testdir {
deny 111.222.111.0/24;
deny 111.222.222.0/24;
}
4. Как при помощи nginx заблокировать доступ из списка ip адресов и списка диапазонов ip? расположенных в отдельном файле к некоторой секции сайта?
Вот мы и подошли к более интересному случаю, когда мы можем заблокировать на одном сайте, в нескольких сайтах или же на большом количестве сайтов множество ip адресов и диапазонов сетей, которые у нас расположены в некотором файле "testdir_ip_deny.txt", расположенном в папке "/etc/nginx/"
location /testdir {
include /etc/nginx/testdir_ip_deny.txt
}
Содержимое файла "testdir_ip_deny.txt" может выглядеть следующим образом:
deny 111.555.111.0/24;
deny 111.222.333.444;
deny 111.222.333.555;
deny 111.222.333.666;
deny 111.222.333.777;
deny 111.666.222.0/24;
deny 111.333.333.888;
deny 111.444.333.999;
deny 111.222.321.666;
deny 111.222.456.777;
В таком виде nginx может обработать десятки тысяч ip адресов и диапазонов ip сетей.
Аналогичным образом вы можете заблокировать доступ ко всем сайтам и всем локейшинам nginx, не прописывая правила блокировки во всех конфигах сайтов.
Для этого достаточно создать файл ip_deny_to_all.conf в директории конфигурационных файлов (/etc/nginx/conf.d) nginx:
nano /etc/nginx/conf.d/ip_deny_to_all.conf
B вставить в него произвольный список запретов:
...
deny 111.666.222.0/24;
deny 111.333.333.888;
...
include добавлять никуда не нужно, т.к. все конфигурационные файлы (*.conf) из данной директории автоматически подключаются в основной конфиг в секцию HTTP, проверить это вы можете открыв соответствующий файл:
nano /etc/nginx/nginx.conf
И найдя следующий код:
http {
...
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
Таким образом вы сможете заблокировать или разрешить доступ ко всем сайтам, учитывая содержимое файла /etc/nginx/conf.d/ip_deny_to_all.conf
Таким образом вы можете составить несколько списков, в том числе и списки по странам (вместо использования NGINX GeoIP Module), взяв их, например, на одном из следующих сайтов:
https://www.countryipblocks.net/acl.php (может быть недоступен с ip адресов РФ и РБ)
http://ipverse.net/ipblocks/data/countries/xx.zone (пример: xx – ru)
Диапазоны IP-адресов по странам
Major IP Addresses Blocks By Country
На деле это редко когда может быть актуальным, т.к. тратит ресурсы сервера: канал и процессорное время и правильнее использовать блокировку при помощи ipset или iptables!