No es desesperación, la desesperación es sólo para los que ven el final más allá de toda duda. Nosotros no lo hacemos…
Hace unos días, el buen Rod me comentó que tenía algunos problemas creando relaciones de confianza entre servidores utilizando llaves de SSH. La referencia obligada fueron dos posts anteriores: Mecanismos de confianza con llaves de SSH, donde compartí el procedimiento básico para generarlos, y Que hacer cuando algo falla, en caso de necesitar algún análisis de falla y poder encontrar la causa raíz de la misma, para solucionarla.
Sin embargo, después de varios días, el mecanismo seguía sin funcionar correctamente, por lo que hubo que analizar más a fondo el caso.
Escenario
El userA desde el serverA se debe conectar al serverB como el userB de forma automática sin contraseña.
Ambos servidores están instalados igual, en el mismo segmento. La única diferencia entre ellos, era que el home de userB en serverB se encontraba bajo /opt.
Primer Análisis
De inicio, no obviamos nada y revisamos lo básico:
En serverA
- Que exista la llave privada
- El contenido de la llave pública sea una sola línea y sea el mismo en el serverB
[userA@serverA ~]$ ls -la .ssh/ total 20 drwx------. 2 userA userA 4096 Dec 11 10:32 . drwx------. 3 userA userA 4096 Dec 11 11:08 .. -rw-------. 1 userA userA 1675 Dec 11 10:32 id_rsa -rw-r--r--. 1 userA userA 410 Dec 11 10:32 id_rsa.pub -rw-r--r--. 1 userA userA 796 Dec 11 19:24 known_hosts [userA@serverA ~]$ wc -l .ssh/id_rsa.pub 1 .ssh/id_rsa.pub [userA@serverA ~]$ cat .ssh/id_rsa.pub ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAz59j3eSrdkgnQPvYpiFXL3EVqdgCE8Q7v4hFfCzORxXxSprXNpZW18L2BkEfo5P/JO//qGTyFSMrZbqRHAm6s7PR/idWbSGtZfXLt3ri5Rw4OUyLcDrXVqzhbBo3bvSADksXXYVcjDu2h0P8p70EOc1mouRsOph5bE0l4Yk2/RYZ6JfMI8DDbtpU/nKfPfdsysjeLQwOJ7XiXrKWwnqSZ+rP3Irol336RkPrgMpoQDzenkoMiAkc68cUYy1K85k1kv34gxWLFYK9riiXp4OriUFm62z7Fx2jaeDNPbLndDOBzCcm65P4b2j8K5vv8MshJtddWUypen+cB34lH7rjbw== userA@serverA.example-rh.com
En serverB
- Que los permisos del home de userB sean 700 y exclusivos del dueño
- La llave pública se llame authorized_keys, en una sola línea y con el mismo contenido que en el serverA
[userB@clientB ~]$ ls -ld ~/ drwx------. 3 userB userB 4096 Dec 11 19:20 /opt/userB/ [userB@clientB ~]$ ls -la .ssh/ total 16 drwx------. 2 userB userB 4096 Dec 11 19:20 . drwx------. 3 userB userB 4096 Dec 11 19:20 .. -rw-------. 1 userB userB 410 Dec 11 19:20 authorized_keys -rw-r--r--. 1 userB userB 391 Dec 11 19:18 known_hosts [userB@clientB ~]$ wc -l .ssh/authorized_keys 1 .ssh/authorized_keys [userB@clientB ~]$ cat .ssh/authorized_keys ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAz59j3eSrdkgnQPvYpiFXL3EVqdgCE8Q7v4hFfCzORxXxSprXNpZW18L2BkEfo5P/JO//qGTyFSMrZbqRHAm6s7PR/idWbSGtZfXLt3ri5Rw4OUyLcDrXVqzhbBo3bvSADksXXYVcjDu2h0P8p70EOc1mouRsOph5bE0l4Yk2/RYZ6JfMI8DDbtpU/nKfPfdsysjeLQwOJ7XiXrKWwnqSZ+rP3Irol336RkPrgMpoQDzenkoMiAkc68cUYy1K85k1kv34gxWLFYK9riiXp4OriUFm62z7Fx2jaeDNPbLndDOBzCcm65P4b2j8K5vv8MshJtddWUypen+cB34lH7rjbw== userA@serverA.example-rh.com
Al comparar el md5 de ambos archivos de llave pública daba el mismo hash:
b02e3cc11c58c8ba36677316bf52ed74 .ssh/id_rsa.pub b02e3cc11c58c8ba36677316bf52ed74 .ssh/authorized_keys
Sin embargo, al hacer pruebas, el mecanismo de confianza no funcionaba:
[userA@serverA ~]$ ssh userB@serverB hostname userB@serverb's password: [userA@serverA ~]$ ssh -v userB@serverB hostname OpenSSH_5.3p1, OpenSSL 1.0.1e-fips 11 Feb 2013 ... debug1: Next authentication method: publickey debug1: Trying private key: /home/userA/.ssh/identity debug1: Offering public key: /home/userA/.ssh/id_rsa debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password debug1: Trying private key: /home/userA/.ssh/id_dsa debug1: Trying private key: /home/userA/.ssh/id_ecdsa debug1: Next authentication method: password userB@serverb's password: [userA@serverA ~]$
Al revisar /var/log/messages y /var/log/secure no se encontraba evidencia alguna de la falla:
[root@clientB ~]# tail -f /var/log/messages /var/log/secure ==> /var/log/messages <== Dec 12 12:33:30 clientB kernel: type=1305 audit(1418409210.149:4): audit_pid=952 old=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:auditd_t:s0 res=1 Dec 12 12:33:30 clientB kdump: No crashkernel parameter specified for running kernel ==> /var/log/secure <== Dec 12 12:33:31 clientB sshd[1050]: Server listening on 0.0.0.0 port 22. Dec 12 12:33:31 clientB sshd[1050]: Server listening on :: port 22. Dec 12 12:33:40 clientB sshd[1192]: Accepted password for root from 192.168.122.1 port 40110 ssh2 Dec 12 12:33:41 clientB sshd[1192]: pam_unix(sshd:session): session opened for user root by (uid=0) Dec 12 12:54:30 clientB sshd[1212]: Connection closed by 192.168.122.110 Dec 12 12:54:38 clientB sshd[1214]: Connection closed by 192.168.122.110 ^C [root@clientB ~]#
Segundo Análisis
Entonces revisamos la configuración de ssh, /etc/ssh/sshd_config, y lo modificamos para que sólo permita autenticación por llave y amarramos el nombre de la misma como authorized_keys2, para tratar de delimitar la falla:
[root@clientB ~]# cat /etc/ssh/sshd_config | grep ^[A-Z] Protocol 2 SyslogFacility AUTHPRIV AuthorizedKeysFile %h/.ssh/authorized_keys2 PasswordAuthentication no ChallengeResponseAuthentication no GSSAPIAuthentication no GSSAPICleanupCredentials yes UsePAM yes AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE AcceptEnv XMODIFIERS X11Forwarding yes Subsystem sftp /usr/libexec/openssh/sftp-server [root@clientB ~]#
Generamos otra llave, de tipo dsa, y la copiamos en el serverB como authorized_keys2:
[userA@serverA ~]$ ssh-keygen -t dsa -b 1024 [userA@serverA ~]$ cat .ssh/id_dsa.pub ssh-dss AAAAB3NzaC1kc3MAAACBAOpcPejQC+G/jRz3v9gUhaJy/CogjtOmXQG9zoL69pIOhKcMfjJy21GED49tS9kAw857WTpjEVzF3ssLJlS2LMqxIervQ/bsaH8WKSqUvueTMOw/4+fiwECbllCPE/g/ULozqJFssDUJlNdTAc+yA6qVbldqT69HVbNjyWeZc3dbAAAAFQDKiDJ5GwkZLiuXbYcJaElS881GtQAAAIEApXBcAfXHfewuQiHLHrBvnd0SePgjJmU8bUgfjWjwu4yoT4Z1aWy+FmtYoQGfc9SUHq4/u6EhwVUz9i7UXLW+WrEA+OtsAftEo0TjKjG8OeH4igcqsoSkosrj2QxLrf6I8l6YQnVIt5ufVtLoE4ZqCVrLtTnsS4elFeaR56hKKT8AAACAA83nEJaqK9tWm3k8RJQJZB5sEY/DAI0ZYd/TTtCKWIOXACz+G0iK+jj1JZtV40gZyJKzIFoD89FJh3RV8PZp1+UosK4kBYsxtP4WXvUjkhwVzh6PPu8A1/BJeEq/RvCqwBPinCY0rnAQrGwLCocMNkpnJxyqjg6ZLu2bsQo1HvE= userA@serverA.example-rh.com [userA@serverA ~]$ [userB@clientB ~]$ cat .ssh/authorized_keys2 ssh-dss AAAAB3NzaC1kc3MAAACBAOpcPejQC+G/jRz3v9gUhaJy/CogjtOmXQG9zoL69pIOhKcMfjJy21GED49tS9kAw857WTpjEVzF3ssLJlS2LMqxIervQ/bsaH8WKSqUvueTMOw/4+fiwECbllCPE/g/ULozqJFssDUJlNdTAc+yA6qVbldqT69HVbNjyWeZc3dbAAAAFQDKiDJ5GwkZLiuXbYcJaElS881GtQAAAIEApXBcAfXHfewuQiHLHrBvnd0SePgjJmU8bUgfjWjwu4yoT4Z1aWy+FmtYoQGfc9SUHq4/u6EhwVUz9i7UXLW+WrEA+OtsAftEo0TjKjG8OeH4igcqsoSkosrj2QxLrf6I8l6YQnVIt5ufVtLoE4ZqCVrLtTnsS4elFeaR56hKKT8AAACAA83nEJaqK9tWm3k8RJQJZB5sEY/DAI0ZYd/TTtCKWIOXACz+G0iK+jj1JZtV40gZyJKzIFoD89FJh3RV8PZp1+UosK4kBYsxtP4WXvUjkhwVzh6PPu8A1/BJeEq/RvCqwBPinCY0rnAQrGwLCocMNkpnJxyqjg6ZLu2bsQo1HvE= userA@serverA.example-rh.com [userB@clientB ~]$
Sin embargo, la falla seguía presentándose:
[userA@serverA ~]$ ssh -v userB@serverB hostname ... debug1: Offering public key: /home/userA/.ssh/id_rsa debug1: Authentications that can continue: publickey debug1: Offering public key: /home/userA/.ssh/id_dsa debug1: Authentications that can continue: publickey debug1: Trying private key: /home/userA/.ssh/id_ecdsa debug1: No more authentication methods to try. Permission denied (publickey). [userA@serverA ~]$
Aumentamos el nivel de log de sshd:
[root@clientB ~]# grep LogLevel /etc/ssh/sshd_config LogLevel DEBUG [root@clientB ~]#
Al hacer pruebas, continúa la falla, pero el /var/log/secure ya nos daba indicios de lo que estaba sucediendo:
[userA@serverA ~]$ ssh userB@serverB hostname Permission denied (publickey). [userA@serverA ~]$ [root@clientB ~]# tail /var/log/secure Dec 12 15:40:29 clientB sshd[1432]: debug1: trying public key file /opt/userB/.ssh/authorized_keys2 Dec 12 15:40:29 clientB sshd[1432]: debug1: Could not open authorized keys '/opt/userB/.ssh/authorized_keys2': Permission denied Dec 12 15:40:29 clientB sshd[1432]: Failed publickey for userB from 192.168.122.1 port 40376 ssh2 Dec 12 15:40:29 clientB sshd[1433]: Connection closed by 192.168.122.1 Dec 12 15:40:29 clientB sshd[1433]: debug1: do_cleanup Dec 12 15:40:29 clientB sshd[1432]: debug1: PAM: cleanup [root@clientB ~]#
Revisamos los permisos especiales, y validamos las opciones de montado del filesystem:
[root@clientB ~]# lsattr /opt/userB/ [root@clientB ~]# [root@clientB ~]# getfacl /opt/userB/ getfacl: Removing leading '/' from absolute path names # file: opt/userB/ # owner: userB # group: userB user::rwx group::--- other::--- [root@clientB ~]# df -hP /opt/userB Filesystem Size Used Avail Use% Mounted on /dev/mapper/vg_opt-userB_home 988M 1.3M 936M 1% /opt/userB [root@clientB ~]# [root@clientB ~]# tune2fs -l /dev/mapper/vg_opt-userB_home | grep -i options Default mount options: (none) [root@clientB ~]#
Tercer Análisis
Al no encontrar indicios en los permisos básicos y extendidos, procedimos a revisar los permisos desde el punto de vista de seguridad:
[root@serverA ~]# getenforce Enforcing [root@serverA ~]# ls -lZd /home/userA/ drwx------. userA userA unconfined_u:object_r:user_home_dir_t:s0 /home/userA/ [root@serverA ~]# [root@clientB ~]# getenforce Enforcing [root@clientB ~]# ls -lZd /opt/userB/ drwx------. userB userB system_u:object_r:file_t:s0 /opt/userB/ [root@clientB ~]#
Al parecer, teníamos diferencia en los contextos de SELinux; entonces realizamos una prueba, deshabilitando momentáneamente la seguridad:
[root@clientB ~]# setenforce 0 [root@clientB ~]# [root@clientB ~]# getenforce Permissive [root@clientB ~]# [userA@serverA ~]$ ssh userB@serverB hostname clientB.example-rh.com [userA@serverA ~]$
Al deshabilitar SELinux la conexión se realizaba de forma exitosa; sin embargo, era un requisito del cliente tenerlo habilitado.
Para conocer exactamente el comando a ejecutar y restablecer el contexto correctamente; instalamos setroubleshoot, esta herramienta nos ayuda a diagnosticar los problemas con SELinux a partir de las alertas AVC generadas en el log de audit y las parsea para entregarnos información legible en /var/log/messages. Al hacer pruebas, encontramos dicho mensaje:
[root@clientB ~]# yum -y install setroubleshoot ... [root@clientB ~]# [root@clientB ~]# setenforce 1 [root@clientB ~]# [root@clientB ~]# getenforce Enforcing [root@clientB ~]# [userA@serverA ~]$ ssh userB@serverB hostname Permission denied (publickey). [userA@serverA ~]$ [root@clientB ~]# tail /var/log/messages Dec 12 16:56:32 clientB kernel: type=1305 audit(1418424992.590:4): audit_pid=952 old=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:auditd_t:s0 res=1 Dec 12 16:58:26 clientB setroubleshoot: SELinux is preventing /usr/sbin/sshd from search access on the directory /opt/userB. For complete SELinux messages. run sealert -l f963dd2e-ab81-4c3a-99ad-4d4d1e6736d5 [root@clientB ~]#
Al ejecutar el comando recomendado, éste nos decía:
[root@clientB ~]# sealert -l f963dd2e-ab81-4c3a-99ad-4d4d1e6736d5 SELinux is preventing /usr/sbin/sshd from search access on the directory /opt/userB. ***** Plugin restorecon (82.4 confidence) suggests ************************* If you want to fix the label. /opt/userB default label should be usr_t. Then you can run restorecon. Do # /sbin/restorecon -v /opt/userB ... [root@clientB ~]#
Ejecutamos la recomendación:
[root@clientB ~]# ls -lZd /opt/userB/ drwx------. userB userB system_u:object_r:file_t:s0 /opt/userB/ [root@clientB ~]# [root@clientB ~]# restorecon -v /opt/userB restorecon reset /opt/userB context system_u:object_r:file_t:s0->system_u:object_r:usr_t:s0 [root@clientB ~]# [root@clientB ~]# ls -lZd /opt/userB/ drwx------. userB userB system_u:object_r:usr_t:s0 /opt/userB/ [root@clientB ~]#
Y al hacer pruebas:
[userA@serverA ~]$ ssh userB@serverB hostname clientB.example-rh.com [userA@serverA ~]$
Causa Raíz
El home del usuario esta montado en un volumen sobre /opt, realizamos una prueba, desmontando el volumen y revisando el contexto del directorio y encontramos:
[root@clientB ~]# umount /opt/userB/ [root@clientB ~]# [root@clientB ~]# ls -lZd /opt/userB/ drwx------. userB userB system_u:object_r:usr_t:s0 /opt/userB/ [root@clientB ~]#
Lo que nos indica que, cuando el usuario fue creado, al montar el volumen no se restablecieron los contextos de su home.
Gracias Rod por la confianza! fue un gusto apoyarte a resolver este caso y poder compartir la experiencia.
Espero les sirva…