Как ограничить доступ к XML-RPC только для нужных IP в WordPress

XML-RPC в WordPress часто отключают целиком, но это не всегда подходит. Если у вас остались рабочие сценарии вроде мобильного приложения, внешнего клиента публикации или интеграции с сервисом, безопаснее не рубить endpoint полностью, а разрешить его только с нужных IP.

Ниже — практический вариант без выдуманных хуков и без лишней магии: сначала определяем, действительно ли XML-RPC нужен, потом ограничиваем доступ на уровне сервера или WordPress, а затем проверяем, что лишние запросы режутся, а нужные проходят.

Когда ограничение по IP лучше полного отключения

Полное отключение XML-RPC удобно, если вы точно знаете, что он нигде не используется. Но на реальных сайтах это не всегда так. Чаще всего XML-RPC нужен для одной из задач:

  • публикация через внешние редакторы;
  • подключение мобильного приложения WordPress;
  • старые интеграции, которые не переведены на REST API;
  • автоматизация, завязанная именно на XML-RPC, а не на REST.

Если хотя бы один такой сценарий есть, лучше ограничить доступ по IP. Это снижает поверхность атаки и не ломает рабочие интеграции.

Диагностика: кто реально ходит в xmlrpc.php

Перед изменениями стоит понять, есть ли живые обращения к /xmlrpc.php. Если у вас есть доступ к логам веб-сервера, это самый надёжный способ. Ищите запросы к файлу xmlrpc.php и смотрите IP, User-Agent и частоту.

Что искать в логах

В access-логах обычно достаточно фильтра по имени файла. Пример для nginx:

grep "xmlrpc.php" /var/log/nginx/access.log | tail -n 50

Если запросы идут с одного-двух адресов, это хороший кандидат на whitelist. Если обращений много и они с разных IP, сначала разберитесь, какие из них принадлежат вашим сервисам, а какие — сканерам и брутфорсу.

Проверка снаружи

Можно вручную проверить ответ endpoint с разных IP. Если у вас есть VPS или тестовый сервер с другим адресом, выполните запрос:

curl -i https://example.com/xmlrpc.php

Нормальный доступный endpoint обычно отвечает не 404, а сообщением о том, что XML-RPC сервер принимает только POST-запросы. Это уже сигнал, что файл доступен извне.

Как ограничить xmlrpc.php только для нужных IP

Есть два рабочих подхода: на уровне веб-сервера и на уровне WordPress. Если есть доступ к конфигу nginx или Apache, лучше делать ограничение там. Это быстрее и надёжнее. Если доступа к серверу нет, можно поставить проверку в mu-plugin или в обычный плагин.

ПодходПлюсыМинусы
nginx / ApacheРанний отказ, меньше нагрузки, проще защититьНужен доступ к конфигу сервера
WordPress-кодМожно внедрить без правок веб-сервераЗапрос уже дошёл до PHP
Полное отключениеСамый жёсткий вариантЛомает все интеграции, которые используют XML-RPC

Вариант 1: ограничение в nginx

Если сайт работает на nginx, можно разрешить доступ только с конкретных IP. Пример для отдельного location:

location = /xmlrpc.php {
    allow 203.0.113.10;
    allow 198.51.100.25;
    deny all;

    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass php-fpm;
}

Замените IP на свои. Если у вас несколько доверенных адресов, добавьте их отдельными строками allow. Всё остальное будет получать отказ.

Вариант 2: ограничение в Apache

Для Apache можно использовать правила в .htaccess или в конфиге виртуального хоста. Если сервер поддерживает mod_authz_core, подойдёт такой вариант:

<Files "xmlrpc.php">
    Require ip 203.0.113.10 198.51.100.25
</Files>

Если у вас старый Apache с другой схемой авторизации, синтаксис может отличаться. В таком случае лучше править основной конфиг виртуального хоста, а не надеяться на универсальный .htaccess.

Вариант 3: проверка в WordPress через mu-plugin

Если серверный доступ недоступен, можно отфильтровать запросы в WordPress. Это не так рано, как на уровне nginx, но всё ещё рабочий вариант. Создайте файл wp-content/mu-plugins/restrict-xmlrpc.php:

