{{tag>nginx server triks}}

====== Ограничение доступа средствами Nginx ======


Небольшая заметка о том, как средствами Nginx-а закрыть доступ к файлам/папке по паролю. В nginx-е это решение не менее элегантно, чем в apache, а может и еще лучше, кому как нравится.

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

<code nginx>  location ^~ /files/ {
      root   /path/to/server;
      autoindex    on;
      autoindex_exact_size  off;
      auth_basic "Hello, please login";
      auth_basic_user_file /usr/nginx/passwords;
      access_log   /usr/nginx/logs/files.log   download;
  }
</code>

и админовской части c дополнительным ограничением по IP:
<code nginx>  location ^~ /admin/ {
      fastcgi_pass unix:/home/project/server.sock;
      include  conf/fastcgi.conf;
      allow 11.11.0.0/16;
      allow 22.22.22.22;
      deny all;
      auth_basic "Hello, Admin, please login";
      auth_basic_user_file /usr/nginx/adminpassword;
      access_log   /usr/nginx/logs/admin.log  main;
  }
</code>
Добавить пользователя можно с помощью стандартной утилиты от apache:
htpasswd -b passwords NewUser NewPassword
В файле запись с зашифрованным паролем имеет вид:
NewUser:P47ghZ4kloG78: Your Can Comment Here
Защиту от перебора паролей можно организовать одновременно двумя методами, основанными на использовании iptables:
Блокирование IP на время, если количество запросов в секунду превышает какое-либо разумное количество
Вести лог неудачных попыток подбора пароля и скриптом раз в минуту проверять лог и заносить IP адреса в iptables
Для первого варианта достаточно создать правила:

  iptables -A INPUT -p tcp --syn --dport 80 -i eth0 -m state --state NEW
              -m recent --name bhttp --set
  iptables -A INPUT -p tcp --syn --dport 80 -i eth0 -m state --state NEW
              -m recent --name bhttp --update --seconds 120 
              --hitcount 360 -j DROP
  iptables -A INPUT -p tcp --syn --dport 80 -i eth0 -j ACCEPT
  
Можно вместо DROP использовать TARPIT, чтобы усложнить жизнь ломателям :) 

Для второго варианта надо добавить в конфиг:
<code nginx>
  location /401.html {
      root   /usr/nginx;
      access_log   /usr/nginx/logs/denied.log  error401;
  }
</code>

Формат error401, у меня например такой:
  log_format error401  '$remote_addr - $remote_user [$time_local] '
                       '$status "$request"';
                       
Теперь все неправильные попытки будут записываться в отдельный лог, который мы можем обрабатывать по cron-у:
<code bash>  \*/1 * * * * root /usr/nginx/parser401.pl >/dev/null 2>&1</code>
  
например, таким скриптом: parser401.pl Скрипт проверяет лог, и если обнаруживает больше 4-х попыток неправильного набора пароля, блокирует этот IP.
Есть какие-либо идеи, мысли?