Каждую неделю я смотрю логи серверов своих клиентов и вижу одно и то же: тысячи запросов к xmlrpc.php и wp-login.php, которые бьют по сайту как отбойный молоток. Это не паранойя — это реальность любого WordPress-сайта, и если вы не закрыли эти векторы атаки, вы буквально оставили дверь нараспашку.
Почему XML-RPC и wp-login.php — любимые цели хакеров
Начну с конкретики. У меня есть клиент — небольшой интернет-магазин на WordPress 6.4, хостинг на обычном VPS с PHP 8.1 и MySQL 8.0. Однажды утром он написал мне: "Павел, сайт жутко тормозит, хостер грозит отключением за нагрузку". Открываю логи — 40 000 запросов в час только к xmlrpc.php. Ботнет методично перебирал пароли через multicall-метод XML-RPC. За ночь они сделали больше миллиона попыток авторизации. Сайт лежал на боку.
XML-RPC — это старый протокол удалённого управления WordPress, появившийся ещё в эпоху блогов нулевых. Изначально его придумали для публикации постов из внешних приложений вроде Windows Live Writer. Но у него есть убийственная особенность: метод system.multicall позволяет отправить тысячи команд в одном HTTP-запросе. Грубо говоря, один запрос = тысяча попыток авторизации. Для брутфорса это идеальный инструмент.
wp-login.php — ещё проще. Это стандартная страница входа, которая всегда находится по предсказуемому адресу. Боты знают этот адрес наизусть и долбят его круглосуточно. Без ограничений на количество попыток — это просто открытый буфет для подбора паролей.
Полное отключение XML-RPC: три способа
Первый вопрос, который я слышу: "А вдруг он мне нужен?". Честно говоря, в 2026 году XML-RPC нужен примерно 2% сайтов. Если вы не используете Jetpack (и то — современные версии уже перешли на REST API), не публикуете посты через мобильное приложение WordPress для iOS/Android, и не интегрируете сторонние сервисы через этот протокол — отключайте без сожаления. Проверьте сначала, есть ли у вас зависимости.
Способ 1 — Блокировка на уровне Nginx
Это мой любимый метод. Блокировка на уровне веб-сервера работает до того, как PHP вообще запустится. Нагрузка на сервер — минимальная, запрос просто получает 403 и уходит.
server {
# ... остальная конфигурация ...
# Полная блокировка XML-RPC
location = /xmlrpc.php {
deny all;
access_log off;
log_not_found off;
return 403;
}
# Дополнительно — блокируем любые попытки обращения к файлу
location ~* ^/xmlrpc\.php$ {
deny all;
return 403;
}
}
Строку access_log off я добавляю специально — чтобы эти запросы не засоряли логи. Когда их тысячи в день, логи растут как на дрожжах, и потом в них сложно найти реальные проблемы. Если хотите мониторить атаки — лучше настройте отдельный лог для таких блокировок или используйте специализированный инструмент. Кстати, про грамотную работу с логами я подробно писал в статье настройка логов сайта: мониторинг и анализ ошибок.
Способ 2 — Блокировка через .htaccess (Apache)
Если у вас Apache, используем .htaccess. Добавьте в корень сайта:
# Блокировка XML-RPC
<Files "xmlrpc.php">
Order Deny,Allow
Deny from all
</Files>
# Альтернативный вариант через RewriteRule
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^xmlrpc\.php$ - [F,L]
</IfModule>
# Блокировка wp-login.php от всех кроме вашего IP
<Files "wp-login.php">
Order Deny,Allow
Deny from all
Allow from 192.168.1.100
Allow from 203.0.113.50
</Files>
Замените IP-адреса на свои реальные. Если у вас динамический IP от провайдера — это неудобно, но решаемо: можно использовать VPN с фиксированным IP или настроить другой метод аутентификации. О том, как полноценно закрыть административную панель, я рассказывал в статье защита wp-admin: закрываем доступ к панели WordPress.
Способ 3 — Через плагин или functions.php
Этот способ работает на уровне PHP, что менее эффективно с точки зрения нагрузки, но зато не требует доступа к серверу. Добавьте в functions.php вашей темы или в мю-плагин:
<?php
// Полное отключение XML-RPC
add_filter( 'xmlrpc_enabled', '__return_false' );
// Удаляем заголовок X-Pingback из HTTP-ответов
add_filter( 'wp_headers', function( $headers ) {
unset( $headers['X-Pingback'] );
return $headers;
} );
// Убираем ссылку на xmlrpc.php из head
remove_action( 'wp_head', 'rsd_link' );
remove_action( 'wp_head', 'wlwmanifest_link' );
?>
Но — и это принципиально — такой способ всё равно позволит PHP начать обработку запроса. Сервер получит запрос, запустит PHP, загрузит WordPress, и только потом вернёт отказ. При массированной атаке это всё равно будет создавать нагрузку. Поэтому я рекомендую комбинировать: закрыть на уровне Nginx/Apache и дополнительно отключить через PHP.
Защита wp-login.php: комплексный подход
С wp-login.php полная блокировка — уже не вариант, ведь вам самому нужно входить в админку. Здесь нужен более тонкий подход. Я использую несколько слоёв защиты одновременно.
Rate limiting на уровне Nginx
Ограничение количества запросов — первая линия обороны. Настраиваем в конфигурации Nginx:
http {
# Зона для ограничения входа — 10 МБ памяти, 1 запрос в секунду с одного IP
limit_req_zone $binary_remote_addr zone=wp_login:10m rate=1r/s;
limit_req_zone $binary_remote_addr zone=xmlrpc:10m rate=1r/m;
}
server {
# Ограничение для wp-login.php
location = /wp-login.php {
limit_req zone=wp_login burst=3 nodelay;
limit_req_status 429;
# Логируем превышения отдельно
access_log /var/log/nginx/wp-login-blocked.log;
include fastcgi_params;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Параметр burst=3 означает, что мы допускаем небольшой всплеск — до 3 запросов подряд — прежде чем начнём блокировать. Это нужно, чтобы не заблокировать себя, если случайно обновил страницу дважды. Подробнее про rate limiting и защиту от DDoS я разбирал в статье настройка rate limiting: защита от DDoS 2026.
HTTP Basic Auth как второй замок
Это элегантное решение: перед тем, как WordPress даже увидит запрос к wp-login.php, браузер спросит логин и пароль на уровне веб-сервера. Двойная авторизация — сначала HTTP Auth, потом WordPress.
location = /wp-login.php {
auth_basic "Restricted Access";
auth_basic_user_file /etc/nginx/.htpasswd;
limit_req zone=wp_login burst=3 nodelay;
include fastcgi_params;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
# То же для wp-admin, кроме admin-ajax.php (он нужен для работы сайта)
location /wp-admin/ {
auth_basic "Restricted Access";
auth_basic_user_file /etc/nginx/.htpasswd;
location = /wp-admin/admin-ajax.php {
auth_basic off;
include fastcgi_params;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Файл .htpasswd создаётся командой: htpasswd -c /etc/nginx/.htpasswd username. Важный момент: не делайте логин и пароль от HTTP Auth такими же, как от WordPress — это разные уровни защиты, и они должны быть независимы.
openssl rand -base64 24. Сохраните в менеджере паролей — это не тот пароль, который нужно помнить наизусть.Смена URL страницы входа: работает или нет?
Честно говоря, это спорная тема. Смена стандартного URL wp-login.php на что-то вроде /my-secret-door/ — это security through obscurity, то есть "безопасность через неочевидность". Само по себе это не защита. Но в комплексе с другими мерами — снижает шум от автоматических атак.
Плагин WPS Hide Login делает именно это. Он перехватывает запросы к новому URL и перенаправляет на форму входа, а все запросы к оригинальному wp-login.php возвращают 404. Статистика из моей практики: после смены URL количество попыток брутфорса падает на 95-99% — просто потому что боты знают стандартный адрес и не ищут другие.
Но есть нюанс. Если вы забудете новый URL и потеряете доступ — придётся лезть в базу данных и удалять соответствующую опцию из таблицы wp_options. Я видел несколько таких случаев. Поэтому всегда записывайте кастомный URL в надёжное место.
-- Если потеряли доступ к кастомному URL входа,
-- выполните этот запрос в phpMyAdmin или через MySQL CLI
DELETE FROM wp_options WHERE option_name = 'whl_page';
-- Для плагина All-In-One WP Security
DELETE FROM wp_options WHERE option_name = 'aios_login_page_slug';
Двухфакторная аутентификация: обязательный слой
Даже если злоумышленник каким-то образом подобрал пароль — 2FA остановит его. Это самый надёжный дополнительный уровень защиты wp-login.php. Я настраиваю 2FA на всех сайтах клиентов без исключения.
Для WordPress лучшие варианты — плагины WP 2FA или Two Factor Authentication от Plugin Contributors. Оба поддерживают TOTP (Google Authenticator, Authy), email-коды и резервные коды на случай потери телефона. Подробную инструкцию по настройке двухфакторки я расписал отдельно — читайте статью двухфакторная аутентификация на сайте: настройка 2026.
Важный момент при настройке 2FA на многопользовательских сайтах: принудите всех администраторов и редакторов включить 2FA. Плагин WP 2FA умеет выставлять политику — если пользователь не настроил 2FA, при входе он будет перенаправлен на страницу настройки и не сможет зайти в панель, пока не завершит процесс. Это жёстко, но правильно.
Firewall и блокировка ботов на уровне сервера
Плагины безопасности вроде Wordfence или Solid Security (бывший iThemes Security) — это хорошо, но они работают внутри WordPress, то есть PHP уже запустился к тому моменту, как плагин заблокирует запрос. Настоящая защита начинается раньше.
Я настраиваю fail2ban на всех серверах. Это демон, который анализирует логи и автоматически добавляет IP в iptables при обнаружении подозрительной активности. Для WordPress создаём отдельный jail:
# /etc/fail2ban/filter.d/wordpress.conf
[Definition]
failregex = ^<HOST>.*POST.*(wp-login\.php|xmlrpc\.php).* (200|403|429)
ignoreregex =
# /etc/fail2ban/jail.local
[wordpress]
enabled = true
port = http,https
filter = wordpress
logpath = /var/log/nginx/access.log
maxretry = 5
findtime = 300
bantime = 86400
Параметры: 5 попыток за 5 минут — бан на 24 часа. Можно сделать жёстче. Для особо назойливых IP я вручную добавляю bantime = -1, что означает постоянный бан. Кстати, если хотите выстроить полноценную систему защиты на уровне сервера — рекомендую почитать про настройку Firewall для защиты сайта, там я разобрал тему значительно глубже.
Геоблокировка как крайняя мера
Иногда атаки идут из конкретных регионов. Если у вас сайт для русскоязычной аудитории, и 99% атак идут, например, из Нигерии или Бразилии — можно заблокировать целые страны на уровне Nginx через базу MaxMind GeoIP2. Это радикально, но иногда оправдано. Я использовал этот подход для одного клиента из сферы e-commerce: после блокировки 15 стран нагрузка от атак упала на 70%, а реальных покупателей оттуда не было вообще.
Мониторинг попыток взлома: как не пропустить реальную атаку
Настроить защиту — половина дела. Нужно ещё понимать, что происходит с сайтом. Я настраиваю уведомления о подозрительной активности для всех клиентов на поддержке WordPress.
Минимальный набор мониторинга для wp-login.php и xmlrpc.php:
- Уведомление при 10+ неудачных попытках входа за час (Wordfence умеет это из коробки)
- Алерт при входе с нового IP-адреса или из новой страны
- Уведомление при создании нового администратора
- Мониторинг изменений файлов ядра WordPress
- Еженедельный отчёт по заблокированным IP
Для анализа логов я часто использую простые bash-скрипты. Например, чтобы посмотреть топ атакующих IP за последние 24 часа:
#!/bin/bash
# Топ-20 IP, атакующих wp-login.php и xmlrpc.php за последние сутки
echo "=== Атаки на wp-login.php ==="
grep "wp-login.php" /var/log/nginx/access.log | \
grep "POST" | \
awk '{print $1}' | \
sort | uniq -c | sort -rn | head -20
echo ""
echo "=== Атаки на xmlrpc.php ==="
grep "xmlrpc.php" /var/log/nginx/access.log | \
awk '{print $1}' | \
sort | uniq -c | sort -rn | head -20
echo ""
echo "=== Текущие забаненные IP (fail2ban) ==="
fail2ban-client status wordpress | grep "Banned IP list"
Этот скрипт я запускаю через cron каждое утро и отправляю себе отчёт на почту. Занимает 5 минут на настройку, но даёт отличную картину происходящего.
Настройка плагинов безопасности: что реально работает
Рынок плагинов безопасности для WordPress огромен. Из того, что я реально использую и рекомендую клиентам:
Wordfence Security — самый функциональный вариант. Бесплатная версия закрывает большинство потребностей: WAF, сканер малвари, блокировка IP, защита входа. Платная версия добавляет real-time обновления правил (в бесплатной — с задержкой 30 дней), что на мой взгляд, принципиально для активно атакуемых сайтов. Настройки, которые я включаю всегда: лимит попыток входа (3 попытки, бан на 24 часа), блокировка сканирования, защита от перечисления пользователей.
Solid Security (iThemes Security) — хорошая альтернатива. Мне нравится их подход к hardening: они проходятся по чек-листу уязвимостей и предлагают исправить каждую. Особенно полезна функция "Security Check" — она автоматически находит проблемные настройки.
WPS Hide Login — только для смены URL входа. Лёгкий, не создаёт нагрузки, делает одно дело хорошо.
Что я не рекомендую ставить одновременно: несколько тяжёлых плагинов безопасности. Видел сайты, где стояли Wordfence + Sucuri + iThemes одновременно. Это не тройная защита — это тройная нагрузка и конфликты. Выберите один основной плагин.
Дополнительный хардинг WordPress
Защита xmlrpc.php и wp-login.php — это важно, но это часть более широкой картины. Несколько вещей, которые я делаю в комплексе:
Отключение перечисления пользователей. По умолчанию WordPress позволяет узнать логины всех авторов через URL вида /?author=1. Это облегчает брутфорс — злоумышленник знает реальные логины. Добавьте в functions.php:
<?php
// Запрет перечисления пользователей
add_action( 'init', function() {
if ( ! is_admin() ) {
if ( isset( $_REQUEST['author'] ) && is_numeric( $_REQUEST['author'] ) ) {
wp_redirect( home_url(), 301 );
exit;
}
}
} );
// Убираем имена пользователей из REST API для неавторизованных
add_filter( 'rest_endpoints', function( $endpoints ) {
if ( isset( $endpoints['/wp/v2/users'] ) ) {
foreach ( $endpoints['/wp/v2/users'] as $key => $endpoint ) {
if ( isset( $endpoint['permission_callback'] ) ) {
continue;
}
$endpoints['/wp/v2/users'][$key]['permission_callback'] = function() {
return current_user_can( 'list_users' );
};
}
}
return $endpoints;
} );
?>
Защита REST API. WordPress REST API — это ещё один вектор атаки, который часто упускают. Если вы не используете REST API для внешних интеграций, закройте его для неавторизованных пользователей. Если используете — ограничьте доступные эндпоинты.
Отключение редактора файлов в админке. Стандартный редактор тем и плагинов — это потенциальная дыра. Если злоумышленник получит доступ к админке, он сможет вставить вредоносный код прямо через браузер. Добавьте в wp-config.php:
define( 'DISALLOW_FILE_EDIT', true );
define( 'DISALLOW_FILE_MODS', true ); // Запрещает также установку плагинов/тем
И не забывайте про регулярные бэкапы. Даже идеальная защита не даёт 100% гарантии, и если что-то пойдёт не так — бэкап позволит восстановиться за минуты, а не за дни. Как правильно организовать резервное копирование, читайте в статье бэкапы сайта: как делать правильно и не терять данные.
Итоговый чек-лист: что проверить прямо сейчас
Я составил этот список по результатам аудитов, которые провожу для новых клиентов. Обычно на необработанном сайте закрыто 3-4 пункта из 12. После настройки — все 12.
- XML-RPC заблокирован на уровне Nginx/Apache (не только через плагин)
- Заголовок X-Pingback убран из HTTP-ответов
- На wp-login.php настроен rate limiting (не более 5 запросов в минуту с одного IP)
- Настроен HTTP Basic Auth для /wp-admin/ и wp-login.php
- Включена двухфакторная аутентификация для всех администраторов
- URL страницы входа изменён (опционально, но рекомендую)
- Fail2ban настроен и следит за логами WordPress
- Перечисление пользователей отключено
- REST API закрыт для неавторизованных (если не используется)
- DISALLOW_FILE_EDIT = true в wp-config.php
- PHP версии 8.2 или 8.3
- Автоматические бэкапы настроены и проверены
Если хотите, чтобы я провёл аудит вашего WordPress-сайта и настроил всё это — обращайтесь на страницу поддержки WordPress. Также занимаюсь доработкой сайтов любой сложности. За годы практики я видел последствия взломов через xmlrpc.php и wp-login.php — от вставки спам-ссылок до полного уничтожения данных. Настройка защиты занимает несколько часов. Восстановление после взлома — иногда несколько дней, и не всегда успешно.
Безопасность — это не разовая акция, а постоянный процесс. Мир угроз меняется, появляются новые уязвимости, обновляются плагины. Настройте мониторинг, следите за обновлениями WordPress и плагинов, проверяйте логи хотя бы раз в неделю. И тогда ваш сайт останется вашим.
Хотите надёжно защитить свой сайт на WordPress от атак?
Оставьте заявку, и наши специалисты настроят комплексную защиту вашего сайта в кратчайшие сроки.