Безопасность сайта

Как ограничить число попыток входа в админку и заблокировать ботов

Rate-limit на /wp-login.php, защита от brute-force в Битриксе и OpenCart, fail2ban и базовые правила .htaccess. Боты больше не достают.

обновлено 7 минут чтения 4 Дмитрий Акиндинов
Содержание
  1. Что такое brute-force и почему этого надо бояться
  2. Rate-limit на уровне CMS
  3. Защита на уровне веб-сервера
  4. Скрытие самой формы входа
  5. Защита API XML-RPC
  6. Геоблокировка
  7. Двухфакторка как страховка
  8. Чек-лист на любой сайт
  9. Что почитать дальше
  10. Частые вопросы

На типовом маленьком сайте идёт 50-500 попыток входа в сутки. Ограничение числа попыток блокирует адрес после нескольких неудач, а закрытие служебного API убирает второй канал перебора. Вместе это снимает около 95 процентов автоматического мусора.

Если вы хоть раз заглядывали в логи доступа сайта на WordPress или Битрикс, вы видели монотонные строки попыток входа в /wp-login.php, /bitrix/admin/, /admin.php. На типичном маленьком сайте таких попыток 50-500 в сутки. Большинство отваливается на длинном пароле, но ботам всё равно: они перебирают часами, нагружают CPU, заполняют логи, иногда всё-таки попадают в учётку с переиспользованным паролем.

Решение очевидное и копеечное: ограничить число попыток входа с одного IP. После 3-5 неудач IP блокируется на час или сутки, и бот идёт играть на чужом сайте. Ниже разложу, как это ставится на разные CMS и на уровне сервера, без шаманства и платных плагинов.

Счётчик попыток входа на форме авторизации

Что такое brute-force и почему этого надо бояться

Brute-force это перебор паролей в надежде угадать. Бот берёт ваш логин (часто из самого сайта, со страницы автора или из RSS), и подставляет к нему пароли из словаря. Современные словари это 100 миллионов вариантов, отсортированных по популярности.

Если у вас пароль из топ-1000, его подберут за минуту. Из топ-100 000 за пару часов. Если пароль 12 случайных символов, не подберут никогда (см. соседний материал про безопасные пароли). Но даже непробиваемый пароль не отменяет вреда от brute-force: 500 запросов в час на slow-shared-хостинге это медленно отдающаяся главная для реальных посетителей.

Поэтому защищаются не только сильным паролем, но и ограничением попыток.

Rate-limit на уровне CMS

WordPress

Готовых решений много, я ставлю одно из этих.

Limit Login Attempts Reloaded. Бесплатный плагин, ставится в один клик. После N неудачных попыток (по умолчанию 4) IP блокируется на 20 минут, после повторных блокировок на сутки. Логирует попытки в админке.

Настройки, которые я меняю от дефолта:

  • Allowed retries: 3 (вместо 4)
  • Minutes lockout: 60 (вместо 20)
  • Lockouts increase lockout time to: 24 часа после 3-й блокировки
  • Reset retries every: 12 часов

WPS Hide Login. Перенесёт /wp-login.php на другой адрес типа /secret-vhod-77/. Любой бот, тыкающий стандартный URL, получает 404. Это не криптозащита, это шумоподавление: 95 процентов автоматических ботов уходят без попытки. Ставлю в паре с Limit Login Attempts.

После установки обязательно: записать новый URL в менеджер паролей. Я раз потерял сайт сам у себя на 20 минут, потому что забыл, что там за URL.

Wordfence. Большой комбайн. Может всё, включая блокировку по странам и IP-репутации. Ставлю на критичных проектах. Минус: нагружает базу и тормозит сайт на 50-100 мс. На простом сайте Limit Login Attempts достаточно.

Битрикс

В Битриксе встроенный rate-limit живёт в Проактивной защите. Включаю в настройках:

  • Защита авторизации: вкл.
  • Защита от перебора паролей: вкл.
  • Перенаправление при ошибке: страница ошибки.
  • Блокировать пользователя после: 5 неудачных попыток.
  • На срок: 60 минут.

Дополнительно Битрикс проверяет аномальные действия в админке: подозрительные IP, рваное поведение в одной сессии, попытки доступа к чужим разделам.

Для крупного интернет-магазина я добавляю ещё и rate-limit на уровне Apache (см. ниже).

OpenCart

