Se cree que un here-document con cuatro líneas es un inicio de sesión no interactivo completo, y esa creencia aguanta justo hasta que la pasarela ofrece dos grupos, imprime un banner o pide un token después de la contraseña. Entonces el mismo script escribe la contraseña en un menú que esperaba un número. El cliente de línea de comandos en Linux se puede automatizar, pero solo si le entrega lo que de verdad espera y no lo que el tutorial supuso.

El here-document fijo es un mito

El cliente Linux de Cisco instala un pequeño programa en /opt/cisco/anyconnect/bin/vpn, y Secure Client 5 todavía lo incluye. Con el servicio vpnagentd en marcha, el flag -s lee las respuestas de la entrada estándar en el orden en que el cliente las pide. Ese orden no es fijo entre servidores.

Un menú de grupos añade una línea. Un banner de inicio de sesión añade otra. Una petición de token después de la contraseña rompe por completo un script de cuatro líneas, porque la quinta línea nunca iba a ser el token. El fallo es silencioso: el cliente recibe la cadena equivocada, el intento de conexión termina y el script no informa de nada útil.

Ejecute el cliente a mano una vez contra la misma pasarela y versión, y anote los avisos en el orden en que aparecen. Esa transcripción es la especificación que su script debe cumplir.

Qué espera el cliente

En el caso habitual de un solo grupo, la secuencia es nombre de usuario, contraseña y a veces una confirmación de banner. La primera línea de un here-document solo se convierte en un índice de menú cuando el servidor presenta realmente un menú, y por eso el mismo script funciona en un sitio y falla en el siguiente.

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

Léalo como cuatro respuestas a cuatro preguntas posibles, no como un protocolo fijo. El cero es una selección de menú, no una contraseña, y la y final acepta un banner que muchas pasarelas nunca envían.

Use expect cuando el orden no es predecible

Cuando el orden de los avisos varía, deje de contar líneas y espere el aviso. Un script expect lanza el comando connect, espera el aviso de nombre de usuario, envía, espera el aviso de contraseña, envía y después espera el estado conectado. Cada espera tiene su propio tiempo de espera.

Trate un tiempo de espera agotado como un fallo y salga. Un script que sigue enviando entrada tras un aviso inesperado escribirá alegremente la contraseña en un shell, en un menú o en cualquier otra cosa que esté leyendo. Así es como un script de inicio de sesión se convierte en un incidente.

expect también le da una transcripción que puede registrar con el secreto eliminado, y vale más que el código de salida cuando una pasarela cambia sus avisos tras una actualización.

El secreto tiene que vivir en algún sitio

Todas las versiones de este problema comparten una debilidad: la contraseña debe existir en una forma que el cliente pueda leer. Pasarla como argumento la expone en la tabla de procesos. Enviarla por una tubería a menudo la deja en el historial del shell. Ambas cosas son legibles por otros usuarios locales en un host de salto compartido.

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

Un archivo con modo 600 propiedad de la cuenta es el mínimo, y sigue siendo un secreto en texto plano en el disco. secret-tool lookup lee del llavero de Linux, y en macOS la misma tarea la hace security find-generic-password -w. Donde la organización admite autenticación por certificado o SAML, prefíerala, porque una contraseña guardada más MFA sigue sin poder completar un inicio de sesión sin una persona.

Confirme el túnel y luego asuma el cierre

No confíe en la ausencia de texto de error. Pregunte al cliente por su estado y compruebe la interfaz por separado:

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

El estado debería decir Connected, y una interfaz de túnel debería tener una dirección. Luego solicite un recurso que el túnel deba alcanzar, porque un estado conectado sin ruta es un resultado real y fácil de pasar por alto.

Desconéctese con vpn disconnect, y deje que el script que inició el túnel se encargue del cierre. Un trabajo fallido que deja una sesión abierta consume una plaza de licencia y parece un problema de autenticación a la siguiente persona que lo intente.

Orden de trabajo: confirme vpnagentd, capture el orden real de los avisos, elija here-document o expect, mantenga el secreto fuera de argv y del historial, verifique el estado y un recurso, y luego desconéctese en el mismo script.

Artículos relacionados