Блокировка доступа к NGINX

Способы ограничения доступа к ресурсу в NGINX




Блокировка по User Agent`у




Я использую эту технику, прежде всего, для защиты от роботов, которые игнорируют настройки в моем файле robots.txt.




if ($http_user_agent ~ "Windows 95|Windows 98|xpymep|TurnitinBot|sindice|Purebot|libwww-perl")  {
  return 403;
  break;
}




Я выбрал для блокирования libwww-Perl, потому что в последние несколько лет, я не видел ни GET или POST по libwww-Perl, вероятно пробовали использовать какую-то уязвимость ПО.




Блокировка по IP-адресу




deny 85.17.26.68;     # spam
deny 85.17.230.23;    # spam
deny 173.234.11.105;  # junk referrers
deny 173.234.31.9;    # junk referrers
deny 173.234.38.25;   # spam
deny 173.234.153.30;  # junk referrers
deny 173.234.153.106; # spam
deny 173.234.175.68;  # spam
deny 190.152.223.27;  # junk referrers
deny 195.191.54.90;   # odd behaviour, Mozilla, doesnt fetch js/css. Ended up doing a POST, prob a spambot
deny 195.229.241.174; # spammy comments
deny 210.212.194.60;  # junk referrers + spam




Блокировка по запросу




Кроме того, можно заблокировать доступ на основе информации которая отправляется в заголовках HTTP.




if ($http_referer ~* (viagra|sex|porn|) ) {
  return 403;
}




Я использую ключ ~* для того чтобы предотвратить запрос GET по указанным словам во всей строке.




Блокировка по подсети




deny 69.28.58.0/24;   # spam
deny 79.142.64.0/20;  # spam
deny 80.67.0.0/20;    # spam




Блокировка по геолокации




Мы можем заблокировать целые страны, основанные на данных GeoIP предоставляемых MaxMind. Необходимо, чтобы NGINX имел модуль GeoIP. Во-первых, вы должны обозначить NGINX где база данных GeoIP находится в файловой системе. Вы можете сделать это внутри HTTP {}; Конфигурация блока:




geoip_country /etc/nginx/GeoIP.dat;




Теперь сообщаем NGINX страны которые необходимо заблокировать:




if ($geoip_country_code ~ (BR|CN|KR|RU) ) {
  return 403;
}




Блокировка по паролю




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




location ^~ /codes/ {
   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/codes.log   download;
      }




либо админки с ограничением по IP-адресу:




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;
}




Добавить пользователя можно с помощью стандартной утилиты от 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, чтобы усложнить жизнь ломателям.




Для второго варианта надо добавить в конфиг:




location /401.html {
   root   /usr/nginx;
            access_log   /usr/nginx/logs/denied.log  error401;
        }




Формат error401, у меня например такой:




log_format error401  '$remote_addr - $remote_user [$time_local] '
   '$status "$request"';



2022-04-14T17:32:32
Software