Каждый день боты методично перебирают пароли к тысячам WordPress-сайтов - и ваш не исключение. Стандартный адрес входа в административную панель известен всем: /wp-admin и /wp-login.php публичны по умолчанию, и любой желающий может попробовать туда попасть. Я занимаюсь веб-разработкой с 2013 года, руковожу студией «Мельница» (melnyca.ru), и за это время видел сотни сайтов, взломанных именно через брутфорс формы входа. Закрыть доступ к wp-admin посторонним - это первое, что я делаю на любом новом проекте. Block access к административной зоне на уровне сервера снижает нагрузку, убирает целый класс атак и не требует сторонних плагинов.

В этой статье разберём три подхода: ограничение через .htaccess для Apache, настройку nginx и PHP-код в functions.php. Также рассмотрим HTTP-аутентификацию как дополнительный рубеж защиты. Каждый метод подходит для разных ситуаций - в зависимости от вашего хостинга и уровня доступа к серверу. Статья рассчитана на владельцев WordPress-сайтов и вебмастеров; если вы работаете с другими CMS - логика похожа, но конкретные настройки отличаются.

Почему стандартная защита WordPress недостаточна

Схема брутфорс-атаки на форму входа WordPress

WordPress из коробки защищает административную панель только одним рубежом - формой входа с логином и паролем. Казалось бы, этого достаточно: поставил сложный пароль, и всё. Но проблема в том, что сама форма входа остаётся публичной и доступна любому адресу в интернете. Боты знают об этом и активно этим пользуются.

Типичная картина на среднестатистическом WordPress-сайте без дополнительной блокировки: сотни запросов в сутки к /wp-login.php, автоматический перебор связок логин-пароль, сканирование xmlrpc.php. Всё это создаёт нагрузку на сервер, засоряет логи и рано или поздно приводит к успешному взлому - особенно если где-то используется слабый пароль или устаревший плагин с уязвимостью.

Концепция «двойной защиты» решает эту проблему иначе. Первый слой - серверный: запрос от постороннего IP просто не доходит до WordPress, сервер возвращает 403 или перенаправляет на другую страницу. Второй слой - штатная аутентификация WordPress для тех, кому доступ разрешён. Держать wp-admin публичным - всё равно что оставлять входную дверь офиса открытой в расчёте на то, что замок на сейфе внутри достаточно надёжен.

В текущей реальности угроза брутфорса и сканирования особенно актуальна для сайтов на популярных CMS. WordPress занимает больше 40% рынка, а значит, боты заточены именно под него. Стандартные меры - сложный пароль, капча, ограничение попыток входа через плагины - полезны, но работают уже после того, как запрос дошёл до PHP. Серверная блокировка не даёт запросу дойти вообще. Именно поэтому block access на уровне веб-сервера я считаю обязательным шагом, а не опциональным.

Как закрыть wp-admin через .htaccess (Apache)

Если ваш сайт работает на Apache (большинство виртуальных хостингов), самый простой и надёжный способ - создать файл .htaccess прямо в папке /wp-admin. Важный момент: этот файл создаётся именно в папке wp-admin, а не в корне сайта. Тогда правила применяются только к административной зоне и не затрагивают остальной сайт.

Базовая инструкция:

  1. Подключитесь к серверу через FTP, cPanel или SSH.
  2. Перейдите в папку /wp-admin.
  3. Создайте файл .htaccess (или откройте существующий).
  4. Добавьте следующий код, заменив IP на ваш реальный адрес.

Сценарий 1: разрешить доступ только с вашего IP, всем остальным - deny from:

Order deny,allow
Deny from all
Allow from 123.456.789.0

Сценарий 2: заблокировать конкретные IP-адреса (например, источники атак), остальным оставить доступ:

Order allow,deny
Allow from all
Deny from 111.222.333.0
Deny from 555.666.777.0

Важное предупреждение: если у вас динамический IP (меняется при каждом подключении), первый сценарий заблокирует и вас самих после смены адреса. В таком случае либо используйте диапазон подсети (например, 123.456.789), либо совмещайте IP-блокировку с HTTP-аутентификацией - об этом расскажу дальше.

Синтаксис директив отличается в зависимости от версии Apache. Делать вид, что этой разницы не существует, нельзя - неправильный синтаксис либо не сработает, либо сломает сайт целиком:

Параметр Apache 2.2 Apache 2.4
Запретить всем Deny from all Require all denied
Разрешить IP Allow from 1.2.3.4 Require ip 1.2.3.4
Порядок обработки Order deny,allow не нужен (RequireAny/RequireAll)
Где используется Старые хостинги Современные серверы

