MAATRIX / Блог / Двухфакторная аутентификация для VPN-подключения (TOTP + сертификат)

Двухфакторная аутентификация для VPN-подключения (TOTP + сертификат)

MAATRIX

Сертификат клиента подтверждает, что подключается устройство, которому вы когда-то выдали ключ — но не то, что за этим устройством по-прежнему сидите вы. Ноутбук украли, флешку с ключом скопировали, конфиг переслали «на всякий случай» коллеге — и сертификат продолжает исправно пускать в туннель кого угодно. Второй фактор поверх самого VPN-подключения (а не только поверх панели, где вы им управляете) закрывает именно этот сценарий: даже с валидным сертификатом или паролем в руках атакующий не пройдёт дальше без кода из приложения на вашем телефоне.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Почему сертификата или пароля недостаточно для самого VPN

Три независимых способа авторизации в VPN — и у каждого своя дыра, если он используется в одиночку:

  • Сертификат клиента. Файл .ovpn или .p12 — это просто файл. Он копируется, пересылается по почте, остаётся в бэкапе старого ноутбука, попадает в утёкший архив с рабочего стола. Отозвать его (через CRL) вы сможете только после того, как заметите проблему — а до этого момента он рабочий.
  • Логин и пароль. Та же история, что и с любым паролем: повторное использование на других сервисах, фишинг, кейлоггер на заражённой машине. Пароль от VPN часто проще угадать или перебрать, чем пароль от почты — про него реже вспоминают при генерации.
  • IP-ограничения и allowlist. Работают только для статичных офисов; для удалённых и мобильных подключений бесполезны, потому что IP меняется постоянно.

TOTP-код, который живёт 30 секунд и генерируется локально на телефоне, не устраняет ни одну из этих проблем сам по себе — он делает кражу одного фактора недостаточной для входа. Утёкший сертификат или подсмотренный пароль без физического доступа к разблокированному телефону владельца бесполезны.

Отдельно: если вы уже читали про двухфакторную аутентификацию для панели управления сервером — это другая задача. Там закрывается вход в личный кабинет или в ispmanager/cPanel, откуда вы администрируете сервер. Здесь речь о самом VPN-туннеле: втором факторе, который проверяется в момент установки соединения, до того как трафик вообще пошёл через сервер.

Как PAM встраивает TOTP в процесс подключения

OpenVPN и strongSwan (IKEv2) сами по себе не умеют проверять одноразовые коды — но оба умеют делегировать проверку пароля модулю PAM (Pluggable Authentication Modules), стандартной подсистеме Linux для аутентификации. Google Authenticator поставляет свой PAM-модуль pam_google_authenticator.so, который проверяет TOTP-код по секрету, привязанному к системному пользователю. Схема одинакова для обоих протоколов:

  1. Клиент подключается и, помимо сертификата (если он требуется), отправляет строку логин/пароль.
  2. VPN-демон вызывает PAM-стек вместо (или в дополнение к) своей встроенной проверки.
  3. PAM-стек прогоняет введённые данные через цепочку модулей: сначала проверяется TOTP-код, затем — обычный системный пароль пользователя.
  4. Только если оба фактора прошли проверку, PAM возвращает «успех», и VPN-демон устанавливает туннель.

Технический нюанс, из-за которого многие спотыкаются на первой попытке: у OpenVPN и IKEv2 в диалоге логина только одно поле «пароль», а факторов два. Стандартный обходной путь — пользователь вводит пароль, сразу за которым без пробела следует 6-значный код (например, пароль S3cr3t! и код 482913 превращаются в S3cr3t!482913). Модуль pam_google_authenticator.so с опцией forward_pass отрезает последние 6 цифр, проверяет их как OTP, а остаток строки передаёт следующему модулю в цепочке как обычный пароль.

Арендуйте сервер под свои задачи!

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

OpenVPN + Google Authenticator: пошаговая настройка PAM

Ставится поверх уже работающего OpenVPN-сервера с сертификатной авторизацией (см. установку OpenVPN на VPS, если сервера ещё нет).

1. Установите PAM-модуль и сгенерируйте секрет для пользователя.

apt update && apt install libpam-google-authenticator
# от имени системного пользователя, для которого включаем TOTP
su - vpnuser
google-authenticator

