Utilizando SSH
Criptografía pública
OpenSSH dispone de varios métodos para verificar la identidad
de un usuario remoto, uno de ellos es el uso de contraseñas de
usuarios, pero otro de los métodos se basa en la autenticación
RSA, en donde se dispone de un juego de llaves privada/pública
que garantiza la identidad de un usuario intentando conectarse
al equipo remoto. El juego de llaves tiene la propiedad de que
lo que se encripta con una, sólo se puede desencriptar con la
otra, pero sin embargo, a partir de la llave pública no se
puede derivar la llave privada.
Para asegurarse de que un usuario es quien dice ser por medio
de criptografía pública OpenSSH emplea el siguiente procedimiento:
Primero, el servidor genera un número aleatorio que encripta
con la llave pública del usuario y le envia el resultado al
cliente, si el usuario es quien dice ser entonces no tendrá
ningún problema en desencriptarlo. El cliente aplicará una
transformación predefinida a dicho número y lo enviará de
vuelta al servidor, el cual, revisará dicho resultado y de
ser correcto, dará acceso al cliente.
Un sistema parecido al anterior es el que se emplea también
para verificar que el servidor al que se está conectando es
el correcto y no estamos siendo victimas de un ataque de
tipo Monkey In the Middle.
Configurar el servidor para que acepte llaves públicas.
Para poder trabajar con llaves públicas, lo primero que tendremos
que hacer será configurar el servidor de SSH para que las acepte.
Habitualmente los archivos de configuración de OpenSSH se ubican
en la carpeta /etc/ssh, en este caso, el archivo que
nos interesa es /etc/ssh/sshd_config, lo abrimos con
un editor de textos y corregimos los valores de las siguientes
opciones relacionadas con las llaves públicas:
#RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
La primera opción (RSAAuthentication) sirve para indicar
cuando se permitirá autenticación RSA, está opción esta habilitada
por defecto, y en el ejemplo está comentada porque sólo sirve para
la versión 1 del protocolo SSH.
La segunda opción (PubkeyAuthentication) es la que
especifica si se podrán usar llaves públicas para demostrar la
autenticidad de un usuario. Si su valor es yes como
en el ejemplo, entonces se podrán emplear las llaves públicas,
si por el contrario su valor es no, entonces el uso
de llaves públicas quedará prohibido.
La tercera opción (AuthorizedKeysFile) especifica el
archivo que contiene las llaves públicas empleadas para la
autenticación de los usuarios. Por defecto suele ser el archivo
.ssh/autorized_keys, dentro de la carpeta personal
de cada usuario.
Finalmente, en caso de haber alterado el archivo de configuración
del servidor, para que los cambios sean efectivos, será necesario
reiniciar el servidor de SSH.
Crear nuevas llaves
Para poder crear nuevas llaves privadas y sus correspondientes
llaves públicas, OpenSSH dispone de una herramienta llamada
ssh-keygen, esta herramienta puede crear llaves RSA
para el protocolo SSH versión 1, cuyo uso se desaconseja y aquí
no se va a hablar de ellas, por otro lado, también puede generar
llaves RSA o DSA para el protocolo SSH versión 2. Para especificar
que tipo de llave crear, se emplea el parámetro -t
seguido del tipo de llave: "rsa" o "dsa". Por ejemplo, para crear
una llave RSA podemos poner:
[hell@local] $ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/hell/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/hell/.ssh/id_rsa.
Your public key has been saved in /home/hell/.ssh/id_rsa.pub.
The key fingerprint is:
c0:40:50:27:e8:d9:b8:55:d6:a4:5f:af:e5:30:5d:9b hell@local
[hell@local] $
Por el contrario, para generar una llave DSA, simplemente:
[hell@local] $ ssh-keygen -t dsa
Generating public/private dsa key pair.
Enter file in which to save the key (/home/hell/.ssh/id_dsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/hell/.ssh/id_dsa.
Your public key has been saved in /home/hell/.ssh/id_dsa.pub.
The key fingerprint is:
f5:b2:f3:2d:43:1b:22:44:98:6c:fe:42:df:a3:15:09 hell@local
[hell@local] $
Los anteriores comandos piden los mismos datos, el primero, en
donde salvar la llave privada, si simplemente pulsamos intro,
se salvará en la ruta por defecto (la indicada entre paréntesis),
a no ser que emplees varias llaves privadas, la ruta por defecto
es una buena opción, ya que el cliente la usará sin necesidad de
que el usuario tenga que especificarla.
Las siguientes dos cosas que pide son la frase clave con la que
encriptar la llave privada y una petición de que se repita la
frase para cerciorarse de que no se han cometido errores al
escribirla la primera vez. Para la frase con la que encriptar
la llave privada se puede emplear cualquier carácter (letras,
numeros, signos de puntuación, espacios), en principio el tamaño
de la frase puede ser arbitrario, pero ssh-keygen se quejará si
es menor de cuatro carácteres. En caso de no introducir ninguna
frase, la llave privada quedará sin encriptar, lo cual podria
ser útil para realizar algunas automatizaciones como podría ser
el realizar copias de seguridad, pero, para uso habitual, se
desaconseja dejar las llaves privadas sin encriptar por el
peligro que puede representar que estas sean robadas.
A continuación el ssh-keygen muestra donde se ha salvado la
llave privada (/home/hell/.ssh/id_dsa) y donde está la llave
pública que le corresponde (/home/hell/.ssh/id_dsa.pub), que
no es más que el mismo nombre de archivo con la extensión
.pub añadida al final.
En la última línea imprime una huella dactilar que sirve para
identificar la llave que acabamos de crear, seguida de un
comentario que puede servir para identificar la llave pública.
Añadir llaves públicas a authorized_keys
Despues de haber creado un juego de llaves privada y pública,
nos encontramos con el dilema de que hacer con ellas, lo primero
es mantener la llave privada secreta, por defecto ssh-keygen
establecerá los permisos del archivo con esta llave para que
sólo el dueño pueda leerla y modificarla. Por el contrario
la llave pública podrá ser leida por cualquier usuario, pues
por algo es pública.
Pero para poder autenticarnos en un equipo remoto con nuestra
llave privada, lo único que tendremos que hacer es añadir nuestra
llave pública en el archivo .ssh/authorized_keys dentro
del directorio personal del usuario al que queremos acceder
(generalmente $HOME/.ssh/authorized_keys).
El primer dilema que se nos plantea es el cómo enviamos nuestra
llave pública al equipo remoto, una forma, en caso de que podamos
acceder a el usando SSH con contraseñas de usuario para autenticarnos,
sería mediante SCP, a modo de ejemplo, imaginemos que despues de
crear el juego de llaves tenemos lo siguiente en nuestro directorio
.ssh:
[hell@local] $ ls -1 ~/.ssh
id_rsa
id_rsa.pub
[hell@local] $
No es más que un juego de llaves RSA, ahora la máquina remota
donde queremos instalar nuestra llave se llama
remoto.ejemplo.com, y la cuenta de usuario es la
misma que la que estamos empleando en el sistema que estamos
utilizando, entonces podríamos poner:
[hell@local] $ scp ~/.ssh/id_rsa.pub remoto.ejemplo.com:mi_llave.pub
hell@remoto.ejemplo.com's password:
id_rsa.pub 100% 398 0.4KB/s 00:00
[hell@local] $
De esta manera en la máquina remota tendremos el archivo
mi_llave.pub que contiene nuestra llave pública, ahora
tan sólo nos resta crear el directorio .ssh, en caso de que no
exista, y añadir la llave pública al archivo
$HOME/.ssh/authorized_keys, para ello, podemos conectarnos
mediante SSH y usar el comando cat. Una sesión SSH a modo de
ejemplo sería la siguiente:
[hell@local] $ ssh ejemplo.remoto.com
hell@remoto.ejemplo.com's password:
[hell@remoto] $ mkdir .ssh
[hell@remoto] $ chmod 700 .ssh
[hell@remoto] $ cd .ssh
[hell@remoto] $ cat ../my_llave.pub >> authorized_keys
[hell@remoto] $
Ahora, la próxima vez que nos conectemos al servidor
remoto.ejemplo.com, en lugar de pedirnos la contraseña
del usuario, nos pedira la frase clave con la que la encriptamos
nuestra llave privada:
[hell@local] $ ssh ejemplo.remoto.com
Enter passphrase for key '/home/hell/.ssh/id_rsa':
[hell@remoto] $
Trabajar con varias llaves públicas
A veces se puede dar el caso de que dispongamos de varias llaves
para autenticarnos, los motivos pueden ser diversos, como por
ejemplo que nuestra llave habitual no nos permita redireccionar
puertos en la máquina remota, o, por el contrario, que una llave
pública ejecuta automáticamente un proceso para hacer copias de
seguridad, también existe la posibilidad de que nuestra llave
habitual este restringida y necesitemos usar otra que no lo
este.
Sea cual sea la causa por la que tenemos que emplear otra llave,
la manera de hacerlo es mediante el parámetro -i
seguido del archivo que contiene la llave privada a emplear.
A modo de ejemplo, supongamos que la máquina a la que queremos
conectar se llama remoto.ejemplo.com y que la llave
que vamos a emplear está en el archivo llave_acceso1.key,
un comando como el siguiente sería suficiente:
[hell@local] $ ssh -i llave_acceso1.key ejemplo.remoto.com
Enter passphrase for key 'llave_acceso1.key':
[hell@remoto] $
Tamaño de las llaves públicas
Por defecto, ssh-keygen genera llaves de 2048 bits, cuanto más
grande sea una llave, más segura será. En la actualidad, ssh-keygen
admite que las llaves tengan un mínimo de 512 bits y aunque en
la página del manual no se indique, el máximo son 32768 bits, pero
este último valor podría cambiar a medida que la potencia de los
equipos informáticos se incremente. No obstante, con la liberación
de la versión 4.3 de OpenSSH, sus desarrolladores decidieron fijar
el tamaño de las llaves DSA a 1024 bits, pudiendo alterarse tan
sólo el tamaño para las llaves RSA.
Por lo general el número de bits para la llave que escoge ssh-keygen
por defecto es suficiente, pero para quienes prefieran otros valores,
se puede especificar el tamaño de la llave con el parámetro
-b seguido del número de bits que se desea que tenga la
llave. Un ejemplo para generar una llave RSA de 4096 bits podría ser
el siguiete:
[hell@local] $ ssh-keygen -t rsa -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (/home/hell/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/hell/.ssh/id_rsa.
Your public key has been saved in /home/hell/.ssh/id_rsa.pub.
The key fingerprint is:
4b:29:23:e9:20:c1:e5:32:6e:fa:b4:91:9a:01:b5:10 hell@local
[hell@local] $
Comentarios de las llaves públicas
En el momento de su creación, ssh-keygen nos permite añadir
un comentario a las claves públicas, por defecto el comentario
que pone es del tipo usuario@máquina, pero podemos
emplear el parámetro -C seguido del comentario que
queramos, para así diferenciar más facilmente nuestra llave
pública del resto de llaves. A modo de ejemplo, supongamos que
queremos crear una clave de pruebas de tipo RSA con el comentario
"Clave de pruebas":
[hell@local] $ ssh-keygen -t rsa -C "Clave de pruebas"
Generating public/private rsa key pair.
Enter file in which to save the key (/home/hell/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/hell/.ssh/id_rsa.
Your public key has been saved in /home/hell/.ssh/id_rsa.pub.
The key fingerprint is:
97:47:90:2d:b6:d9:ab:6d:91:41:ed:ad:dc:fb:a0:64 Clave de pruebas
[hell@local] $
Cambiar la frase clave de una llave privada
En alguna ocasión nos veremos en la necesidad de querer cambiar
la frase con la que una llave privada fue encriptada, o en el caso
de que la llave privada no estubiese encriptada, querer
encriptarla. Para conseguir este objetivo podemos invocar al
programa ssh-keygen con el parámetro -p, veamos un
ejemplo:
[hell@local] $ ssh-keygen -p
Enter file in which the key is (/home/hell/.ssh/id_rsa):
Enter old passphrase:
Key has comment '/home/hell/.ssh/id_rsa'
Enter new passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved with the new passphrase.
[hell@local] $
En primer lugar nos pide la frase con la que está encriptada
(old passphrase), a continuación, nos pide que introduzcamos
la nueva frase (new passphrase), entre paréntesis, nos indica
que si no ponemos nada, la llave privada quedará sin encriptar
(empty for no passphrase). Después nos pide que repitamos la
frase, para asegurarse de que no hemos cometido errores al
escribirla la primera vez y finalmente, graba la llave privada
encriptada con la nueva frase.