Проверить версию Apache можно командой apache2 -v по SSH или запросив поддержку хостинга. На большинстве современных серверов уже Apache 2.4, поэтому для текущей конфигурации предпочтителен синтаксис с Require. После сохранения файла проверьте доступ к /wp-admin с разрешённого IP и с другого адреса (например, через мобильный интернет) - убедитесь, что блокировки работают именно так, как задумано.

Как закрыть wp-admin в nginx

В nginx логика блокировки отличается от Apache: здесь нет .htaccess, все правила прописываются в конфигурационном файле сервера - обычно в блоке server внутри /etc/nginx/sites-available/your-site.conf.

Базовый location-блок для закрытия wp-admin по IP выглядит так:

location ~ ^/wp-admin {
 allow 95.142.45.10;
 deny all;
}

location = /wp-login.php {
 allow 95.142.45.10;
 deny all;
}

Здесь важен порядок директив: nginx проверяет allow/deny сверху вниз и применяет первое совпадение. Если ваш IP стоит перед deny all - вы пройдёте, все остальные получат 403.

Критический нюанс, который ломает сайты: нельзя блокировать admin-ajax.php. Этот файл находится в папке wp-admin, но используется для AJAX-запросов на фронтенде - формы, корзина WooCommerce, динамические блоки. Если применить block access ко всей папке без исключения, плагины начнут молча ломаться. Правильный вариант:

location = /wp-admin/admin-ajax.php {
 allow all;
}

location ~ ^/wp-admin {
 allow 95.142.45.10;
 deny all;
}

location = /wp-login.php {
 allow 95.142.45.10;
 deny all;
}

Блок с admin-ajax.php должен стоять выше общего правила для wp-admin - иначе общее правило перехватит запрос раньше. После правок не забудьте сделать nginx -t для проверки синтаксиса и systemctl reload nginx для применения изменений.

Если у вас динамический IP - добавьте несколько адресов через отдельные строки allow, либо используйте вместо IP-блокировки метод с HTTP-аутентификацией, о котором расскажу ниже.

Как ограничить доступ через PHP в functions.php

Если у вас нет доступа к конфигурации сервера - shared-хостинг без SSH, панель управления без редактора nginx - можно сделать блокировки на уровне WordPress через хук init. Это не так надёжно, как серверные методы, но лучше, чем ничего.

Базовый сниппет выглядит так:

add_action( 'init', function() {
 if ( is_admin() && ! current_user_can( 'manage_options' ) ) {
 wp_die( 'Доступ запрещён', 403 );
 }
});

Разберём построчно: add_action( 'init', ... ) запускает функцию на каждый запрос после загрузки WordPress. is_admin() проверяет, что запрос идёт в зону /wp-admin. current_user_can( 'manage_options' ) - проверка роли: только администраторы пройдут дальше. Остальные получат экран с ошибкой.

Теперь про проблему, на которую я наступал сам: наивная реализация ломает выход из системы. Когда пользователь кликает «Выйти», WordPress обрабатывает запрос через wp-login.php?action=logout, но промежуточный редирект может проходить через зону is_admin() - и сниппет его обрежет. Пользователь зависнет в сессии. Правильный вариант с защитой от этого:

add_action( 'init', function() {
 if ( is_admin()
 && ! current_user_can( 'manage_options' )
 && ! wp_doing_ajax()
 && ! ( isset( $_GET['action'] ) && $_GET['action'] === 'logout' )
 ) {
 wp_die( 'Доступ запрещён', 403 );
 }
});

Функция wp_doing_ajax() исключает AJAX-запросы - без этого комментарий к записи через форму на фронтенде может не отправиться. Проверка action=logout сохраняет работоспособность выхода из системы.

Механизм простой: exit add action - хук 'init' срабатывает до отрисовки страницы, wp_die() завершает скрипт с кодом 403. Куда вставлять: в functions.php вашей темы или, лучше, в отдельный плагин-сниппет (например, через Code Snippets). Редактировать functions.php напрямую рискованно - одна синтаксическая ошибка в PHP закроет весь сайт.

Дополнительный рубеж: HTTP-аутентификация для wp-admin

HTTP Basic Auth - это второй пароль на уровне сервера, до того как WordPress вообще загрузится. Браузер показывает системное окно с запросом логина и пароля - боты его не проходят, потому что не умеют с ним взаимодействовать. Этот метод особенно полезен, когда у вас динамический IP и белый список адресов не подходит.

