На VPS/VDS WordPress часто держит открытыми два лишних канала: xmlrpc.php и часть REST API через /wp-json/. Первый нужен редко, второй — уже встроен в ядро и используется редактором, блоками, некоторыми плагинами и внешними интеграциями. Поэтому задача обычно не в том, чтобы «всё запретить», а в том, чтобы убрать ненужный доступ и не сломать рабочие сценарии.
Ниже — рабочая схема: сначала понять, что именно у вас используется, затем отключить только то, что не нужно, и проверить, что сайт не потерял функциональность.
Когда это вообще имеет смысл
Отключать XML-RPC и резать REST API стоит не «на всякий случай», а если вы видите один из типичных сценариев:
- в логах много запросов к
/xmlrpc.phpс перебором логинов или pingback-активностью; - сайт не использует старые мобильные приложения WordPress, Jetpack или внешние сервисы, которым нужен XML-RPC;
- REST API нужен только для фронтенда и админки, но вы хотите ограничить доступ к публичным эндпоинтам снаружи;
- на сервере уже есть WAF/фильтрация, и вы хотите убрать лишнюю поверхность атаки на уровне Nginx или Apache.
Если у вас подключены конструкторы, headless-фронтенд, мобильное приложение или интеграции через REST, не стоит блокировать /wp-json/ целиком. В этом случае лучше ограничивать только отдельные маршруты или доступ по условиям.
Диагностика: что именно используется сейчас
Перед изменениями проверьте, есть ли реальные обращения к этим точкам входа. На VDS это проще всего сделать по логам веб-сервера.
Проверка по access log
Для Nginx:
grep -E "xmlrpc\.php|wp-json" /var/log/nginx/access.log | tail -n 50Для Apache путь может отличаться, но логика та же. Если видите постоянные запросы к xmlrpc.php с разных IP и без полезной нагрузки, это хороший кандидат на отключение. Если /wp-json/ дергает ваш фронтенд, тема или плагин — блокировать его нельзя.
Проверка зависимостей в админке
Посмотрите, используете ли вы:
- Jetpack;
- старые мобильные приложения WordPress;
- внешние публикации через XML-RPC;
- headless-сценарии, где фронтенд получает данные из REST API;
- плагины, которые явно работают через REST.
Если ответ «да» хотя бы по одному пункту, сначала тестируйте на staging или через временное ограничение по IP, а не рубите доступ сразу на боевом сайте.
Как отключить XML-RPC без лишнего риска
Самый безопасный вариант — отключить обработку XML-RPC на уровне WordPress, а не только скрывать файл на веб-сервере. Тогда даже если файл доступен, WordPress не будет принимать запросы.
Вариант через код в functions.php или mu-plugin
Лучше добавить это в mu-plugin, чтобы правило не потерялось при смене темы. Пример:
<?php
/**
* Plugin Name: Disable XML-RPC
*/
add_filter( 'xmlrpc_enabled', '__return_false' );Если нужен именно серверный запрет, можно добавить правило в Nginx:
location = /xmlrpc.php {
deny all;
access_log off;
log_not_found off;
}Для Apache подойдет блокировка через .htaccess:
<Files xmlrpc.php>
Require all denied
</Files>Серверный запрет полезен как дополнительный слой, но не заменяет проверку зависимостей. Если какой-то плагин всё же обращается к XML-RPC, он просто начнет получать ошибку.
Как ограничить доступ к wp-json, не ломая сайт
Полностью закрывать REST API на живом WordPress — плохая идея, если сайт использует редактор блоков или современные плагины. Вместо этого обычно ограничивают только публичные эндпоинты для неавторизованных пользователей.
Ограничение через код для части маршрутов
Если вам нужно закрыть собственные REST-маршруты или чувствительные данные, используйте проверку прав в permission_callback. Это правильнее, чем пытаться блокировать весь /wp-json/ на сервере.
<?php
add_action( 'rest_api_init', function () {
register_rest_route( 'myplugin/v1', '/secret', array(
'methods' => 'GET',
'callback' => 'myplugin_get_secret_data',
'permission_callback' => function () {
return current_user_can( 'manage_options' );
},
) );
} );Если маршрут уже существует, а вы не контролируете его регистрацию, можно хотя бы проверять права внутри callback и не отдавать лишние данные гостям.
Серверная блокировка только для конкретных путей
Иногда нужно закрыть отдельные REST-эндпоинты, которые используются только в админке или внутренними интеграциями. Тогда лучше блокировать не весь /wp-json/, а конкретный путь. Например, для Nginx:
location ~* ^/wp-json/wp/v2/users {
deny all;
access_log off;
log_not_found off;
}Это не универсальное правило, а пример. Перед применением проверьте, не нужен ли вам этот маршрут для авторизации, редактора или плагинов.
Пошаговое решение на VDS
- Проверьте логи и список подключенных интеграций.
- Отключите XML-RPC через
xmlrpc_enabledили серверное правило. - Не закрывайте
/wp-json/целиком, если сайт использует блоки, редактор или REST-плагины. - Ограничьте только чувствительные REST-маршруты через
permission_callbackили правила веб-сервера. - Очистите кеш сайта и кеш на уровне Nginx/плагина, если он есть.
- Проверьте логи после изменения и убедитесь, что нет 500/403 на нужных страницах.
Проверка результата после внедрения
После изменений важно не ограничиться «вроде работает». Проверьте несколько конкретных вещей.
- Откройте
/xmlrpc.phpв браузере или черезcurl— должен быть отказ или пустой ответ в зависимости от правила. - Проверьте главную страницу, записи, страницу редактирования в админке и сохранение поста.
- Если используете редактор блоков, убедитесь, что запросы к REST API не получают 403.
- Посмотрите access log: число обращений к
xmlrpc.phpдолжно упасть до нуля или почти нуля.
Пример проверки через curl:
curl -I https://example.com/xmlrpc.php
curl -I https://example.com/wp-json/Для REST API важен не только код ответа, но и контекст. 200 на /wp-json/ сам по себе не проблема. Проблема — если закрылись маршруты, которые нужны админке или фронтенду.
Частые ошибки и как их исправить
Закрыли весь wp-json и сломали редактор
Это самая частая ошибка. Gutenberg, некоторые плагины и даже часть стандартных функций WordPress используют REST API. Если после блокировки перестали сохраняться записи или не подгружаются блоки, откатите серверное правило и ограничьте только конкретные маршруты.
Отключили XML-RPC, но забыли про Jetpack или внешнюю интеграцию
Если после запрета перестала синхронизироваться публикация или статистика, проверьте, не завязана ли интеграция на XML-RPC. В таком случае либо возвращайте доступ, либо переводите сервис на REST API, если это возможно.
Добавили правило в тему, а потом сменили шаблон
Код в functions.php темы — не лучшее место для таких ограничений. При смене темы защита исчезнет. Для постоянных правил используйте mu-plugin или отдельный мини-плагин.
Заблокировали только на уровне Nginx, но WordPress всё равно принимает запросы
Если у вас несколько виртуальных хостов, прокси или нестандартная схема, правило могло сработать не там, где нужно. Проверьте конфиг именно того сайта, который обслуживает домен, и не забудьте перезагрузить Nginx после правок.
Что делать с безопасностью и производительностью дальше
Отключение XML-RPC и точечное ограничение REST API — это не замена нормальной защите сервера. На VDS имеет смысл держать в порядке еще несколько вещей:
- ограничить доступ к
/wp-adminпо IP, если админка используется из фиксированной сети; - включить актуальные обновления WordPress, темы и плагинов;
- проверить права на файлы и каталоги;
- не хранить в коде лишние секреты и токены;
- следить за логами 403/401 и аномальными запросами.
Если вам нужен более широкий набор технических правок без ручной сборки правил, иногда удобнее использовать профильный плагин для чистки и SEO-оптимизации, например Clearfy Pro: https://wpshop.ru/plugins/clearfy. Но и в этом случае серверные ограничения лучше проверять отдельно, а не полагаться только на интерфейс плагина.
| Подход | Что делает | Плюс | Минус |
|---|---|---|---|
| Код в mu-plugin | Отключает XML-RPC или проверяет права REST | Не зависит от темы | Нужно поддерживать вручную |
| Nginx/Apache | Блокирует запросы на уровне веб-сервера | Режет лишний трафик раньше WordPress | Можно случайно сломать нужный маршрут |
| Плагин | Даёт интерфейс для части ограничений | Быстро включить без правки кода | Дополнительная зависимость и нагрузка |
Если после правок сайт стал отвечать нестабильно, сначала откатите серверные блокировки, затем проверьте, не остались ли старые правила в кеше или в нескольких конфигурациях виртуального хоста. На VDS такие ошибки часто выглядят как «WordPress сломался», хотя на деле проблема в одном лишнем location или забытом Require all denied.