Вы настроили Nginx reverse proxy, оптимизировали PHP-FPM и ускорили сайт до 90+ баллов в PageSpeed. Но быстрый сайт — это лакомая цель для ботов. Ежедневно тысячи сканеров пытаются подобрать пароль к wp-login.php, эксплуатируют уязвимости плагинов и отправляют DDoS-запросы.
В этом руководстве мы выстроим многоуровневую защиту: от настройки SSH и Fail2ban на уровне сервера до ограничения запросов в Nginx и подключения Cloudflare. Эти меры отсекнут 99% автоматических атак без потери производительности.
Уровень 1: Базовая защита сервера (SSH)
Прежде чем защищать WordPress, нужно закрыть сам сервер. Если злоумышленник получит доступ по SSH, никакие плагины безопасности не помогут.
1. Отключите вход по паролю и используйте SSH-ключи
# Генерация ключа на локальной машине (если нет)
ssh-keygen -t ed25519 -C "admin@custom-code.ru"
# Копирование ключа на сервер
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@your_server_ip2. Запретите вход для root и измените порт (опционально)
Откройте /etc/ssh/sshd_config и измените параметры:
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
# Port 2222 # Раскомментируйте, если хотите сменить стандартный портsudo systemctl restart sshУровень 2: Fail2ban против брутфорса
Fail2ban анализирует логи и банит IP-адреса, которые совершают подозрительные действия (например, 5 неудачных входов в админку подряд).
Установка и настройка
sudo apt update
sudo apt install fail2ban -y
sudo systemctl enable fail2banЗащита SSH
Создайте файл /etc/fail2ban/jail.local:
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
findtime = 600Защита WordPress (wp-login.php)
Создайте фильтр /etc/fail2ban/filter.d/wordpress.conf:
[Definition]
failregex = ^<HOST> .* "POST /wp-login.php
ignoreregex =Добавьте jail в /etc/fail2ban/jail.local:
[wordpress]
enabled = true
port = http,https
filter = wordpress
logpath = /var/log/nginx/access.log
maxretry = 5
bantime = 86400
findtime = 300sudo systemctl restart fail2ban
sudo fail2ban-client status wordpressУровень 3: Ограничение запросов в Nginx (Rate Limiting)
Fail2ban реагирует постфактум. Nginx Rate Limiting отсекает атаки на уровне веб-сервера, не допуская их до PHP-FPM и базы данных.
Настройка зон ограничения
В файле /etc/nginx/nginx.conf в блок http { ... } добавьте:
http {
# Лимит для авторизации (1 запрос в секунду с одного IP)
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
# Лимит для всего сайта (10 запросов в секунду)
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
# Лимит для API и xmlrpc (2 запроса в секунду)
limit_req_zone $binary_remote_addr zone=api:10m rate=2r/s;
# ... остальные настройки
}Применение лимитов в конфиге сайта
В вашем конфиге /etc/nginx/sites-available/wordpress добавьте правила:
server {
# Общий лимит для сайта
limit_req zone=general burst=20 nodelay;
# Жесткий лимит для wp-login.php
location = /wp-login.php {
limit_req zone=login burst=2 nodelay;
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
# Блокировка xmlrpc.php (если не используете мобильное приложение)
location = /xmlrpc.php {
deny all;
return 444;
}
# Лимит для REST API
location ~ ^/wp-json/ {
limit_req zone=api burst=5 nodelay;
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}sudo nginx -t
sudo systemctl reload nginxУровень 4: Cloudflare (Защита от DDoS и скрытие IP)
Если на сервер идет мощная DDoS-атака, ни Nginx, ни Fail2ban не справятся — канал будет забит. Cloudflare принимает удар на себя.
1. Подключение домена
Зарегистрируйтесь на Cloudflare, добавьте домен custom-code.ru и замените NS-серверы у вашего регистратора.
2. Настройка Firewall Rules (бесплатно)
В панели Cloudflare перейдите в Security → WAF → Firewall Rules и создайте правила:
- Блокировка стран: Если ваш сайт только для РФ/СНГ, заблокируйте весь остальной мир (Country is not in [RU, BY, KZ…]).
- Защита wp-login: If URI contains
wp-login.phpAND Threat Score is greater than 10 → Challenge (Captcha).
3. Критически важно: передача реального IP в Nginx
Если вы подключите Cloudflare, Nginx и Fail2ban будут видеть только IP-адреса Cloudflare. При срабатывании Fail2ban заблокирует весь Cloudflare, и ваш сайт упадет для всех.
Скачайте актуальные IP Cloudflare и настройте Nginx:
# Создаем файл с IP Cloudflare
curl -s https://www.cloudflare.com/ips-v4 > /etc/nginx/cloudflare_ips.txt
curl -s https://www.cloudflare.com/ips-v6 >> /etc/nginx/cloudflare_ips.txtВ начало конфига сайта добавьте:
# Чтение IP Cloudflare
include /etc/nginx/cloudflare_ips.txt; # (формат файла нужно будет привести к set_real_ip_from)
# Правильный способ через модуль real_ip:
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
# ... добавьте все подсети из ips-v4
real_ip_header CF-Connecting-IP;Уровень 5: Внутренняя защита WordPress
Помимо серверной защиты, нужно закрыть уязвимости внутри самого движка.
1. Отключение редактирования файлов в админке
Добавьте в wp-config.php:
define( 'DISALLOW_FILE_EDIT', true );2. Скрытие версии WordPress
Добавьте в functions.php дочерней темы:
remove_action( 'wp_head', 'wp_generator' );
function remove_wp_version_strings( $src ) {
global $wp_version;
parse_str( parse_url( $src, PHP_URL_QUERY ), $query );
if ( ! empty( $query['ver'] ) && $query['ver'] === $wp_version ) {
$src = remove_query_arg( 'ver', $src );
}
return $src;
}
add_filter( 'style_loader_src', 'remove_wp_version_strings' );
add_filter( 'script_loader_src', 'remove_wp_version_strings' );3. Правильные права на файлы
Как мы разбирали в статье про ошибку 500, неправильные права — частая причина взлома. Выполните:
sudo find /var/www/wordpress -type d -exec chmod 755 {} \;
sudo find /var/www/wordpress -type f -exec chmod 644 {} \;
sudo chown -R www-data:www-data /var/www/wordpressЧек-лист безопасности
- ✅ Вход по SSH только по ключам, root отключен
- ✅ Fail2ban настроен на SSH и wp-login.php
- ✅ Nginx Rate Limiting ограничивает частоту запросов
- ✅ xmlrpc.php заблокирован (если не нужен)
- ✅ Подключен Cloudflare, настроены Firewall Rules
- ✅ Nginx корректно определяет реальный IP через CF-Connecting-IP
- ✅ Редактирование файлов в админке отключено
- ✅ Права на файлы 644, на папки 755
- ✅ Все плагины и ядро WordPress обновлены
Что делать, если проблемы не решаются?
Fail2ban банит легитимных пользователей
Проверьте, не слишком ли агрессивны настройки maxretry и findtime. Если вы используете Cloudflare, убедитесь, что Nginx передает реальный IP (иначе бан прилетит всем посетителям с одного IP Cloudflare).
Сайт отдает 503 Service Unavailable
Если вы настроили Rate Limiting и видите ошибку 503, значит, лимиты слишком жесткие для вашего трафика. Увеличьте параметр burst в директиве limit_req.
После подключения Cloudflare сайт работает медленно
Убедитесь, что в Cloudflare включено кэширование статики (Caching → Configuration → Caching Level: Standard). Также проверьте, что SSL-режим установлен в Full (Strict), иначе будут циклические редиректы или ошибки 521/522.
Итог
Безопасность — это не плагин «Wordfence», который ест 200 МБ оперативной памяти и замедляет сайт. Это грамотная настройка сервера. Fail2ban + Nginx Rate Limit + Cloudflare создают эшелонированную защиту, которая не нагружает PHP и MySQL, оставляя ваш сайт быстрым и недоступным для ботов.