Защита XML-RPC и wp-login.php: полное руководство 2026

Каждую неделю я смотрю логи серверов своих клиентов и вижу одно и то же: тысячи запросов к 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 — ещё проще. Это стандартная страница входа, которая всегда находится по предсказуемому адресу. Боты знают этот адрес наизусть и долбят его круглосуточно. Без ограничений на количество попыток — это просто открытый буфет для подбора паролей.

⚠️
Реальная угроза: По данным Wordfence за 2025 год, более 90 миллиардов попыток входа в WordPress было зафиксировано только за первое полугодие. Большинство атак идут именно через xmlrpc.php и wp-login.php. Если вы думаете "мой сайт маленький, кому он нужен" — вы ошибаетесь. Боты атакуют всех подряд по спискам IP.

Полное отключение 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 — это разные уровни защиты, и они должны быть независимы.

💡
Совет по паролям: Для HTTP Basic Auth используйте генератор случайных паролей длиной минимум 20 символов. Можно сгенерировать прямо в терминале: 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%, а реальных покупателей оттуда не было вообще.

ℹ️
Про Wordfence и нагрузку: Wordfence в режиме Extended Protection умеет работать до загрузки WordPress — это режим Firewall на уровне PHP, который активируется через auto_prepend_file в php.ini. Это лучше, чем стандартный режим, но всё равно хуже блокировки на уровне Nginx. На PHP 8.2-8.3 производительность заметно лучше, чем на старых версиях — если у вас ещё PHP 7.4, это ещё один аргумент для обновления.

Мониторинг попыток взлома: как не пропустить реальную атаку

Настроить защиту — половина дела. Нужно ещё понимать, что происходит с сайтом. Я настраиваю уведомления о подозрительной активности для всех клиентов на поддержке WordPress.

Минимальный набор мониторинга для wp-login.php и xmlrpc.php:

Для анализа логов я часто использую простые 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% гарантии, и если что-то пойдёт не так — бэкап позволит восстановиться за минуты, а не за дни. Как правильно организовать резервное копирование, читайте в статье бэкапы сайта: как делать правильно и не терять данные.

⚠️
Версии PHP имеют значение: PHP 7.4 уже не получает обновления безопасности с декабря 2022 года. PHP 8.0 — с ноября 2023 года. Если вы до сих пор на этих версиях — это критическая уязвимость. Минимум — PHP 8.1 (поддержка до декабря 2025), рекомендую — PHP 8.2 или 8.3. На более новых версиях и Wordfence работает эффективнее, и WordPress быстрее.

Итоговый чек-лист: что проверить прямо сейчас

Я составил этот список по результатам аудитов, которые провожу для новых клиентов. Обычно на необработанном сайте закрыто 3-4 пункта из 12. После настройки — все 12.

  1. XML-RPC заблокирован на уровне Nginx/Apache (не только через плагин)
  2. Заголовок X-Pingback убран из HTTP-ответов
  3. На wp-login.php настроен rate limiting (не более 5 запросов в минуту с одного IP)
  4. Настроен HTTP Basic Auth для /wp-admin/ и wp-login.php
  5. Включена двухфакторная аутентификация для всех администраторов
  6. URL страницы входа изменён (опционально, но рекомендую)
  7. Fail2ban настроен и следит за логами WordPress
  8. Перечисление пользователей отключено
  9. REST API закрыт для неавторизованных (если не используется)
  10. DISALLOW_FILE_EDIT = true в wp-config.php
  11. PHP версии 8.2 или 8.3
  12. Автоматические бэкапы настроены и проверены

Если хотите, чтобы я провёл аудит вашего WordPress-сайта и настроил всё это — обращайтесь на страницу поддержки WordPress. Также занимаюсь доработкой сайтов любой сложности. За годы практики я видел последствия взломов через xmlrpc.php и wp-login.php — от вставки спам-ссылок до полного уничтожения данных. Настройка защиты занимает несколько часов. Восстановление после взлома — иногда несколько дней, и не всегда успешно.

Безопасность — это не разовая акция, а постоянный процесс. Мир угроз меняется, появляются новые уязвимости, обновляются плагины. Настройте мониторинг, следите за обновлениями WordPress и плагинов, проверяйте логи хотя бы раз в неделю. И тогда ваш сайт останется вашим.

Хотите надёжно защитить свой сайт на WordPress от атак?

Оставьте заявку, и наши специалисты настроят комплексную защиту вашего сайта в кратчайшие сроки.

П
Павел
Веб-разработчик · 10+ лет опыта · Bitrix, WordPress, Laravel

Читайте также

Почему сайт медленно работает и как это исправить Как настроить автообновление CMS: WordPress, Bitrix, Laravel SEO-аудит сайта: что проверить в первую очередь