Archivo de credenciales o socket de gestión de OpenVPN: qué conviene automatizar
auth-user-pass cubre el aviso de la cuenta; el socket de gestión cubre los cuatro. Compare la exposición, el coste de automatizar y cómo falla cada uno en un servicio.
Un script que inicia OpenVPN y nunca conecta no suele ser un problema de red: el cliente está ante un aviso sin un terminal donde dibujarlo. OpenVPN tiene exactamente dos formas admitidas de responder ese aviso sin una persona, un archivo de credenciales detrás de auth-user-pass y el socket de gestión, y no son intercambiables. El archivo cuesta una directiva y responde un aviso; el socket responde todos los avisos y entrega a cualquier cosa que pueda abrir un puerto loopback un canal de control sin autenticación. Cuál corresponde a su despliegue depende de qué aviso bloquea en realidad y de qué secreto puede permitirse dejar en reposo.
Nombre el aviso antes de elegir un mecanismo
Cuatro avisos se ven idénticos en un terminal. El par de cuenta viene de la configuración PAM o auth-user-pass-verify del servidor y lo responde auth-user-pass. La frase de contraseña de una clave privada pertenece al archivo de clave y se lee con --askpass o se teclea a mano. Un paquete PKCS#12 pide una contraseña propia. La autenticación de proxy usa el archivo auth que toma --http-proxy, no las credenciales de la cuenta.
Cuando OpenVPN se ejecuta como hijo de systemd, PHP o Node no hay terminal, así que cualquiera de estos bloquea en silencio. El proceso se queda ahí, el registro se detiene tras la línea de cifrado y la unidad acaba agotando el tiempo; ese silencio es la razón de que la gente añada un bucle de reintento o un sleep en lugar de mirar qué aviso está pendiente. Solo el socket de gestión puede responder los cuatro. El archivo de credenciales responde el primero y nada más.
auth-user-pass: un archivo, un aviso
El archivo guarda el nombre de usuario en la línea uno y la contraseña en la línea dos, y nada más: sin comillas, sin nombres de clave, sin comentario. Ponga el modo 600 y haga dueño a la cuenta que ejecuta openvpn, que para un servicio suele ser un usuario dedicado y no su inicio de sesión. Un archivo propiedad de root bajo /root es la diferencia entre un comando que funciona en su shell y una unidad que falla al arrancar.
Dos detalles convierten un archivo correcto en un aviso. Un editor que guarda CRLF deja un retorno de carro pegado a la contraseña, así que el servidor rechaza una contraseña que en el archivo parece correcta; compruébelo con cat -A u od -c en lugar de a ojo. Y un auth-user-pass sin argumento dentro del perfil significa «pregunta al usuario» por diseño, algo que una segunda directiva en la línea de órdenes puede que no anule, porque el perfil se analiza donde está.
El orden de las opciones es la tercera trampa, y depende de la versión. Algunas compilaciones de OpenVPN 2.4 ignoran --auth-user-pass cuando aparece antes de --config, así que las mismas dos opciones en el otro orden conectan. Ponga la directiva dentro del perfil, o después de --config en la línea de órdenes, y busque en el perfil cada aparición antes de cambiar nada más.
auth-nocache pertenece a este mecanismo pero no aporta nada. Limita cuánto tiempo guarda el cliente la credencial en memoria, lo que ayuda tras un fallo y nada en absoluto cuando falta el archivo. Una reconexión tras un tiempo de espera de sesión en el servidor vuelve a leer el archivo, así que una credencial que funcionó al arrancar puede caducar a mitad del día.
El socket de gestión: todos los avisos, más superficie
Inicie el cliente con un escucha y declare explícitamente que los avisos se informarán por él, con las directivas documentadas en el manual de OpenVPN 2.6:
management 127.0.0.1 3030
management-query-passwords
Desde bash, mantenga la conexión en un descriptor de archivo libre y responda por nombre de aviso en lugar de por posición, porque una reconexión puede preguntar en otro orden:
exec 3<>/dev/tcp/127.0.0.1/3030
while read -r -u 3 line; do
case "$line" in
*"Need 'Auth' username/password"*)
echo 'username "Auth" alice' >&3
echo 'password "Auth" secret' >&3 ;;
*"Need 'Private Key' password"*)
echo 'password "Private Key" secret' >&3 ;;
esac
done
La frontera es el transporte. El protocolo de gestión es texto plano sobre TCP en loopback, así que el escucha no debe publicarse en una dirección de LAN o de túnel para que un controlador remoto lo alcance; un controlador remoto significa un reenvío SSH, no un enlace más ancho. El demonio comunitario también acepta un solo cliente de gestión a la vez, así que una GUI o un monitor no pueden compartir el socket con su script. La segunda conexión se rechaza, no se encola, y el fallo parece un script que se quedó sordo.
Ese socket es también un canal de control. Sin contraseña de gestión, cualquier cosa que pueda conectarse a 127.0.0.1:3030 puede leer el estado, matar el túnel o responder un aviso por sí misma. La contraseña de gestión y el archivo de credenciales son secretos de la misma clase, y ambos merecen el mismo cuidado.
Cuál encaja con el despliegue
Elija el archivo de credenciales cuando el único aviso sea el par de cuenta, el cliente se ejecute como servicio con un dueño estable y pueda mantener un archivo 600 fuera de copias de seguridad que no controla. Elija el socket de gestión cuando haya una frase de contraseña de clave o una contraseña PKCS#12, cuando el envoltorio ya supervise el proceso o cuando necesite vigilar estado y avisos mientras depura una reconexión.
Dos condiciones mueven la decisión. Si el envoltorio es /bin/sh, una unidad de systemd que llama al binario directamente o un contenedor mínimo, el pegamento de socket solo para bash no está disponible y el archivo es la respuesta más barata. Si el secreto rota a menudo, ningún archivo es un buen hogar para él: consulte un llavero desde un envoltorio pequeño y deje que la unidad llame al envoltorio, lo que mantiene la rotación en un solo lugar y la contraseña fuera del historial del shell.
La sustitución de procesos se sitúa entre los dos y no pertenece a ninguno. La orden de una línea de abajo funciona porque bash la expande antes de que openvpn arranque, no porque el cliente entienda la sintaxis:
openvpn --config client.ovpn --auth-user-pass <(printf "%s
%s
" "$USER" "$PASS")
Se rompe bajo /bin/sh, en una unidad que evita el shell y en imágenes sin bash ni /dev/fd. Consérvelo para pruebas interactivas, nunca como el contrato del que depende un servicio.
Proteja el secreto y luego verifique desde el registro
Ambos mecanismos dejan un secreto legible por el proceso de OpenVPN. Nunca ponga la contraseña en la línea de órdenes ni en el archivo de la unidad, donde ps y systemctl la muestran a cada usuario local; pase la ruta al archivo, no el valor que contiene. Donde los certificados pueden sustituir al par de cuenta, eso elimina la categoría de aviso en lugar de ocultarla.
Una ejecución correcta muestra la secuencia de avisos completándose y la sesión alcanzando «Initialization Sequence Completed». Si el cliente se detiene en el mismo aviso, la coincidencia falló: imprima las líneas exactas que envió el socket, compruebe las comillas y el nombre del aviso, y corrija el patrón en lugar de añadir un sleep. Un túnel que informa éxito y no transporta nada es un problema de enrutamiento o de push, no de credenciales.
Después pruebe la reconexión, no solo el primer arranque. Corte la sesión del servidor o espere su tiempo de espera; el cliente vuelve a preguntar, y es ahí donde un archivo que parecía correcto al arrancar muestra si sigue siendo legible para la cuenta que se reconecta.