El autenticador muestra un código nuevo de seis dígitos, la VPN lo rechaza y el mismo código se verifica sin problemas cuando lo prueba desde su propio shell. Esa brecha es toda la historia. Un módulo PAM que no puede abrir el secreto de inscripción devuelve un fallo que parece idéntico a un código incorrecto, y el entorno del servicio que oculta los directorios personales es una causa habitual. Antes de relajar cualquier permiso, decida en cuál de las tres situaciones está.

¿Cuál de los tres fallos es este?

El primero es un secreto que el módulo no puede leer en absoluto. El segundo es un secreto que puede leer pero no actualizar. El tercero es un código que realmente es incorrecto, normalmente por deriva del reloj o un valor reutilizado.

Sepárelos leyendo el diario del servicio y el registro de autenticación del sistema para un intento fallido, y luego confirme qué servicio PAM carga el complemento y qué línea de módulo usa ese servicio. Un mensaje genérico de fallo de autenticación no los distingue, ni tampoco una prueba manual correcta, porque su shell no es el entorno del servicio.

La vista del sistema de archivos de la unidad es el culpable habitual cuando solo falla el servicio.

systemctl show -p ProtectHome -p ProtectSystem -p ReadWritePaths [email protected]
ls -l /var/lib/vpn-otp/*/.google_authenticator 2>/dev/null | head -n 20

Opción A: sacar el secreto del directorio personal

Cuando el servicio oculta /home y prefiere conservar esa protección, guarde el secreto en un lugar donde pueda verlo. El módulo acepta una ruta secret= y una cuenta user= que realiza las operaciones de archivos, lo que permite que un almacén central atienda muchas identidades.

Esta es la opción ordenada, y es la que necesita más cuidado, porque un almacén compartido convierte un solo directorio en la frontera de seguridad de cada cuenta.

auth required pam_google_authenticator.so secret=/var/lib/vpn-otp/${USER}/.google_authenticator user=vpn-otp

Compruebe tres cosas antes de confiar en ella: la cuenta existe, el trabajador del módulo puede cambiar a ella y los archivos son suyos con modos restrictivos. No use ~ ni una ruta con variable de directorio personal junto con user=, y no desactive las comprobaciones de propiedad del módulo para hacer que una ruta funcione. Mantenga la etapa de contraseña y el resto de la pila intactos.

Opción B: dejar el archivo y abrir una ruta

Si el secreto debe quedarse en el directorio personal del usuario, la unidad necesita una vista que incluya ese único directorio sin exponer todos los directorios personales del host. Un drop-in puede añadir un montaje de enlace muy limitado bajo un directorio personal aislado.

Esto mantiene la propiedad por usuario como modelo, a costa de un cambio en la unidad que debe revisarse siempre que cambie el entorno aislado.

Dos límites son fáciles de pasar por alto. Una ruta de solo lectura añadida bajo un directorio que el entorno aislado oculta no lo expone, porque el padre simplemente no está. Y el montaje debe ser escribible si el módulo tiene que actualizar el estado, lo que pone en juego la siguiente opción. Escriba el drop-in como un archivo separado en lugar de editar la unidad empaquetada bajo /usr/lib, para que una actualización del paquete no lo deshaga en silencio.

Opción C: mantener el entorno aislado y corregir las escrituras de estado

Leer el secreto es solo la mitad de la autenticación. El módulo puede reescribir información de desviación horaria, protección contra repetición o un contador, y un archivo que pasa la comprobación de lectura todavía puede fallar en la escritura.

Ese fallo parece un código incorrecto en el siguiente intento y no en este, por eso se confunde con una deriva del reloj.

Dele un directorio escribible propio y apunte allí la ruta del secreto, en lugar de hacer escribible todo el directorio personal. Confirme el propietario del directorio, el espacio libre del sistema de archivos y si la unidad restringe escrituras en otros lugares. Después pruebe dos inicios de sesión consecutivos, porque el segundo demuestra la ruta de escritura y el primero solo la de lectura.

Verifique como el servicio, no como usted mismo

Cada comprobación que importa debe ejecutarse dentro del entorno aislado de la unidad con la identidad de la unidad.

Un comando que tiene éxito como root le dice que el archivo existe y nada más. Un inicio de sesión por el servicio real le dice si el módulo puede leer el secreto, usarlo y escribir de vuelta lo que necesita.

Por último, mantenga el requisito intacto. Añadir una opción de contraseña nula, aceptar fallos de solo lectura o eliminar el entorno aislado harían desaparecer el síntoma cambiando la política. Un usuario obligado a presentar un código debe seguir siendo rechazado cuando el secreto es inalcanzable.

Artículos relacionados