Проблема ограничения доступа к сайтам, директориям и файлам, которые располагаются на вашем сервере не является редкой и может возникнуть в десятках, если не сотнях случаев: реконструкция или разработка сайта, доступ к которому нужно ограничить его командой до завершения процесса, региональные или локальные проекты, борьба со школохацкерами и т.п.

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 (пример: xxru)

Диапазоны IP-адресов по странам

Major IP Addresses Blocks By Country

На деле это редко когда может быть актуальным, т.к. тратит ресурсы сервера: канал и процессорное время и правильнее использовать блокировку при помощи ipset или iptables!