11 mayo 2012

Autenticación mediante clave pública en SSH

El uso de claves públicas para acceder a servicios como SSH, SCP o SFTP, resulta una técnica más segura para autenticar dichos servicios que el esquema clásico de usuario y contraseña, al que estamos tan acostumbrados. Además, nos permite realizar una identificación automática y transparente, sin necesidad de tener que interaccionar, lo cual será de gran utilidad en la automatización de ciertas tareas rutinarias que, preferiblemente, deban realizarse de forma desatendida como por ejemplo la realización de copias de seguridad.

Algoritmos de cifrado

SSH permite crear claves usando los algoritmos RSA y DSA, pero… ¿cuál de ellos nos conviene más?
  • RSA: (de las siglas de sus autores, Rivest, Shamir y Adleman) Es un algoritmo asimétrico cifrador de bloques, que utiliza una clave pública, la cual se distribuye y otra privada, guardada en secreto por su propietario. Su funcionamiento reside en el uso de expresiones exponenciales dentro de la aritmética modular. Obteniendo una completa seguridad, debido a que aún no se conocen formas óptimas de factorizar un número grande en sus factores primos utilizando ordenadores personales. El RSA se basa en dos problemas matemáticos: el problema de factorizar números grandes y el problema RSA. El descifrado completo de un texto cifrado con RSA es computacionalmente intratable.
    Por otro lado la factorización de números grandes proponen métodos para longitudes de 600-700 bits de longitud. Y generalmente, las claves RSA usan entre 1024-2048 bits.
  • DSA: (Digital Signature Algorithm) es el algoritmo de firmado digital incluido en el DSS (Digital Signature Standard) del NIST Norteamericano. Está basado en el problema de los logaritmos discretos y únicamente puede emplearse para las firmas digitales (a diferencia del RSA, que puede emplearse también para encriptar). La elección de este algoritmo como estándar de firmado generó multitud de críticas puesto que perdía bastante flexibilidad respecto al RSA.
En general, se comprueba que el algoritmo DSA es más rápido para generar la firma que para verificarla, al contrario de lo que sucede con RSA. Por lo que, para realizar la autentificación en nuestro servidor SSH, usaremos este último. Además, si comparamos el tamaño de las llaves generadas por ambos algoritmos, comprobaremos que las utilizadas por RSA son superiores a las de DSA. Razones por las que nos decantaremos por usar el algoritmo RSA.

Configuración en el servidor

Vamos a comprobar que el equipo remoto tiene activada la versión 2 del protocolo SSH y, además, que tenga habilitada la opción para utilizar claves RSA. Para ello buscamos las siguientes directivas en el fichero de configuración del servidor SSH /etc/ssh/sshd_config:
Protocol 2
RSAAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
Para cada usuario que vaya a conectarse remotamente, debe de existir el directorio /home/nombre_usuario/.ssh/ y en él el archivo authorized_keys. En caso de no existir, deberemos crearlo de forma manual, asignarle los permisos correspondientes y, posteriormente, (re)iniciar el servidor.
$ cd ~
$ mkdir .ssh
$ chmod 600 .ssh/
$ touch .ssh/authorized_keys
$ sudo /etc/init.d/sshd start
Generación de los pares de claves RSA

Como antes comentamos, SSH nos permite generar indistintamente claves RSA o DSA (en nuestro caso usaremos claves RSA), creándose una clave pública y una clave privada.

Dichas claves, pueden generarse en el servidor, en la estación cliente, o en cualquier otra máquina.

Al final sólo la clave pública debe de aparecer en el fichero ~/.ssh/authorized_keys del servidor remoto.

Para generar el par de claves utilizaremos el comando ssh-keygen. Durante el proceso, se nos pedirá la introducción de una passphrase, lo que viene a ser una contraseña para poder generar unas claves más fuertes y seguras.

