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

Один вход, два обмена с RADIUS

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

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

Именно этот симптом и нужно искать, и его легко подтвердить только со стороны клиента: если клиент VPN запрашивает ровно один секрет, а затем отклоняет пароль, который вы знаете как верный, обмен, вероятно, закончился на вызове.

Что на самом деле несёт вызов

Спецификация RADIUS описывает код 11 в разделе 4.4 и допускает два атрибута, которые здесь важны. Reply-Message содержит текст для пользователя, а State содержит непрозрачное значение, которое сервер хочет получить обратно. NAS не должен интерпретировать State, только возвращать его без изменений.

Последующий запрос использует новый Identifier и новый Request Authenticator, и он должен нести то же значение State плюс ответ пользователя. Сервер сопоставляет его с ожидающим вызовом именно по этому State, поэтому шлюз, который заново создаёт или отбрасывает атрибут, не может завершить церемонию. Response authenticator в каждом ответе тоже должен проверяться, иначе NAS должен отбросить пакет.

Раздел 4.4 добавляет деталь, объясняющую большинство тихих сбоев: NAS, не поддерживающий вызовы, трактует Access-Challenge как отказ. Если служба VPN вашего шлюза старше этой поддержки или опускает её, запрос бэкенда о втором факторе превращается в мгновенное «аутентификация не удалась» без какого-либо запроса.

Где теряется цепочный запрос

Первый подозреваемый — путь запроса, а не учётные данные. Портал, показывающий поле OTP для веб-входов, не делает этого автоматически для службы VPN, а некоторые шлюзы передают вызов только клиентам, которые объявляют такую возможность. Проверьте ту же учётную запись на обеих точках входа; если портал работает, а VPN нет, вы смотрите на передачу, а не на токен.

Формат ввода — второй подозреваемый. Склейка пароля и кода без документированного поставщиком разделителя или разрешение сохранённым учётным данным повторять старый код приводит к сбою, который выглядит точно так же, как неверный пароль. Используйте документированный оператором отдельный запрос или объединённый формат и никогда не изобретайте разделитель.

Дефекты, специфичные для версии, существуют, но список исправленных версий многолетней давности не является диагнозом для сегодняшнего развёртывания. Читайте примечания к выпуску того ПО, которое вы действительно запускаете, и сохраняйте наблюдённую стадию обмена как доказательство.

Проследите одну попытку от начала до конца

Воспроизведите её один раз с включённой отладкой на стороне сервера и держите все остальные сеансы вне окна захвата:

$ sudo radsniff -i eth0 -x -f 'udp port 1812'
$ sudo freeradius -X
$ radtest alice 'password' 127.0.0.1 0 testing123

В выводе ищите форму разговора, а не одну строку. Первый Access-Request с Identifier 3, Access-Challenge, несущий State, затем второй Access-Request с Identifier 4, который повторяет этот State и включает ответ пользователя. Если второй запрос отсутствует, шлюз так и не выполнил продолжение. Если он приходит без State, сервер не может сопоставить его с ожидающим вызовом и обычно отклонит.

Скрывайте учётные данные, токены и ненужные данные личности, когда делитесь трассировкой, и сопоставляйте события из одной попытки, вместо того чтобы смешивать повторы из нескольких вкладок браузера. Метки времени здесь ваш друг; вызов, который приходит после того, как клиент сдался, для пользователя выглядит как отказ, а в журнале — как медленный ответ.

Желаемое конечное состояние — завершённый, авторизованный разговор и последующий предусмотренный доступ к службе. Ответ, пришедший от сервера RADIUS, доказывает гораздо меньше.

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