Утилита google-authenticator задаст несколько вопросов (time-based токены — да, окно допуска по времени — оставить по умолчанию) и покажет QR-код прямо в терминале плюс текстовый секрет и 5 резервных кодов на случай потери телефона. Отсканируйте QR любым TOTP-приложением (Google Authenticator, Aegis, Authy).

2. Настройте PAM-стек для OpenVPN. Создайте /etc/pam.d/openvpn:

auth requisite pam_google_authenticator.so forward_pass
auth required pam_unix.so use_first_pass
account required pam_permit.so

Порядок важен: pam_google_authenticator.so идёт первым и отрезает OTP-код от конца строки, pam_unix.so с use_first_pass проверяет оставшуюся часть как системный пароль пользователя, не спрашивая его заново.

3. Подключите PAM-плагин в конфиге сервера (server.conf):

plugin /usr/lib/openvpn/openvpn-plugin-auth-pam.so openvpn

Точный путь к .so-файлу зависит от дистрибутива и версии пакета — проверьте командой dpkg -L openvpn | grep plugin (Debian/Ubuntu) перед тем, как прописывать путь в конфиг.

4. На клиенте добавьте в .ovpn:

auth-user-pass
auth-nocache

auth-nocache заставляет OpenVPN не кэшировать пароль между попытками переподключения — иначе при разрыве связи клиент попробует переподключиться со старым, уже недействительным TOTP-кодом и получит отказ, что выглядит как случайный баг.

Если сервер уже требует клиентский сертификат (ca, cert, key в конфиге), эта настройка ничего не меняет: сертификат по-прежнему проверяется отдельно и обязателен. Плагин PAM добавляет TOTP+пароль как независимый второй слой, а не заменяет сертификат.

IKEv2/strongSwan: TOTP через xauth-pam

Для IKEv2 та же идея реализуется через strongSwan и опцию rightauth2, которая включает механизм множественной аутентификации (RFC 4739) — второй раунд проверки после основного.

1. Проверьте, что плагин xauth-pam доступен:

ipsec listplugins | grep -i xauth

На Debian/Ubuntu он обычно идёт в пакете с «дополнительными» плагинами strongSwan (называние пакета менялось между релизами — проще проверить apt search strongswan | grep -i extra и поставить найденный пакет, чем полагаться на конкретное имя).

2. Настройте PAM-стек — аналогично OpenVPN, но со своим именем сервиса, /etc/pam.d/strongswan-xauth:

auth requisite pam_google_authenticator.so forward_pass
auth required pam_unix.so use_first_pass
account required pam_permit.so

3. В ipsec.conf добавьте второй фактор аутентификации к существующему подключению (предполагается, что сертификатная часть уже настроена — см. strongSwan на Ubuntu 24.04):

conn ikev2-2fa
    keyexchange=ikev2
    left=%any
    leftid=@vpn.example.com
    leftcert=serverCert.pem
    leftsendcert=always
    leftsubnet=0.0.0.0/0
    right=%any
    rightauth=pubkey
    rightauth2=xauth-pam
    rightsourceip=10.10.10.0/24
    rightdns=1.1.1.1
    auto=add

rightauth=pubkey требует от клиента валидный сертификат (первый фактор), rightauth2=xauth-pam — дополнительно логин/пароль+OTP через PAM (второй фактор). Оба должны пройти, иначе туннель не поднимется.

Честная оговорка: множественная аутентификация IKEv2 (RFC 4739) поддерживается не всеми клиентами. StrongSwan-клиенты на Linux и Android работают с ней штатно, а встроенные IKEv2-клиенты Windows, macOS и iOS в большинстве версий такую связку не поддерживают. Проверьте схему с реальными устройствами пользователей до прода — при смешанном парке честнее оставить cert+TOTP на IKEv2 только для strongSwan-клиентов, а для мобильных держать отдельный контур на OpenVPN, где PAM работает предсказуемо на любой платформе.

Сертификат + TOTP: где эта связка оправдана, а где избыточна

Комбинация «сертификат + TOTP» — это не режим по умолчанию для всех VPN-пользователей, а инструмент для конкретных случаев:

СценарийНужен ли TOTP поверх сертификата
Обычный удалённый сотрудник, личное устройство под MDMЧасто избыточно — сертификат + строгий контроль устройства обычно достаточны
Административный доступ к продовой инфраструктуре через VPNДа — цена компрометации высока, а факторов и так должно быть больше одного
Общие/шаредные учётные записи для подрядчиковДа, обязательно — TOTP на личном телефоне конкретного человека решает проблему «кто именно подключился»
Site-to-site туннель между офисами (не пользовательский доступ)Не применимо — там аутентифицируются машины, а не человек с телефоном
VPN для доступа к CI/CD, секретам, платёжным системамДа, без обсуждения