En nuestro caso, vamos a dejar la passphrase en blanco para que no nos la pida y, de ese modo, poder acceder al servidor remoto de forma desatendida.
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/nombre_usuario/.ssh/id_rsa):
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/nombre_usuario/.ssh/id_rsa.
Your public key has been saved in /home/nombre_usuario/.ssh/id_rsa.pub.
The key fingerprint is:
8d:34:58:47:33:4a:ff:98:bd:a8:a9:cc:65:ba:6c:02 nombre_usuario@mi_ordenador_portatil
The key's randomart image is:
+--[ RSA 2048]----+
|        o.=      |
|       + + o     |
|      . + .      |
|       . + =     |
|        S + o    |
|  E       . .    |
|   .    o . .    |
|    .+.+ o       |
|     oBoo        |
+-----------------+
Instalación de clave pública y protección de la clave privada

Una vez generado el par de claves, el siguiente paso es copiar la clave pública en el servidor (o los servidores) donde tengamos pensado autentificarnos a través de clave pública y guardar en un lugar seguro la clave privada.

Particularidades de las claves pública/privada

La misma clave pública nos puede servir para acceder a cualquier servidor. No hay que generar una nueva clave cada vez.


La clave privada debe de ser PRIVADA y debe custodiarse en un lugar seguro (típicamente, en ~/.ssh con los permisos adecuados para que solo pueda acceder el propietario de la clave).

Procedemos a copiar la clave pública al servidor remoto. Una vez realizada la copia, accedemos al servidor y comprobamos que los permisos de los ficheros authorized_keys y known_hosts sea la correcta:
$ ssh-copy-id usuario@host_remoto
usuario@host_remoto's password: 
Now try logging into the machine, with "ssh 'usuario@host_remoto'", and check in:

.ssh/authorized_keys

to make sure we haven't added extra keys that you weren't expecting.

$ ssh usuario@host_remoto
Last login: Fri May 11 13:46:05 2012 from 192.168.0.15
Linux host_remoto 2.6.32-5 #1 SMP Mon Jan 16 20:48:30 UTC 2012 x86_64 GNU/Linux

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.

$ ls -l .ssh/
total 8
-rw------- 1 usuario usuario 1226 May 11 14:39 authorized_keys
-rw-r--r-- 1 usuario usuario 2017 Nov 26  2011 known_hosts
Ahora nos encargamos de la clave privada que debe de estar en nuestro equipo. Forzamos que las claves sólo sean accesibles por su propietario.
$ chmod 600 ~/.ssh/{id_dsa,id_dsa.pub}
$ ls -l ~/.ssh/
total 48
-rw------- 1 usuario usuario   668 2012-05-11 14:38 id_dsa
-rw------- 1 usuario usuario   613 2012-05-11 14:38 id_dsa.pub
-rw-r--r-- 1 usuario usuario 37372 2012-05-07 11:31 known_hosts
Pasos finales

Una vez copiada la clave pública en el servidor y asegurado que podemos establecer una conexión remota, vamos a aumentar la seguridad del servidor remoto introduciendo algunos cambios en el fichero de configuración del servicio ssh (/etc/ssh/sshd_config). Impediremos la conexión con el usuario root y la autenticación mediante password.
PermitRootLogin no
PasswordAuthentication no
Para incrementar la seguridad del equipo remoto, es recomendable activar siempre la primera directiva. Con ella evitamos el acceso remoto como root. En este sentido, lo más seguro es acceder como usuario sin privilegios y, una vez ganado el acceso al sistema, cambiar a usuario root con los comandos su o sudo.

En cuanto a la segunda directiva, hay que tener en cuenta que impedirá que NINGÚN usuario pueda conectarse remotamente mediante usuario/contraseña. TODOS los usuarios remotos deberán validarse mediante su clave pública. A efectos prácticos, en algunos entornos, puede que esto no sea lo más recomendable.

2 comentarios:

Luirro dijo...

Qué implicancias tiene esto si se hace como root?? es decir, qué pasa si copio la clave publica del root en otro servidor??

Unknown dijo...

@Luirro
Una clave pública te identifica como usuario de un equipo.

Cuando copias esa clave pública a otro usuario de otro equipo distinto, lo que estás haciendo es permitir que el usuario1@equipo1 tenga acceso a la cuenta del usuario2@equipo2 (ya sea root o no).

Lógicamente, eso tiene alguna implicación de seguridad ya que si, por la razón que sea, se compromete la seguridad de cuenta del usuario1, también quedará comprometida la seguridad de la cuenta del usuario2. Y si además el usuario2 tiene permiso de root, peor que peor.

Espero que te haya servido la explicación.