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

Порядок запросов показывает, в каком потоке вы находитесь

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

Неверная форма выглядит как плохой код. Вставьте свежий код в поле только для пароля, и сервер прочитает его как часть пароля. На стороне клиента OpenVPN 2.4 и новее делают разницу видимой: сервер, отвечающий AUTH_FAILED,CRV1:, ожидает ответ на вызов, поэтому профилю нужен static-challenge или файл пароля в форме SCRV1:. Более старый профиль только с auth-user-pass проверяет пароль и затем останавливается, что в журнале выглядит как сбой OTP, хотя код не отправлялся.

WireGuard стоит назвать исключением: он аутентифицирует пары ключей, а не людей, поэтому поля для кода нет. Если провайдер рекламирует такой код, его принимает что-то за пределами туннеля.

Что сервер делает с шестью цифрами

Коды на основе времени следуют RFC 6238, который оборачивает более старую конструкцию со счётчиком из RFC 4226: HMAC над движущимся фактором, по умолчанию усечённый до шести цифр. Для TOTP движущийся фактор — текущее время Unix, делённое на шаг, 30 секунд, если оператор его не менял. Проверяющая сторона никогда не сравнивает ваши цифры с сохранённым значением; она пересчитывает ожидаемый код из общего зерна и обычно принимает соседние шаги, поэтому медленный обмен не срывает вход.

Два следствия упускаются. Часовой пояс телефона не имеет значения, потому что зерно никогда не видит местные часы — важна только отстройка от реального UTC, и аппарат, спешащий на две минуты, ошибается на каждом коде, показывая при этом чистый обратный отсчёт. И код одноразовый по замыслу: проверяющая сторона помнит последнее принятое значение счётчика для этого зерна, поэтому те же цифры, отправленные снова, отклоняются даже в том же окне. Клиент, повторяющий попытку после тайм-аута, может сжечь только что отправленный код.

Токены на основе счётчика сдвигают счётчик при каждом нажатии, поэтому выходят из синхронизации после того, как коды сгенерированы, но так и не отправлены; обычное исправление — окно ресинхронизации, принимающее несколько значений вперёд. Если оператор зарегистрировал HOTP, а ваше приложение показывает TOTP, каждое значение неверно так, что это похоже на проблему с часами. URI подготовки за QR-кодом указывает тип, цифры, период и хеш.

Сбои, которые выглядят как неверный код

Самая частая причина — зарегистрированная запись. Приложения-аутентификаторы помечают записи по издателю и учётной записи, поэтому у кого две личности на одном VPN, может оказаться две записи, метки которых различаются одним символом. Код действителен для зерна, которое его сгенерировало, и ни для чего другого. Сравните метку на телефоне с именем пользователя, которое фиксирует сервер, а не с тем, что, как вам помнится, вы ввели.

Второе — несовпадающий набор параметров. Зерно, зарегистрированное с восемью цифрами, периодом 60 секунд или SHA-256, даёт коды, которые проверяющая сторона, ожидающая шесть цифр, 30 секунд и SHA-1, отклоняет, а на клиенте это неотличимо от неверного кода. Это проявляется после миграций, когда запись добавляли заново по фотографии QR-кода или когда запись токена пересобирали со значениями по умолчанию.

Третье — не про код. Шлюзы обычно возвращают одну общую ошибку аутентификации для неверного пароля, истёкшего кода и отключённой учётной записи, намеренно, чтобы никто не мог выяснить, какой фактор отказал. Читайте журнал шлюза или RADIUS вместо сообщения клиента: никогда не выданный вызов, отказ в доступе без атрибута OTP и отказ по политике выглядят на экране одинаково и ведут к разным следующим шагам.

Короткая последовательность, которая это сужает

Начните с самой дешёвой проверки и остановитесь на первом шаге, который не выполняется.

  1. Дождитесь свежего кода, отправьте его один раз и отметьте, появляется ли вызов до или после принятия пароля.
  2. Сопоставьте метку в аутентификаторе с именем пользователя, которое хранит сервер.
  3. Убедитесь, что профиль вообще может ответить на вызов, как в случае CRV1 выше.
  4. Сравните часы устройства с известным источником времени; расхождение больше нескольких десятков секунд само ломает TOTP.
  5. Спросите оператора, TOTP это или HOTP и какие цифры, период и хеш были зарегистрированы.

Два правила не дают этому ухудшиться. Не повторяйте попытки много раз: многие шлюзы считают сбои на учётную запись и либо блокируют её, либо начинают задерживать ответы, так что шквал превращает мелкую ошибку конфигурации в обращение в поддержку. И не перерегистрируйте токен ради диагностики, потому что это делает старое зерно недействительным; если настоящей неисправностью был вызов, который клиент так и не отправил, теперь у вас две изменения для объяснения вместо одного.

Держите зерно и коды восстановления вне цикла

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

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

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

Похожие статьи