<?php
/**
 * Plugin Name: Restrict XML-RPC by IP
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

add_filter( 'xmlrpc_enabled', function( $enabled ) {
    if ( ! $enabled ) {
        return false;
    }

    $allowed_ips = array(
        '203.0.113.10',
        '198.51.100.25',
    );

    $remote_ip = $_SERVER['REMOTE_ADDR'] ?? '';

    if ( in_array( $remote_ip, $allowed_ips, true ) ) {
        return true;
    }

    status_header( 403 );
    nocache_headers();
    exit;
} );

Этот вариант полезен, если нужно быстро закрыть доступ без правок nginx/Apache. Но помните: запрос уже дошёл до PHP, поэтому для высоконагруженного сайта серверное ограничение предпочтительнее.

Пошаговое решение без лишнего риска

  1. Соберите список IP, которым действительно нужен XML-RPC.
  2. Проверьте, что эти адреса статические. Если IP меняется, whitelist будет ломаться.
  3. Сделайте резервную копию конфигурации сервера или файла, который будете менять.
  4. Внедрите ограничение на уровне nginx или Apache, если есть доступ.
  5. Если доступа к серверу нет, используйте mu-plugin или обычный плагин.
  6. Проверьте доступ с разрешённого и запрещённого IP.

Как проверить, что ограничение работает

Проверка должна быть с двух сторон: с доверенного адреса и с внешнего адреса, который не входит в whitelist.

Проверка с разрешённого IP

С доверенного сервера выполните:

curl -i https://example.com/xmlrpc.php

Если endpoint нужен для интеграции, он должен отвечать так, как и раньше. Для XML-RPC это может быть ответ с ошибкой метода или сообщение о том, что сервер принимает только POST. Главное — не получить 403 от вашего ограничения.

Проверка с запрещённого IP

С любого другого адреса запрос должен завершаться отказом. В зависимости от реализации это может быть 403 Forbidden или другой код, но доступ к XML-RPC должен быть закрыт.

Дополнительно проверьте, что:

  • мобильное приложение WordPress всё ещё подключается, если оно в whitelist;
  • внешний редактор публикует записи без ошибок;
  • в логах нет постоянных 500-ошибок после изменения конфигурации;
  • страница сайта и админка работают как раньше.

Частые ошибки и как их исправить

Ограничили не тот IP

Самая частая проблема — в whitelist добавляют IP локальной сети, а запросы на сервер идут через NAT, CDN или прокси. В результате нужный сервис получает 403. Решение простое: смотрите реальный адрес в логах и проверяйте цепочку проксирования.

Сломали доступ через CDN или reverse proxy

Если сайт стоит за Cloudflare, nginx или другим прокси, REMOTE_ADDR может показывать не конечного клиента, а адрес прокси. Тогда проверка в WordPress будет работать неправильно. В такой схеме лучше настраивать ограничение на уровне самого прокси или корректно разбирать заголовки, которым вы доверяете.

Добавили правило, но забыли перезагрузить конфиг

Для nginx и Apache изменения в конфиге не всегда применяются сразу. После правки проверьте синтаксис и перезагрузите сервис. Для nginx это обычно выглядит так:

nginx -t
systemctl reload nginx

Если синтаксис сломан, не перезагружайте сервис вслепую: сначала исправьте ошибку в конфиге.

Оставили XML-RPC открытым для всех POST-запросов

Иногда делают проверку только на уровне WordPress, но забывают, что endpoint всё равно доступен и может нагружать PHP. Если есть возможность, лучше закрыть его на веб-сервере, а в WordPress оставить только дополнительную страховку.

Практические советы по безопасности и производительности

Если XML-RPC нужен только одной интеграции, не держите его открытым для всего интернета. Белый список из нескольких IP обычно проще сопровождать, чем потом разбирать последствия массовых попыток входа.

Полезно также:

  • вести отдельный список сервисов, которым нужен XML-RPC, с их IP и контактами;
  • проверять, не появился ли у провайдера сервиса новый адрес;
  • не смешивать ограничение XML-RPC с отключением REST API — это разные механизмы;
  • при возможности переводить старые интеграции на REST API или webhook-логику;
  • держать правило в конфиге сервера, а не только в теме оформления.

Если вы используете плагины для общей защиты сайта, проверьте, не дублируют ли они это ограничение. Иногда два разных правила дают неожиданный результат: один слой разрешает, второй блокирует, и отладка занимает лишнее время.

Для сайтов, где важна чистка лишних следов и снижение поверхности атаки, иногда удобно сочетать точечные ограничения с инструментами вроде Clearfy Pro, но только если вам действительно нужен набор таких функций, а не ради самого плагина. Сначала решайте задачу на уровне сервера и архитектуры, потом уже добавляйте надстройки.

Когда лучше всё-таки отключить XML-RPC полностью

Если после проверки выяснилось, что XML-RPC не нужен ни одной интеграции, его можно отключить полностью. Это проще в сопровождении, чем whitelist, который надо поддерживать вручную. Но делать это стоит только после проверки всех клиентов и сервисов, иначе вы получите скрытую поломку, которая всплывёт позже.

Практический критерий простой: если вы не можете назвать хотя бы один реальный сценарий использования XML-RPC на сайте, вероятно, он вам не нужен. Если сценарий есть, ограничение по IP обычно даёт лучший баланс между безопасностью и совместимостью.

⭐⭐⭐⭐⭐