Я потерял клиентский сервер один раз — этого хватило, чтобы раз и навсегда сделать 2FA обязательным на всех проектах, которые я веду. Не буду рассказывать подробности, но скажем так: брутфорс SSH в 4 утра — это не то, о чём хочется читать в уведомлениях.
Почему 2FA — это не паранойя, а минимум разумной безопасности
Честно говоря, я долго сам откладывал настройку двухфакторки на серверах. Казалось — SSH-ключи есть, пароль сложный, fail2ban крутится. Ну куда ещё? Но на деле это не защищает от целого класса атак: украденные ключи, компрометация рабочего ноутбука, человеческий фактор при работе с несколькими девелоперами в команде.
По статистике Verizon Data Breach Report за 2024 год, более 80% успешных взломов связаны с компрометацией учётных данных. Пароли утекают с других сервисов, SSH-ключи копируются на личные машины разработчиков, а потом эти машины продаются или теряются. 2FA закрывает эту дыру радикально: даже если злоумышленник получил ваш ключ или пароль, без второго фактора он не зайдёт.
Если вы ещё не читали мою статью про настройку SSH-ключей для сервера — сделайте это до того, как настраивать 2FA. Ключи и двухфакторка работают в связке, и начинать надо именно с ключей.
Инструменты для 2FA на SSH: что выбрать
Для SSH-сервера на Linux самый распространённый вариант — это Google Authenticator PAM-модуль. Он работает с любым TOTP-приложением: Google Authenticator, Authy, 1Password, Bitwarden. Я обычно рекомендую клиентам Authy или 1Password — у них есть облачный бэкап кодов, что спасает при смене телефона.
Есть ещё альтернативы: YubiKey (аппаратный токен), FIDO2/WebAuthn, Duo Security (платный, но удобный для команд). Но grubо говоря, для большинства проектов Google Authenticator PAM — это оптимальное соотношение простоты и надёжности. Ставится за 10 минут, работает без внешних сервисов, бесплатно.
Важный момент: всё это работает на Ubuntu 20.04/22.04/24.04, Debian 11/12, CentOS Stream 9. На старых CentOS 7 тоже работает, но я бы настоятельно рекомендовал сначала обновить систему — поддержка CentOS 7 закончилась ещё в 2024 году.
Настройка Google Authenticator PAM на SSH: пошагово
Начнём с установки. На Ubuntu/Debian это делается одной командой:
sudo apt update
sudo apt install libpam-google-authenticator -y
После установки нужно запустить настройку для каждого пользователя, которому нужен 2FA. Запускайте именно от того пользователя, для которого настраиваете:
google-authenticator
Утилита задаст несколько вопросов. Я обычно отвечаю так: time-based tokens — yes, обновление ~/.google_authenticator — yes, запрет повторного использования токенов — yes, 30-секундное окно — можно yes для надёжности, rate limiting — yes. После этого в терминале появится QR-код и аварийные коды восстановления. QR-код сканируете в Authy или Google Authenticator, коды восстановления — сохраните в менеджер паролей. Это критически важно.
Теперь нужно настроить PAM. Открываем файл:
sudo nano /etc/pam.d/sshd
И добавляем в начало файла (до других строк auth):
auth required pam_google_authenticator.so
Если хотите, чтобы 2FA запрашивался только у пользователей, которые его настроили (а не блокировал остальных), используйте:
auth required pam_google_authenticator.so nullok
Опция nullok позволяет входить без 2FA тем пользователям, у которых нет файла ~/.google_authenticator. На период миграции команды это удобно — можно добавлять 2FA постепенно.
Следующий шаг — настройка самого SSH-демона. Открываем:
sudo nano /etc/ssh/sshd_config
Нужно установить или изменить следующие параметры:
ChallengeResponseAuthentication yes
UsePAM yes
AuthenticationMethods publickey,keyboard-interactive
Строка AuthenticationMethods publickey,keyboard-interactive — это ключевая настройка. Она требует и SSH-ключ, и второй фактор (TOTP-код). Именно так должна выглядеть нормальная защита: что-то, что у вас есть (ключ) + что-то, что вы знаете/имеете (одноразовый код). Если хотите только TOTP без ключей — уберите publickey,, но я бы так не делал.
На Ubuntu 22.04 и новее параметр называется иначе, проверьте:
KbdInteractiveAuthentication yes
Перезапускаем SSH:
sudo systemctl restart sshd
И тестируем в новой вкладке терминала. При подключении сначала используется ключ, потом SSH спросит Verification code — вводите код из приложения.
2FA для панелей управления: ISPmanager, Plesk, cPanel
С панелями управления ситуация проще — у большинства из них 2FA встроен или подключается через плагин. Но дьявол, как всегда, в деталях.
ISPmanager 6
В ISPmanager 6 двухфакторная аутентификация включается прямо в настройках профиля. Заходите в панель под рутом, идёте в раздел «Настройки» → «Двухфакторная аутентификация», включаете и сканируете QR-код. Всё. Но есть нюанс: 2FA в ISPmanager работает только для веб-интерфейса, не для API-доступа. Если у вас настроены автоматические API-запросы — они продолжат работать по токену.
У меня был клиент с ISPmanager 5 (старая версия), где встроенного 2FA не было вообще. Пришлось закрывать веб-интерфейс панели по IP через iptables и настраивать VPN как второй фактор доступа. Грубо говоря, без VPN ты просто не видишь порт панели. Это тоже рабочее решение, хотя и менее удобное.
Plesk Obsidian
В Plesk 2FA настраивается через Extensions → Google Authenticator. Устанавливаете расширение, включаете для нужных пользователей. Plesk поддерживает как TOTP, так и SMS (через Twilio, но это платно и я бы не рекомендовал — SMS небезопасны). TOTP — однозначно лучший вариант.
Важный момент для Plesk: если вы администрируете несколько клиентских аккаунтов, 2FA можно сделать обязательным для всех пользователей через политику безопасности. Это особенно актуально, если вы предоставляете поддержку Битрикс-сайтов и клиенты имеют доступ к панели.
cPanel/WHM
В cPanel 2FA включается в Security Center → Two-Factor Authentication. Там же можно принудительно включить 2FA для всех аккаунтов на сервере — через WHM → Manage Two-Factor Authentication. Работает с любым TOTP-приложением.
Одна вещь, которую я всегда делаю при настройке cPanel: включаю 2FA не только для WHM (root-доступ), но и для самого cPanel-аккаунта клиента. Потому что взлом клиентского аккаунта через cPanel — это тоже очень неприятная история.
2FA для административных панелей CMS: WordPress и Битрикс
Настройка 2FA на уровне сервера — это хорошо. Но если у вас WordPress или Битрикс, злоумышленник может попытаться войти через /wp-admin или /bitrix/admin, минуя SSH вообще. Поэтому 2FA нужен и на уровне CMS.
WordPress
Для WordPress я использую плагин WP 2FA — он простой, активно поддерживается, работает с TOTP и email-кодами. Устанавливаете, активируете, в настройках выбираете TOTP как основной метод, можно принудительно включить для всех пользователей с ролью Administrator и Editor.
Альтернатива — Wordfence Login Security. Если у вас уже стоит Wordfence (а он должен стоять), то 2FA уже включён в пакете. Активируете в разделе Login Security → Two-Factor Authentication. Работает хорошо, я использую его на нескольких проектах.
Про защиту wp-admin в целом я писал подробно — читайте статью про защиту wp-admin, там много дополнительных мер помимо 2FA.
Битрикс
В Битрикс 24 и Битрикс CMS двухфакторная аутентификация настраивается через Настройки → Настройки продукта → Безопасность → Двухфакторная аутентификация. Там можно включить TOTP, выбрать обязательность для администраторов, настроить период доверия устройства (чтобы не вводить код каждый раз на рабочем компьютере).
На деле Битрикс поддерживает 2FA начиная с версии 20.x. Если у вас старее — обновитесь. Подробнее про обновление — в статье как обновить Битрикс без потери данных.
Настройка fail2ban в комбинации с 2FA
2FA хорошо защищает от входа, но не от попыток. Если кто-то долбится в ваш SSH с тысячей попыток в час — это нагрузка на сервер и шум в логах. fail2ban в связке с 2FA закрывает и эту проблему.
Установка на Ubuntu:
sudo apt install fail2ban -y
Создаём локальный конфиг (не редактируем jail.conf напрямую — он перезаписывается при обновлении):
sudo nano /etc/fail2ban/jail.local
Минимальная конфигурация для SSH:
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 86400
Здесь я выставляю maxretry = 3 и bantime = 86400 (24 часа). Три попытки — и IP банится на сутки. С 2FA это означает, что даже если у атакующего есть пароль, три неверных TOTP-кода — и он заблокирован. Грубо говоря, окно для атаки закрывается полностью.
Перезапускаем:
sudo systemctl enable fail2ban
sudo systemctl restart fail2ban
Проверяем статус:
sudo fail2ban-client status sshd
Дополнительный слой: 2FA через nginx для закрытых разделов
Иногда нужно защитить не весь сервер, а конкретный URL — например, /admin/, /bitrix/admin, staging-сервер. Здесь помогает комбинация nginx Basic Auth + IP-ограничения + 2FA на уровне приложения.
Базовая настройка nginx Basic Auth для закрытого раздела:
location /admin/ {
# Ограничение по IP (офис + VPN)
allow 192.168.1.0/24;
allow 10.0.0.0/8;
deny all;
# Basic Auth как дополнительный слой
auth_basic "Restricted Area";
auth_basic_user_file /etc/nginx/.htpasswd;
# Передаём запрос на приложение
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
Создать .htpasswd можно так:
sudo apt install apache2-utils -y
sudo htpasswd -c /etc/nginx/.htpasswd admin_user
Это не заменяет 2FA в приложении, но добавляет ещё один барьер. Злоумышленник должен знать IP (или обойти ограничение), знать логин/пароль для Basic Auth, и иметь учётные данные от самого приложения с TOTP-кодом. Три слоя — это уже серьёзно.
По теме закрытия доступа по IP у меня есть отдельная подробная статья: ограничение доступа по IP на сайте — там рассмотрены все варианты для nginx, Apache и на уровне iptables.
Организация 2FA в команде: как не сойти с ума
Когда у вас один разработчик — всё просто. Но когда команда из 5-10 человек, каждый со своим телефоном и своими TOTP-приложениями, начинается головная боль. Я через это прошёл.
Первое правило: каждый настраивает 2FA сам для своего пользователя. Никакого "я настрою за тебя" — это убивает смысл второго фактора. У каждого разработчика должен быть отдельный системный пользователь на сервере, не все под одним root или deploy.
Второе: коды восстановления — это ответственность каждого. Я прописываю это в регламент онбординга. При увольнении разработчика — удаляем его пользователя с сервера, не отзываем коды (их просто нет смысла отзывать, аккаунт удалён).
Третье: для команды удобнее использовать Duo Security или похожие корпоративные решения. Там есть централизованное управление — можно принудительно включать 2FA, видеть кто и когда логинился, сбрасывать 2FA для пользователя без доступа к его телефону. Стоит Duo от $3/пользователь в месяц — для команды из 5 человек это $15/мес, что абсолютно оправдано.
Четвёртое: сервисные аккаунты (для деплоя, CI/CD, мониторинга) — 2FA для них не нужен и не подходит. Для автоматизированных подключений используйте выделенные SSH-ключи с ограниченными правами и ограничением по IP. Никогда не используйте рутовые ключи для CI/CD — это плохая идея, которую я видел слишком часто.
Проверка и аудит настроек 2FA
После настройки нужно убедиться, что всё работает как задумано, и что нет обходных путей. Я прохожу по такому чеклисту:
Проверяю, что прямой вход по паролю без ключа и без TOTP невозможен:
# На локальной машине, проверяем что вход по паролю закрыт
ssh -o PreferredAuthentications=password user@server
Это должно вернуть ошибку. Если нет — проверьте PasswordAuthentication no в sshd_config.
Проверяю логи аутентификации:
sudo tail -f /var/log/auth.log | grep sshd
При успешном входе с 2FA там должны быть записи с упоминанием keyboard-interactive и publickey. Если вход происходит только по ключу без запроса TOTP — что-то настроено неправильно.
Раз в квартал я рекомендую проводить полный аудит доступов: кто имеет SSH-доступ, у кого настроен 2FA, нет ли лишних authorized_keys. Это занимает час, но даёт спокойствие. Если вы пользуетесь поддержкой WordPress или другими managed-сервисами, уточните у подрядчика, как организован их доступ к вашему серверу — это ваше право знать.
Частые ошибки при настройке 2FA: что идёт не так
За несколько лет настройки 2FA на разных серверах я собрал коллекцию типичных проблем.
Расхождение времени на сервере. TOTP-коды зависят от точного времени. Если на сервере время расходится с реальным больше чем на 30 секунд — коды будут невалидны. Проверяйте:
timedatectl status
# Должно показать synchronized: yes
# Если нет — синхронизируем
sudo apt install ntp -y
sudo systemctl enable ntp
sudo systemctl start ntp
Неправильный порядок в PAM. Если строка с google_authenticator стоит после других auth-правил — поведение может быть непредсказуемым. Ставьте её первой или второй, чётко понимая порядок.
Забытый nullok при поэтапном внедрении. Если убрать nullok до того, как все пользователи настроили 2FA — те, у кого нет ~/.google_authenticator, не смогут войти. Я видел, как из-за этого команда теряла доступ к продакшн-серверу в пятницу вечером.
2FA только для одного пользователя, root без 2FA. Иногда настраивают 2FA для deploy-пользователя, но root оставляют без него. Это дыра. Либо закрывайте root-логин полностью (PermitRootLogin no), либо настраивайте 2FA и для него.
По теме комплексной защиты сервера и сайта — обязательно прочитайте статью как защитить сайт от взлома. 2FA — это важная часть, но далеко не единственная мера.
И последнее: если вам нужна помощь с настройкой 2FA, аудитом безопасности сервера или комплексной доработкой сайта — я занимаюсь этим в рамках технической поддержки. Настройка 2FA на сервере с нуля занимает обычно 1-2 часа, включая тестирование и документирование. Лучше потратить эти два часа сейчас, чем потом разгребать последствия взлома.
Хотите надёжно защитить доступ к вашему серверу?
Наши специалисты помогут настроить двухфакторную аутентификацию и обеспечить максимальную безопасность вашей инфраструктуры.