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

Почему та же команда срывается внутри скрипта

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

Пароль с восклицательным знаком добавляет более тихий второй сбой. Внутри двойных кавычек оболочка раскрывает его задолго до того, как клиент что-либо увидит.

Заключите полезную нагрузку в одинарные кавычки, и символ пройдёт целым. Это вся правка, и она объясняет целый класс отчётов, где одни и те же учётные данные работают при вводе и срываются при сохранении. Проверьте, что сделала оболочка, прежде чем проверять шлюз: выведите нагрузку через обёртку, показывающую точные байты, и посчитайте строки. Большинство таких расследований заканчиваются именно там.

Запишите ответы в том порядке, в котором клиент их запрашивает

Запустите клиент один раз интерактивно и запишите каждый запрос по порядку. Выбор группы появляется только тогда, когда шлюз публикует несколько профилей, а запрос баннера — только тогда, когда он настроен. Файл ответов должен соответствовать тому шлюзу, на который вы действительно направлены, а не тому, что в документации.

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

connect vpn.lab.example
0
username
password
y
exit
/opt/cisco/anyconnect/bin/vpn -s < anyconnect.txt

Та же последовательность может прийти через канал, когда вы предпочитаете не держать файл на диске. Правила цитирования по-прежнему решают, выживет ли она.

Держите учётные данные вне списка процессов

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

printf 'username\npassword\ny\n' | /opt/cisco/anyconnect/bin/vpn -s connect vpn.lab.example

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

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

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

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

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

/opt/cisco/anyconnect/bin/vpn state
/opt/cisco/anyconnect/bin/vpn disconnect

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

Когда фиксированный файл ответов — неподходящий инструмент

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

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

Поскольку протоколы различаются, vpnc не может достичь шлюза, который публикует только профили AnyConnect, а обычная открытая альтернатива для этой службы — openconnect с выбранным протоколом anyconnect. Файл pcf принадлежит старому клиенту Cisco, и хотя его хост, имя группы и групповой пароль можно заново ввести в клиенте, который всё ещё говорит по Cisco IPsec, файл не переносится между клиентами. Необычный порт или нестандартный режим туннелирования обычно теряются при таком переносе. Решите, какой протокол предлагает шлюз, прежде чем выбирать инструмент.

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