Предисловие:
При открытии доступа к домашней сети через прокси-сервер, вы неизбежно столкнётесь с активным сканированием вашей сети и доменных имен роботами в поисках уязвимостей. Используя «Nginx Proxy Manager» в качестве прокси-сервера, в логах часто можно заметить сотни и тысячи запросов с ответом 404 (не найдено). Эта инструкция поможет защитить вашу сеть от сканирующих роботов и заблокировать их навсегда.
Вот небольшой пример лога сканирования:
[19/Nov/2024:07:10:57 +0300] - 404 404 - GET https dedsec.pro "/phpunit/phpunit/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:10:58 +0300] - 404 404 - GET https dedsec.pro "/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:10:59 +0300] - 404 404 - GET https dedsec.pro "/phpunit/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:00 +0300] - 404 404 - GET https dedsec.pro "/lib/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:00 +0300] - 404 404 - GET https dedsec.pro "/lib/phpunit/phpunit/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:01 +0300] - 404 404 - GET https dedsec.pro "/lib/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:02 +0300] - 404 404 - GET https dedsec.pro "/lib/phpunit/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:03 +0300] - 404 404 - GET https dedsec.pro "/lib/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:03 +0300] - 404 404 - GET https dedsec.pro "/laravel/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:04 +0300] - 404 404 - GET https dedsec.pro "/www/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:05 +0300] - 404 404 - GET https dedsec.pro "/ws/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:06 +0300] - 404 404 - GET https dedsec.pro "/yii/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:06 +0300] - 404 404 - GET https dedsec.pro "/zend/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:07 +0300] - 404 404 - GET https dedsec.pro "/ws/ec/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:08 +0300] - 404 404 - GET https dedsec.pro "/V2/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:09 +0300] - 404 404 - GET https dedsec.pro "/tests/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:09 +0300] - 404 404 - GET https dedsec.pro "/test/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:10 +0300] - 404 404 - GET https dedsec.pro "/testing/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:11 +0300] - 404 404 - GET https dedsec.pro "/api/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:12 +0300] - 404 404 - GET https dedsec.pro "/demo/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:12 +0300] - 404 404 - GET https dedsec.pro "/cms/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:13 +0300] - 404 404 - GET https dedsec.pro "/crm/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:14 +0300] - 404 404 - GET https dedsec.pro "/admin/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:14 +0300] - 404 404 - GET https dedsec.pro "/restore.php" [Client 213.108.20.138] [Length 1113841] [Gzip -] [Sent-to 192.168.50.4] "-" "-"
[19/Nov/2024:07:11:14 +0300] - 404 404 - GET https dedsec.pro "/restore.php" [Client 213.108.20.138] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "-" "-"
[19/Nov/2024:07:11:14 +0300] - 404 404 - GET https dedsec.pro "/backup/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:15 +0300] - 404 404 - GET https dedsec.pro "/blog/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:16 +0300] - 404 404 - GET https dedsec.pro "/workspace/drupal/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:17 +0300] - 404 404 - GET https dedsec.pro "/panel/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:17 +0300] - 404 404 - GET https dedsec.pro "/public/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
[19/Nov/2024:07:11:18 +0300] - 404 404 - GET https dedsec.pro "/apps/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php" [Client 171.22.120.12] [Length 1201653] [Gzip -] [Sent-to 192.168.50.4] "Custom-AsyncHttpClient" "-"
!ВНИМАНИЕ!
Эта инструкция актуальна, если вы установили Nginx Proxy Manager в LXC-контейнере на системе Proxmox. Во всех остальных случаях вам нужно будет адаптировать её под свои нужды самостоятельно.
Я не смог заставить работать фильтрацию трафика на виртуальной машине с Ubuntu 24.04 и NPM в Docker-контейнере. Пока что это задача оказалась для меня слишком сложной.
Начинаем начинать:
- Разворачиваем LXC контейнер Nginx Proxy Manager в среде Proxmox.
Самый простой способ, использовать готовый скрипт от сообщества:
https://community-scripts.github.io/ProxmoxVE/scripts?id=nginxproxymanager
- Проваливаемся в контейнер, выполняем команду:
apt update && apt upgrade -y
- Далее устанавливаем комплект софта:
apt install curl mc fail2ban iptables -y
- Запускаем и добавляем Fail2Ban в автозагрузку:
systemctl enable fail2ban && systemctl start fail2ban
- Проверяем статус работы сервиса Fail2ban:
systemctl status fail2ban
В ответ вы должны увидеть такое, сервис заработал:
root@NginxProxyManager:~# systemctl status fail2ban.service
● fail2ban.service - Fail2Ban Service
Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled; preset: enabled)
Active: active (running) since Tue 2024-11-19 15:50:12 MSK; 24min ago
Docs: man:fail2ban(1)
Main PID: 127 (fail2ban-server)
Tasks: 5 (limit: 76137)
Memory: 33.8M
CPU: 1.731s
CGroup: /system.slice/fail2ban.service
└─127 /usr/bin/python3 /usr/bin/fail2ban-server -xf start
Nov 19 15:50:12 NginxProxyManager systemd[1]: Started fail2ban.service - Fail2Ban Service.
Nov 19 15:50:12 NginxProxyManager fail2ban-server[127]: 2024-11-19 15:50:12,860 fail2ban.configreader [127]: WARNING 'allowipv6' not defined in 'Definitio>
Nov 19 15:50:13 NginxProxyManager fail2ban-server[127]: Server ready
Переходим к настройке, а именно созданию фильтра и конфига.
- Создаем новый файл фильтра в папке filter.d
mcedit /etc/fail2ban/filter.d/nginx-404-ban.conf
- Добавляем этот текст в содержимое файла:
[INCLUDES]
[Definition]
failregex = ^.* (405|404|403|401|\-) (405|404|403|401) - .* \[Client <HOST>\] \[Length .*\] .* \[Sent-to <F-CONTAINER>.*</F-CONTAINER>\] <F-USERAGENT>".*"</F-USERAGENT> .*$
ignoreregex = ^.* (404|\-) (404) - .*".*(\.png|\.txt|\.jpg|\.ico|\.js|\.css|\.ttf|\.woff|\.woff2)(\?.*)(/)*?" \[Client <HOST>\] \[Length .*\] ".*" .*$
Нажимем F2 чтобы сохранить и F10 чтобы выйти из редактора.
- Создаём файл конфигурации jail.local
mcedit /etc/fail2ban/jail.local
- Вставляем в него следующий текст:
[DEFAULT]
ignoreip = 127.0.0.1/8 #ВАШ СПИСОК IP АДРЕСОВ КОТОРЫЕ НЕ ДОЛЖНЫ ПОПАДАТЬ В БАН
bantime = -1
findtime = 60
maxretry = 3
banaction = iptables-multiport
[sshd]
enabled = false
[nginx-404-ban]
enabled = true
filter = nginx-404-ban
logpath = /data/logs/*.log
maxretry = 3
findtime = 60
bantime = -1
Данная конфигурация работает следующим образом: раз в минуту сканируется лог, отлавливаются новые записи с ошибкой 404, если за минуту с одного IP адреса было 3 запроса и был получен ответ 404, этот IP адрес отлетает по DROP в iptables навечно, пока вы вручную не разблокируете его.
НО! При этом если ошибка 404 связана с недостатком файлов (которая бывает кстати очень часто и можно расценить как ложное срабатывание) то она игнорируется согласно правилам фильтра.
- Жмём F2 чтобы сохранить и F10 чтобы выйти из редактора.
- Перезапускаем Fail2Ban
systemctl restart fail2ban && systemctl status fail2ban
- Если в ответ получили что сервис запущен, значит всё сделали правильно, фильтр начинает работать.
На этом настройка Fail2Ban закончена.
Вот вам дополнительные команды для проверки правильности работы:
- Проверка работы фильтра по логу:
fail2ban-regex /data/logs/proxy-host-1_access.log /etc/fail2ban/filter.d/nginx-404-ban.conf
- Проверка работы фильтра и просмотр списка заблокированных IP адресов?
fail2ban-client status nginx-404-ban
- Команда для разблокировки IP адреса:
fail2ban-client set nginx-404-ban unbanip 127.0.0.1