Суть проблемы
В логах Nginx появились ошибки "Primary script unknown".
Это боты и сканеры перебирают стандартные WordPress файлы:
- /xmlrpc.php
- /wp-login.php
- /wp-admin/setup-config.php
- /wp-trackback.php
- и много других
Файлов нет, но запросы создают нагрузку и засоряют логи.
Идея решения
Отсекать подозрительные запросы на уровне Nginx, не передавая их PHP.
То есть: если запрос идёт к файлу, которого заведомо нет и быть не должно — сразу закрывать соединение.
Что сделали
1. Заблокировали конкретные файлы
Все запросы к:
- xmlrpc.php
- wp-login.php
- setup-config.php
- wp-trackback.php
- admin.php, about.php, info.php и т.д.
Получают ответ 444 (закрыть соединение без ответа).
2. Заблокировали стандартные пути WordPress
/wp-admin, /wp-includes, /wordpress и другие.
3. Заблокировали подозрительные IP
Добавили в конфиг IP, которые активно сканировали сайт.
4. Заблокировали плохие User-Agent
nikto, sqlmap, nmap, masscan и другие сканеры.
5. Ограничили методы HTTP
Разрешили только GET, HEAD, POST. Всё остальное — 444.
6. Запретили доступ к скрытым файлам
.env, .git, .svn, .htaccess и т.д.
7. Добавили rate limiting
Ограничили количество запросов с одного IP.
Принцип работы
До: запрос → Nginx → PHP-FPM → ошибка "Primary script unknown" → лог.
После: запрос → Nginx проверяет → если в чёрном списке → сразу 444 → в лог ничего не пишется (или пишется, но не ошибка).
Что дальше
- Можно подключить fail2ban для автоматической блокировки
- Регулярно обновлять список плохих IP
- Следить за логами — если появятся новые паттерны, добавлять их
Настройка fail2ban для защиты от сканеров WordPress
Проблема
В логах Nginx появились множественные ошибки:
FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream client: 104.23.221.139, request: "GET /wp-admin/setup-config.php" client: 112.202.123.39, request: "POST /xmlrpc.php" client: 20.53.240.38, request: "GET /wp-trackback.php" client: 89.187.168.122, request: "GET /archivarix.cms.php"
Это боты и сканеры, перебирающие стандартные и подозрительные файлы.
Решение — fail2ban
Автоматическая блокировка IP, с которых приходит много подозрительных запросов.
Конфигурация fail2ban
1. Фильтр /etc/fail2ban/filter.d/wp-scanner.conf
[Definition]
failregex = ^.*client: <HOST>.*request: ".*(wp-login\.php|xmlrpc\.php|setup-config\.php|wp-trackback\.php|about\.php|info\.php|admin\.php|file\.php|goods\.php|rip\.php|sf\.php|chosen\.php|archivarix\.cms\.php).*"
ignoreregex =
2. Джейл в /etc/fail2ban/jail.local
[wp-scanner]
enabled = true
filter = wp-scanner
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 10
findtime = 60
bantime = 3600
action = ufw
Примечание: в DEFAULT секции указано banaction = ufw
Проверка работы
Тест фильтра на конкретной строке:
# Создать тестовый лог
echo '2026/02/21 13:12:04 [error] client: 89.187.168.122 request: "GET /wp-login.php HTTP/1.1"' > /tmp/test.log
# Проверить фильтр
sudo fail2ban-regex /tmp/test.log /etc/fail2ban/filter.d/wp-scanner.conf
Результат теста:
Failregex: 1 total Lines: 1 lines, 1 matched, 0 missed
Добавление тестовой записи в реальный лог:
echo "$(date +'%Y/%m/%d %H:%M:%S') [error] client: 89.187.168.122 request: \"GET /wp-login.php HTTP/1.1\"" | sudo tee -a /var/log/nginx/error.log
Проверка статуса:
sudo fail2ban-client status wp-scanner
Результат после теста:
Status for the jail: wp-scanner |- Filter | |- Currently failed: 1 | |- Total failed: 1 | `- File list: /var/log/nginx/error.log `- Actions |- Currently banned: 0 |- Total banned: 0 `- Banned IP list:
Бан произойдет после 10 нарушений за 60 секунд (или после 1, если временно установить maxretry = 1)
Полезные команды
# Перезапуск fail2ban
sudo systemctl restart fail2ban
# Статус конкретного джейла
sudo fail2ban-client status wp-scanner
# Логи fail2ban
sudo tail -f /var/log/fail2ban.log
# Разблокировать IP (если ошиблись)
sudo fail2ban-client set wp-scanner unbanip 89.187.168.122
Итог
Fail2ban настроен и работает. Сканеры, пытающиеся обращаться к несуществующим WordPress-файлам, будут автоматически блокироваться на 1 час после 10 попыток в течение 60 секунд.
Статус на 21.02.2026: защита активна.
Комментарии
Пока нет комментариев. Будьте первым!