OpenVPN lee la contraseña del terminal, no de stdin
Dónde lee realmente OpenVPN una contraseña, por qué falla un archivo en stdin y las tres vías admitidas para iniciar sesión con scripts en Linux y macOS.
OpenVPN pide un nombre de usuario y una contraseña en el terminal de control, y un archivo redirigido a la entrada estándar no es ese terminal. Ese único detalle explica el script que se cuelga con la contraseña justo ahí en la tubería. El cliente dibuja el aviso y la lectura se toma del dispositivo de terminal, así que redirigir stdin no cambia nada. Alimente al cliente por una de sus vías de entrada documentadas y el mismo script se conecta al primer intento.
Tres vías cubren casi todos los casos, y cada una falla a su manera. Elija por el aviso que el cliente muestra realmente, no por la opción que sea más fácil de escribir en un script.
El aviso no viene de stdin
Cuando OpenVPN necesita credenciales abre el terminal de control y lee allí. Por eso una prueba interactiva se ve bien mientras el mismo comando bajo cron o un archivo de unidad queda inactivo con el aviso escrito en un registro que nadie mira. Algunas compilaciones vuelven a la entrada estándar cuando no existe un terminal, y esa inconsistencia es peor que un fallo duro porque esconde el problema hasta el despliegue.
Compruebe el entorno antes de escribir cualquier código: ejecute el cliente bajo el mismo usuario, con el mismo stdin, que usará el planificador o el gestor de servicios. Si el aviso nunca aparece en el registro y el proceso no avanza, algo espera un terminal que no existe.
Primera vía: un archivo de credenciales de dos líneas
La opción de autenticación toma una ruta, y el archivo contiene exactamente dos líneas, primero el nombre de usuario y luego la contraseña, sin nada más. Pase la ruta explícitamente en lugar de confiar en un nombre de archivo predeterminado, porque un archivo de credenciales perdido en el directorio de trabajo es cómo la cuenta equivocada acaba en uso. Fije el modo en 0600 y dé la propiedad a la cuenta que ejecuta el cliente.
El cliente lee ese archivo una vez al arrancar, así que rotar la contraseña significa reiniciar el proceso. Normalmente ese es el comportamiento que quiere, y pertenece al runbook junto al procedimiento de rotación.
Segunda vía: askpass para la frase de la clave
Una clave privada protegida con frase plantea un segundo aviso distinto, y tiene su propia respuesta en archivo: la opción askpass lee la frase de la primera línea de un archivo. Para los túneles basados en SSH el equivalente es un programa askpass que el cliente ejecuta, y cuya salida estándar se convierte en el secreto.
Ninguna de las dos formas pone el secreto en la lista de argumentos, y ambas lo dejan existiendo como archivo o como ejecutable que lo imprime. La protección son los permisos de archivo y la propiedad del proceso, no la oscuridad. Un ayudante que hace eco de una cadena escrita en el código es un secreto con pasos extra.
Tercera vía: la CLI propia del cliente del portal
Los clientes empresariales suelen incluir un punto de entrada de línea de comandos que se conecta a un portal con nombre sin ninguna ventana, y esa es la vía admitida. En Linux el cliente GlobalProtect expone operaciones de conexión e importación de certificado a través de su CLI, y los portales que usan autenticación por certificado necesitan el paso de importación antes de que una conexión automatizada pueda funcionar. Preféralo a las pulsaciones sintetizadas: obtiene un estado de salida real, ninguna dependencia del foco de la ventana y sobrevive a una pantalla bloqueada.
Si la primera conexión todavía necesita a una persona para aceptar un certificado, la automatización no está terminada. Haga la importación durante la configuración y regístrela como requisito previo.
Cuando el flujo necesita un pseudo-terminal
Una secuencia que pide una contraseña y luego un código de un solo uso no tiene un único archivo que leer. Un controlador de terminal como Expect es la herramienta correcta porque espera cada patrón por turno, y necesita el proceso iniciado antes de poder coincidir con nada.
Dos fallos dominan. Un script que espera un aviso sin lanzar el cliente espera para siempre, y Tcl no es un shell, así que la aritmética de shell escrita dentro de un bloque expect no se evalúa como se lee. Mantenga la bandera de depuración activa mientras construye los patrones y luego apáguela.
Secretos que se filtran, y dónde se esconden
Todo lo que se pasa como argumento es visible en la lista de procesos, así que las credenciales van en un archivo o detrás de un ayudante, nunca en la línea de comandos. Los códigos de un solo uso se consumen por diseño y hay que producirlos para cada intento. Los registros de fallos a menudo llevan el nombre de usuario y a veces más, así que redáctelos antes de enviarlos a cualquier parte, y mantenga el secreto fuera del propio perfil, porque un archivo de configuración con una contraseña incrustada acaba pegado en tickets y repositorios. Rotar la cuenta entonces significa cazar cada copia, que es exactamente el coste que evita esta disposición.
Audite las vías que eligió y luego conéctelas al archivo de unidad o al planificador que realmente ejecutará el cliente. El túnel vive exactamente tanto como ese proceso.