Из коробки OpenCart 4.x умеет ограничивать число попыток входа в настройках администратора: «Системные / Безопасность / Допустимое количество попыток входа». Ставлю 3 с блокировкой на час.

Дополнительно полезен модуль AntiBruteForce или встроенная функция Multi-Store IP Whitelist, которая разрешает доступ в админку только с конкретных IP.

MODX, Joomla, прочие

В большинстве движков либо есть штатный rate-limit, либо плагин на пару кликов. Если ничего нет, защищаемся на уровне веб-сервера.

Защита на уровне веб-сервера

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

.htaccess: блокировка повторных POST-запросов

Простейший вариант на shared-хостинге. В .htaccess в корне сайта или прямо в /wp-admin/:

<RequireAll>
    Require all granted
    <RequireNone>
        Require ip 1.2.3.4
        Require ip 5.6.7.8/24
    </RequireNone>
</RequireAll>

Это блочный список (или белый, если поменять логику) для конкретных IP. Подходит, когда вы знаете, с каких IP к вам ходят боты.

Динамический rate-limit прямо в .htaccess не делается. Для этого нужен или модуль mod_evasive, или движок CMS, или серверный fail2ban.

mod_evasive на VPS

Если у вас VPS, и есть root-доступ, ставится за 5 минут:

apt-get install libapache2-mod-evasive
mkdir -p /var/log/mod_evasive
chown www-data:www-data /var/log/mod_evasive

Конфигурация в /etc/apache2/mods-enabled/evasive.conf:

<IfModule mod_evasive20.c>
    DOSHashTableSize    3097
    DOSPageCount        4
    DOSSiteCount        50
    DOSPageInterval     1
    DOSSiteInterval     1
    DOSBlockingPeriod   600
    DOSEmailNotify      admin@saitfix.ru
    DOSLogDir           /var/log/mod_evasive
</IfModule>

Это правило: если один IP делает больше 4 запросов на одну страницу за 1 секунду, блокируем на 10 минут. Если больше 50 запросов на разные страницы за 1 секунду, тоже блокируем.

Брутфорсу /wp-login.php обычно нужно 30-100 попыток в секунду. mod_evasive режет такого бота на 5-й попытке.

fail2ban

Самый универсальный инструмент для VPS. Парсит логи, ловит паттерны, блокирует IP через iptables.

Ставится одной строкой:

apt-get install fail2ban

Настраивается через jail-файлы. Пример для WordPress:

[wordpress-auth]
enabled = true
filter = wordpress-auth
logpath = /var/log/apache2/saitfix.ru-access.log
maxretry = 5
findtime = 600
bantime = 3600
action = iptables-multiport[name=wordpress, port="http,https"]

С фильтром в /etc/fail2ban/filter.d/wordpress-auth.conf:

[Definition]
failregex = ^<HOST>.*"POST /wp-login.php.*" 200
ignoreregex =

Это блокирует на час любой IP, который сделал больше 5 POST-запросов на /wp-login.php за 10 минут. Фильтр срабатывает на response 200, потому что неуспешная попытка возвращает 200 со страницей авторизации.

После установки проверяю работу:

fail2ban-client status wordpress-auth

Видно текущих заблокированных и счётчик за последний час.

Капитан-стражник останавливает идентичных роботов в очереди

Скрытие самой формы входа

Лучший способ не быть забрутфорсенным это не светить логин-страницу.

Перенос URL. WordPress на /secret-vhod-2026/, Битрикс на /manager/, OpenCart на /staff/. Это не криптозащита, но 95 процентов автоматических ботов перестают ходить.

Закрытие админки от внешнего мира. Если вы заходите в админку только из дома и из офиса, ограничиваем доступ к /wp-admin/ или /bitrix/admin/ парой IP. Всё, никто кроме вас не зайдёт.

В .htaccess:

<Files "wp-login.php">
    Require ip 1.2.3.4
    Require ip 5.6.7.8
</Files>

Минус: если меняется IP (вы уехали в командировку, у провайдера ротируется адрес), вход запрещён и вам.

Базовая HTTP-авторизация поверх формы CMS. Двойная авторизация: сначала окно браузера с логином и паролем, потом сама форма WordPress. Это лучшая защита для непубличной админки.

В .htaccess:

<Files "wp-login.php">
    AuthType Basic
    AuthName "Restricted"
    AuthUserFile /home/user/.htpasswd
    Require valid-user
</Files>

Файл .htpasswd создаётся командой htpasswd -c /home/user/.htpasswd admin (вне webroot, иначе кто-то скачает).

Бот, увидев 401 Unauthorized на /wp-login.php, обычно сдаётся: 99 процентов ботов не проходят даже первый слой.

Защита API XML-RPC

Отдельная история для WordPress. Файл /xmlrpc.php это альтернативный канал авторизации, через который тоже идёт brute-force. Иногда даже сильнее, чем через /wp-login.php.

Если вы не используете мобильное приложение WordPress и не работаете с пингбэками с других сайтов, выключайте xmlrpc целиком.

В .htaccess:

<Files "xmlrpc.php">
    Require all denied
</Files>

После этого попытки на /xmlrpc.php получают 403, бот уходит.

Геоблокировка

Если ваш сайт работает только на Россию, и боты идут в основном из других стран, блокируем целые ASN или диапазоны IP.

В .htaccess через mod_geoip (если хостер ставил):

<RequireAll>
    Require all granted
    Require not env GEOIP_COUNTRY_CODE CN
    Require not env GEOIP_COUNTRY_CODE PH
    Require not env GEOIP_COUNTRY_CODE PK
</RequireAll>

Минус: туристы, командированные сотрудники и пользователи VPN сразу не зайдут. Ставлю только на админку, не на весь сайт.

Через сервис вроде Cloudflare блокировка по странам делается в один клик, но Cloudflare в России работает нестабильно.

Двухфакторка как страховка

Все приёмы выше отсекают ботов. Но если бот всё-таки прошёл, или если ваш пароль утёк целиком, спасает двухфакторная аутентификация. Без второго фактора, даже зная пароль, в админку никто не войдёт.

2FA это последняя линия. Rate-limit это первая. Между ними ещё пара слоёв (длинный пароль, скрытие URL, блокировка xmlrpc). Ни один слой по отдельности не идеален, вместе они дают многократный фильтр.

IP-карта с тремя крестами и часами блокировки

Чек-лист на любой сайт

Что я ставлю в первый день работы с новым клиентом:

  1. Длинный случайный пароль в админке (16 символов, см. отдельную статью).
  2. Сменить логин администратора с admin на что-то нейтральное.
  3. Установить плагин ограничения попыток входа (Limit Login Attempts Reloaded для WP, проактивная защита для Битрикса).
  4. Перенести URL входа на нестандартный.
  5. Закрыть xmlrpc.php через .htaccess.
  6. Поставить базовую HTTP-авторизацию на админку, если вход редкий.
  7. Включить 2FA для всех учёток.
  8. Настроить fail2ban на VPS, если есть root.
  9. Завести алерт на 50 неудачных попыток входа за час, чтобы заметить волну.
  10. Раз в месяц смотреть логи и блокировать особо настойчивых.

Этот пакет занимает один час на старте и потом сам работает годами.

Что почитать дальше

Связанные материалы: Файл .htaccess против ботов и парсеров, DDoS на маленький сайт без Cloudflare, Двухфакторная аутентификация для админки.

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

Частые вопросы

Как ограничить число попыток входа

Плагином или правилом на уровне веб-сервера: после трёх-пяти неудачных попыток адрес блокируется на 15-60 минут. Счётчик сбрасывается через несколько часов.

Что ещё перебирают кроме формы входа

Служебный API удалённого доступа. Через него подбирают пароли пачками и без ограничения по частоте. Если он не используется, его закрывают целиком.

Не заблокирую ли я сам себя

Такое бывает. Поэтому сразу добавьте свой адрес в исключения и держите запасной путь: доступ по FTP или к базе, чтобы снять блокировку вручную.

Нужна ли к этому двухфакторка

Ограничение попыток снижает шум, второй фактор закрывает сам вход. Одно без другого работает, вместе надёжнее: даже подобранный пароль без кода не пустит.

Передайте техническую часть в надёжные руки.

Слежу за хостингом, бэкапами и обновлениями. Когда что-то пойдёт не так – звоните мне, не своему программисту, не в спортзал и не маме.

Короткие вопросы по теме

Все вопросы по теме "Безопасность сайта"

Заявка

Обсудим задачу

Напишите имя и телефон, выберите удобный канал. Перезвоню или напишу в течение часа в рабочее время.

Куда удобнее ответить?