Шаг 1. Создайте файл .htpasswd с хешированным паролем. Проще всего через утилиту htpasswd:

htpasswd -c /etc/nginx/.htpasswd andrey

Или используйте онлайн-генератор - он выдаст строку вида andrey:$apr1$xyz.... Файл нельзя класть в корень сайта - только за пределами webroot или в место, недоступное напрямую через браузер.

Шаг 2. Для Apache - пропишите в .htaccess папки wp-admin:

AuthType Basic
AuthName "Admin Area"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user

Для nginx - добавьте в location-блок:

location ~ ^/wp-admin {
 auth_basic "Admin Area";
 auth_basic_user_file /etc/nginx/.htpasswd;
 allow all;
}

И снова тот же нюанс про admin-ajax.php: его нужно исключить из BasicAuth, иначе AJAX-запросы плагинов будут падать с 401. Добавьте отдельный location выше с auth_basic off.

Из практики студии: на одном проекте мы комбинировали IP-ограничение с BasicAuth - сначала allow from для офисного IP, а для работы с телефона (динамический адрес) - пароль. Это дало гибкость без потери безопасности.

Сравнение трёх методов защиты wp-admin:

Метод Сложность настройки Зависимость от IP AJAX-совместимость Надёжность
.htaccess + IP (Apache) Низкая Да - нужен статический IP Требует исключения admin-ajax.php Высокая
nginx location + IP Средняя Да - нужен статический IP Требует отдельного location Высокая
HTTP Basic Auth (.htpasswd) Средняя Нет - работает с любым IP Требует исключения admin-ajax.php Очень высокая

Самая частая ошибка при deny from / allow from - забыть про admin-ajax.php. Я видел, как после таких блокировок переставали работать формы обратной связи, слайдеры и целые страницы оформления заказа - и клиент несколько часов не понимал, что причина в защите wp-admin.

Типичные ошибки и что делать дальше

За годы практики вижу три ошибки, которые повторяются чаще всего.

  • Динамический IP. Закрыли доступ по IP - утром провайдер выдал новый адрес, и вы сами оказались за бортом. Решение: используйте статический IP или заранее добавьте резервный доступ через VPN с фиксированным адресом.
  • Забыли admin-ajax.php. Плагины, формы, публичную часть сайта - всё, что работает через AJAX, сломается, если заблокировать весь каталог wp-admin без исключения. Обязательно добавляйте правило, разрешающее запросы к admin-ajax.php для всех.
  • Синтаксис .htaccess. Одна лишняя буква - и сайт падает с ошибкой 500. Не паникуйте: зайдите через FTP или файловый менеджер cPanel, откройте .htaccess и удалите последний блок правил. Сайт поднимется за секунды. Перед любой правкой делайте резервную копию файла.

По выбору метода: если есть статический IP - блокировка на уровне .htaccess - самый надёжный вариант. Нет статического IP или работаете с разных мест - установите плагин с белым списком и включите двухфакторную аутентификацию (2FA, например через WP 2FA или Google Authenticator for WP). Для большинства небольших сайтов связка из смены URL входа и 2FA закрывает 95% атак без танцев с настройкой сервера.

Комментарий напоследок: ни один из этих методов не заменяет регулярные обновления WordPress и плагинов. Защита входа - первый рубеж, но не единственный.

Эта статья основана на личном опыте автора и актуальна на момент публикации. Интерфейсы сервисов и алгоритмы поисковых систем регулярно меняются - рекомендую проверять актуальность инструкций на официальных ресурсах. Если у вас остались вопросы - задайте их в комментариях.

Список литературы

  1. WordPress Documentation Team - Hardening WordPress // Developer.WordPress.org (Advanced Administration Handbook)
  2. Nginx, Inc. - Module ngx_http_access_module // nginx.org (официальная документация)
  3. Apache Software Foundation - Access Control. Apache HTTP Server Version 2.4 // httpd.apache.org, 2024
  4. Команда offlineCRM - Взламывают сайты после выхода статей. Пишем подробно, как защитить ваш сайт на WordPress // Habr, 2022
Поделитесь Вашим мнением
Ваш комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *


Еще записи из этой же рубрики

Что будем искать? Например,Хостинг

Минуту внимания
Мы используем файлы cookies, чтобы обеспечивать правильную работу нашего веб-сайта, а также работу функций социальных сетей и анализа сетевого трафика.