Сценарий типичный: XML-RPC на сайте нужен, но не для всех. Например, его использует мобильное приложение, внешний сервис публикации или интеграция с мониторингом. При этом открытый xmlrpc.php часто становится лишней точкой входа для перебора методов и шумных запросов. Полностью отключать его не всегда удобно, поэтому практичнее ограничить доступ по IP.
Ниже — рабочая схема без выдуманных хуков и без «магии» на уровне плагинов. Сначала разберём, как понять, что именно у вас сейчас происходит, затем покажу два варианта: через сервер и через WordPress. Второй вариант полезен, если нет доступа к конфигу веб-сервера или нужно быстро проверить гипотезу.
Когда ограничение по IP действительно нужно
Закрывать XML-RPC по IP имеет смысл не «на всякий случай», а когда у вас есть понятный список доверенных источников. Это может быть один офисный адрес, IP сервиса деплоя, адрес VPN или подсеть, через которую работает интеграция. Если IP у сервиса плавающий, правило по одному адресу быстро начнёт мешать, и тогда лучше смотреть в сторону другого способа аутентификации или вообще отказаться от XML-RPC.
Важно понимать ограничение: если у вас динамический IP у домашнего интернета, мобильная сеть или облачный сервис без фиксированного диапазона, жёсткая фильтрация по одному адресу будет ломать легитимные запросы. В таком случае сначала уточните, можно ли получить статический IP или список подсетей.
Диагностика: что проверить до изменений
Перед тем как что-то блокировать, проверьте три вещи: используется ли XML-RPC вообще, кто к нему обращается и не завязан ли на него критичный процесс. Иначе легко отрезать себе интеграцию и искать причину уже после инцидента.
Как понять, что endpoint живой
Откройте /xmlrpc.php в браузере или через curl. Нормальный ответ для GET-запроса обычно не означает, что метод можно вызвать, но сам файл доступен. Для более точной проверки используйте POST-запрос с тестовым методом.
curl -i https://example.com/xmlrpc.phpЕсли endpoint отвечает, это ещё не проблема. Проблема начинается, когда он доступен всем, хотя нужен только нескольким адресам.
Что смотреть в логах
Полезно проверить access log веб-сервера и, если есть, логи WAF или CDN. Ищите частые POST-запросы к /xmlrpc.php, особенно с разных IP и с ошибками авторизации. Это хороший признак того, что endpoint сканируют или используют для перебора.
- много запросов к
/xmlrpc.phpбез понятного источника; - повторяющиеся 401, 403 или 405 в ответах;
- запросы из странных подсетей, не связанных с вашими сервисами;
- ошибки в интеграциях после прошлых ограничений XML-RPC.
Варианты решения: сервер, WordPress или комбинированно
Если есть доступ к конфигу сервера, лучше ограничивать доступ там. Это дешевле по ресурсам: запросы отсекаются до загрузки WordPress. Если доступа к серверу нет, можно сделать проверку в mu-plugin или обычном плагине. Для production чаще выбирают серверный вариант, а WordPress-уровень оставляют как запасной.
| Подход | Плюсы | Минусы |
|---|---|---|
| Серверный allowlist | Ранний отказ, меньше нагрузки, проще для безопасности | Нужен доступ к nginx/apache, сложнее при CDN и прокси |
| Проверка в WordPress | Можно внедрить без правок сервера | WordPress всё равно загружается, решение зависит от PHP |
| Комбинированный | Можно закрыть на сервере и оставить резервную проверку в коде | Нужно следить, чтобы правила не конфликтовали |
Пошаговое решение через сервер
Если сайт работает на nginx, самый прямой путь — разрешить xmlrpc.php только с нужных IP и всем остальным отдавать 403. Пример ниже рассчитан на отдельный location для файла.
location = /xmlrpc.php {
allow 203.0.113.10;
allow 198.51.100.0/24;
deny all;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/xmlrpc.php;
fastcgi_pass php-fpm;
}Если у вас Apache, логика та же: разрешаете доверенные адреса и запрещаете остальные. Для xmlrpc.php удобно использовать отдельное правило в .htaccess или конфиге виртуального хоста.
<Files "xmlrpc.php">
Require ip 203.0.113.10
Require ip 198.51.100.0/24
</Files>Если сайт стоит за CDN или reverse proxy, проверьте, что сервер видит реальный IP клиента, а не адрес прокси. Иначе вы случайно разрешите только IP CDN, а не нужных пользователей. Для nginx это обычно решается настройкой real_ip_header и доверенных прокси, но конкретная конфигурация зависит от вашей схемы.
Проверка через WordPress-код, если сервер трогать нельзя
Когда доступа к конфигу нет, можно перехватить запрос до выполнения XML-RPC и вернуть 403 для всех, кроме доверенных IP. Для этого подходит фильтр xmlrpc_enabled. Он не отключает endpoint физически, но блокирует обработку XML-RPC на уровне WordPress.
<?php
add_filter('xmlrpc_enabled', function ($enabled) {
$allowed_ips = array(
'203.0.113.10',
'198.51.100.0/24',
);
$remote_ip = $_SERVER['REMOTE_ADDR'] ?? '';
if ($remote_ip === '') {
return false;
}
foreach ($allowed_ips as $allowed) {
if (wphide_ip_matches($remote_ip, $allowed)) {
return $enabled;
}
}
return false;
});
function wphide_ip_matches($ip, $allowed) {
if (strpos($allowed, '/') === false) {
return hash_equals($allowed, $ip);
}
list($subnet, $mask) = explode('/', $allowed, 2);
$mask = (int) $mask;
$ip_long = ip2long($ip);
$subnet_long = ip2long($subnet);
if ($ip_long === false || $subnet_long === false) {
return false;
}
$mask_long = -1 << (32 - $mask);
return (($ip_long & $mask_long) === ($subnet_long & $mask_long));
}Этот вариант лучше размещать в mu-plugin, чтобы он не зависел от темы. Файл можно положить, например, в wp-content/mu-plugins/limit-xmlrpc-by-ip.php. Если mu-plugins у вас ещё нет, создайте каталог вручную.
Почему здесь не стоит использовать обычный плагин
Обычный плагин можно случайно отключить, удалить или забыть после обновления темы. Для ограничения доступа к XML-RPC это плохой сценарий: защита должна быть всегда активна. mu-plugin загружается автоматически и не требует активации в админке.
Как проверить, что ограничение сработало
Проверка должна быть не только «страница открывается», а именно по сценариям доступа. Сначала сделайте запрос с разрешённого IP, затем с запрещённого. Если у вас нет второго адреса под рукой, можно проверить через VPN или временно добавить тестовый IP в deny-список на сервере.
curl -i -X POST https://example.com/xmlrpc.php \
-H 'Content-Type: text/xml' \
--data '<?xml version="1.0"?><methodCall><methodName>system.listMethods</methodName><params></params></methodCall>'Что считать нормальным результатом:
- с разрешённого IP endpoint отвечает так, как ожидает ваша интеграция;
- с запрещённого IP возвращается 403 или обработка не доходит до XML-RPC;
- в логах нет всплеска ошибок PHP после внедрения;
- внешний сервис, который должен работать, продолжает авторизоваться.
Если вы ограничивали доступ через WordPress-фильтр, проверьте не только HTTP-код, но и то, что в логах не появляются фатальные ошибки из-за некорректной функции сравнения IP или пустого REMOTE_ADDR.
Частые ошибки и как их исправить
Забыли про прокси или CDN
Если сайт за Cloudflare, балансировщиком или nginx reverse proxy, REMOTE_ADDR может содержать адрес прокси. Тогда правило по IP не работает как задумано. Решение — сначала корректно настроить получение реального IP на уровне сервера, а потом уже строить allowlist.
Ограничили только один адрес, хотя сервис использует подсеть
У некоторых провайдеров IP меняется внутри диапазона. Если разрешить только один адрес, интеграция начнёт падать после очередной смены. Проверьте документацию сервиса: часто там есть список подсетей, которые можно разрешить целиком.
Положили код в тему
При смене темы защита исчезнет. Для таких задач используйте mu-plugin или отдельный мини-плагин, который не зависит от шаблона.
Смешали блокировку XML-RPC с отключением REST API
Это разные механизмы. Если у вас уже отключён REST API, а интеграция всё равно использует XML-RPC, проблемы будут не там, где вы их ищете. Сначала зафиксируйте, какой именно endpoint нужен конкретному сервису.
Практические советы по безопасности и производительности
Если XML-RPC нужен только для одного внешнего сервиса, держите allowlist коротким и документированным. Не оставляйте в правилах старые IP «на всякий случай» — это превращает ограничение в формальность. После смены подрядчика, VPN или хостинга пересматривайте список адресов.
Для сайтов с высокой нагрузкой серверный вариант предпочтительнее: он отсекает лишние запросы раньше и не тратит ресурсы PHP. Если у вас уже есть слой защиты вроде WAF, можно добавить правило и там, но не полагайтесь только на него: конфигурация WAF иногда меняется отдельно от сайта.
Если нужна более широкая чистка технических дублей и лишних точек входа, имеет смысл смотреть на инструменты уровня Clearfy Pro: они не заменяют точечную фильтрацию XML-RPC, но помогают убрать часть лишнего шума на сайте. Ставить такой инструмент стоит только если он реально закрывает ваши задачи, а не ради ещё одного слоя без понимания, что именно он делает.
В итоге рабочая схема простая: сначала выясняете, кто и зачем использует XML-RPC, потом ограничиваете доступ на сервере или через xmlrpc_enabled, затем проверяете реальные запросы и логи. Если после внедрения интеграция продолжает работать, а посторонние запросы получают отказ, задача решена правильно.