Практический принцип: сертификат отвечает за «это разрешённое устройство», TOTP — за «это разрешённый человек прямо сейчас». Там, где достаточно первого утверждения, второй фактор — лишний шаг при каждом подключении. Там, где нужна персональная ответственность за действия (административный доступ, продакшен), TOTP закрывает риск, который сертификат не закрывает в принципе: кражу или передачу файла ключа третьему лицу.

Резервные коды и что делать при потере телефона

При генерации секрета google-authenticator печатает 5 одноразовых резервных кодов — они работают вместо TOTP-кода ровно один раз каждый, если приложение недоступно (телефон потерян, разряжен, сброшен). Их стоит сохранить сразу, отдельно от пароля к VPN:

  • Распечатать и убрать в физически защищённое место, либо сохранить в зашифрованном виде отдельно от менеджера паролей, где лежит основной пароль — иначе компрометация одного хранилища ломает сразу оба фактора.
  • Не оставлять в открытом текстовом файле рядом с .ovpn-конфигом или .p12-сертификатом на том же устройстве — тогда кража одного файла с диска отдаёт оба фактора разом.

Если резервные коды закончились или потеряны вместе с телефоном, секрет TOTP придётся перевыпускать. Заходите на сервер по SSH (не через VPN, который сейчас недоступен) от имени администратора и запускаете google-authenticator заново для нужного пользователя — старый секрет и QR-код перезаписываются новым. Если административный SSH-доступ тоже защищён 2FA (см. двухфакторную аутентификацию для SSH), заранее убедитесь, что есть запасной путь входа на сервер — иначе рискуете заблокировать себя полностью, если оба набора резервных кодов потеряются одновременно.

Для команды из нескольких человек процедуру перевыпуска секрета стоит формализовать: кто на сервере имеет право запускать google-authenticator для чужого пользователя и как подтверждается личность того, кто просит сброс. Без этого «я потерял телефон, перевыпусти TOTP» превращается в социальную инженерию для обхода второго фактора — ровно то, от чего он должен защищать.

Арендуйте сервер под свои задачи!

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

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

Можно ли использовать TOTP вместо сертификата, а не вместе с ним?

Технически да — PAM-плагин работает независимо от того, требует сервер клиентский сертификат или нет. Но это снижает общий уровень защиты: сертификат сложнее украсть удалённо (нужен доступ к файловой системе устройства), а связка «сертификат + TOTP» перекрывает больше сценариев атаки, чем любой из факторов по отдельности.

Что если у пользователя один и тот же пароль используется и для системного логина, и для VPN?

Так и должно быть в этой схеме — pam_unix.so проверяет именно системный пароль Linux-пользователя. Если хотите отдельный пароль для VPN, не совпадающий с системным, потребуется отдельная база пользователей (например, через FreeRADIUS) вместо прямой проверки по pam_unix.so.

Работает ли эта схема с RADIUS-аутентификацией вместо локальных Linux-пользователей?

Да, и для смешанного парка клиентов это часто удобнее: FreeRADIUS с модулями TOTP (например, rlm_otp или интеграция с privacyIDEA) плюс плагин eap-radius в strongSwan или plugin ... openvpn-auth-radius в OpenVPN дают тот же результат, но без привязки к системным Unix-аккаунтам на самом VPN-сервере — актуально, если пользователей много и их проще централизованно администрировать в RADIUS.

Замедлит ли это подключение к VPN?

На практике добавляется один шаг — ввод 6 цифр после пароля, 5–10 секунд на подключение. Установка самого туннеля (handshake, назначение IP) занимает сопоставимое время независимо от PAM-проверки.

Нужно ли гонять NTP отдельно для этой схемы?

Да, критично: TOTP основан на текущем времени, и если часы сервера уезжают больше чем на 1–2 интервала (30–60 секунд), коды перестанут совпадать у всех пользователей одновременно — это выглядит как массовый сбой VPN, а на деле проблема с chronyd/systemd-timesyncd. Проверяйте timedatectl status на сервере, особенно после миграции на новый VPS.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →