Вярването е, че here-документ с четири реда е пълноценен неинтерактивен вход и то се държи, докато шлюзът не предложи две групи, не отпечата банер или не поиска токен след паролата. Тогава същият скрипт въвежда паролата в меню, което е очаквало число. Клиентът на командния ред в Linux може да се скриптира, но само ако му подадете това, което наистина чака, а не това, което урокът е предполагал.

Фиксираният here-документ е мит

Linux клиентът на Cisco инсталира малка програма в /opt/cisco/anyconnect/bin/vpn и Secure Client 5 все още я доставя. Докато услугата vpnagentd работи, флагът -s чете отговори от стандартния вход в реда, в който клиентът ги иска. Този ред не е фиксиран между сървърите.

Менюто с групи добавя един ред. Банерът за вход добавя още един. Подканата за токен след паролата напълно чупи скрипт от четири реда, защото петият ред никога не е трябвало да бъде токенът. Отказът е тих: клиентът получава грешен низ, опитът за свързване приключва и скриптът не съобщава нищо полезно.

Стартирайте клиента ръчно веднъж срещу същия шлюз и версия и запишете подканите в реда, в който се появяват. Този запис е спецификацията, на която вашият скрипт трябва да отговаря.

Какво чака клиентът

В обичайния случай с една група последователността е потребителско име, парола и понякога потвърждение на банер. Първият ред на here-документ става индекс на меню само когато сървърът наистина покаже меню, затова един и същ скрипт работи на едно място и се проваля на следващото.

/opt/cisco/anyconnect/bin/vpn -s connect vpn.example.net <<EOF
0
alice
$VPN_PASSWORD
y
EOF

Четете това като четири отговора на четири възможни въпроса, а не като фиксиран протокол. Нулата е избор от меню, а не парола, а завършващото y приема банер, който много шлюзове никога не изпращат.

Използвайте expect, когато редът не е предвидим

Когато редът на подканите се мени, спрете да броите редове и вместо това изчакайте подканата. Скрипт с expect стартира командата connect, чака подканата за потребителско име, изпраща, чака подканата за парола, изпраща и след това чака състоянието на свързаност. Всяко изчакване има собствен таймаут.

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

Expect ви дава и запис, който можете да логнете с премахната тайна, и това струва повече от кода за изход, когато шлюзът смени подканите си след надграждане.

Тайната трябва да живее някъде

Всяка версия на този проблем има една слабост: паролата трябва да съществува във форма, която клиентът може да прочете. Подаването ѝ като аргумент я излага в таблицата на процесите. Отпечатването ѝ през конвейер често я слага в историята на обвивката. И двете се четат от други локални потребители на споделен междинен хост.

install -m 600 /dev/null ~/.vpn-secret
umask 077; VPN_PASSWORD=$(cat ~/.vpn-secret) /opt/cisco/anyconnect/bin/vpn -s connect vpn.example.net

Файл с режим 600, притежаван от акаунта, е минимумът и той все още е тайна в чист текст на диска. secret-tool lookup чете от ключодържателя на Linux, а на macOS същата работа върши security find-generic-password -w. Където организацията поддържа удостоверяване със сертификат или SAML, предпочитайте го, защото запазена парола плюс MFA все още не може да завърши вход без човек.

Потвърдете тунела, после поемете прекъсването

Не се доверявайте на липсата на текст за грешка. Попитайте клиента за състоянието му и проверете интерфейса независимо:

/opt/cisco/anyconnect/bin/vpn state
ip -brief address

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

Прекъснете с vpn disconnect и оставете скрипта, стартирал тунела, да поеме прекъсването. Неуспешна задача, която остави сесия отворена, изразходва лицензно място и изглежда като проблем с удостоверяването за следващия, който опита.

Ред на работа: потвърдете vpnagentd, запишете действителния ред на подканите, изберете here-документ или expect, дръжте тайната извън argv и историята, проверете състоянието и един ресурс, после прекъснете в същия скрипт.

Подобни статии