index
RECURSOS GRATUITOS, CIBERACTIVISMO
  Navegación-> Inicio | Hellguest | SSH | Agente SSH
SSH
Introducción
El cliente de SSH
Copiando archivos con SCP
Criptografía pública
Agente SSH
Túneles SSH

Utilizando SSH

Agente SSH

Una de las ventajas de emplear llaves públicas frente al uso de contraseñas de usuario es que no tenemos que recordar nada más que una única frase, la frase con la que hemos cifrado nuestra llave privada. Eso es un avance, pero OpenSSH dispone de una herramienta que nos puede evitar el trámite de tener que andar escribiendo dicha frase cada vez que establezcamos una nueva conexión. Esta herramienta se llama ssh-agent y tiene la capacidad de recordar las llaves privadas que tenemos.

Al ejecutar el agente ssh (ssh-agent), este crea un socket UNIX y establece la variable de entorno SSH_AUTH_SOCK con el nombre del socket. Por razones de seguridad los permisos del socket son ajustados para que tan sólo el usuario actual pueda acceder al socket. Además, el agente también crea la variable de entorno SSH_AGENT_PID y establece su valor con su PID (identificador de programa).

Cuando el cliente de SSH necesita autenticar a un usuario, lo primero que hace es mirar si existe la variable de entorno SSH_AUTH_SOCK, de ser así, la usa para establecer una conexión con el agente, el agente no le pasa la llave privada al cliente de SSH, sino que es el propio agente el que se encarga de realizar la autenticación, de forma que la llave privada nunca sea expuesta a los clientes.

Iniciando el agente

Actualmente hay varias formas de cargar el agente, una de ellas es poniendo simplemente ssh-agent en la línea de comandos:

[hell@local] $ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-nfxOw32113/agent.32113; export SSH_AUTH_SOCK;
SSH_AGENT_PID=32114; export SSH_AGENT_PID;
echo Agent pid 32114;
[hell@local] $

La salida anterior se corresponde a una shell Bourne y no es más que los comandos que habría que ejecutar para establecer las variables de entorno SSH_AUTH_SOCK y SSH_AGENT_PID, en el caso de emplear una shell derivada del csh la salida sería ligeramente distinta. El programa ssh-agent intenta averiguar el tipo de shell que se está usando, no obstante, se le puede pasar la opción -c para indicar una shell derivada de csh, o la opción -s para que muestre los comandos apropiados para una shell derivada del Bourne. Por ejemplo, para especificarle que estamos usando una shell csh:

[hell@local] $ ssh-agent -c
setenv SSH_AUTH_SOCK /tmp/ssh-hLBzi32149/agent.32149;
setenv SSH_AGENT_PID 32150;
echo Agent pid 32150;
[hell@local] $

El inconveniente de invocar el comando ssh-agent de la anterior manera está en que tenemos que establecer las variables de entorno manualmente, copiando y pegando, o escribiéndolas a mano, pero para hacerlo más cómodo, podemos emplear el comando eval de la siguiente forma:

[hell@local] $ eval `ssh-agent`
Agent pid 32171
[hell@local] $

De esa manera, logramos que la salida de ssh-agent se evalúe, quedando las variables de entorno establecidas. Podemos verificarlo así:

[hell@local] $ set | grep SSH
SSH_AGENT_PID=32174
SSH_AUTH_SOCK=/tmp/ssh-QUpBw32173/agent.32173
[hell@local] $

La otra manera de iniciar el agente es especificándole un programa a ejecutar, de forma que el agente establecerá las variables de entorno y ejecutará el programa, por ejemplo, para iniciar una shell csh con el agente:

[hell@local] $ ssh-agent bash
local:hell {1} env | grep SSH
SSH_AUTH_SOCK=/tmp/ssh-DBKNN10192/agent.10192
SSH_AGENT_PID=1921
local:hell {2} exit
[hell@local] $

También, por ejemplo, se puede ejecutar con el agente una terminal xterm:

[hell@local] $ ssh-agent xterm

Añadir llaves al agente

El agente nada más iniciarse no contiene ninguna llave, para agregarlas se emplea la herramienta ssh-add, si se ejecuta sin argumentos intenta añadir los archivos ~/.ssh/id_rsa, ~/.ssh/id_dsa y ~/.ssh/identity:

[hell@local] $ ssh-add
Enter passphrase for /home/hell/.ssh/id_rsa:
Identity added: /home/hell/.ssh/id_rsa (/home/hell/.ssh/id_rsa)
Identity added: /home/hell/.ssh/id_dsa (/home/hell/.ssh/id_dsa)
[hell@local] $

En el caso anterior ssh-add primero encuentra el archivo ~/.ssh/id_rsa y pide la frase con la que está cifrada la llave que contiene, entonces añade dicha llave al agente, después, localiza el archivo ~/.ssh/id_dsa que contiene otra llave, pero al estar cifrada con la misma frase que la primera llave, no vuelve a pedir la frase, si no que la descifra y la añade directamente al agente.

Si lo que queremos es añadir otra llave distinta a las tres que busca por defecto, lo único que tenemos que hacer es pasar el archivo con la llave como parámetro de ssh-add. Por ejemplo, para añadir una llave llamada millave.key:

[hell@local] $ ssh-add millave.key
Enter passphrase for millave.key: 
Identity added: millave.key (millave.key)
[hell@local] $

Listar las llaves que hay en el agente

En caso de querer ver que llaves contiene el agente, podemos pasarle la opción -l a la herramienta ssh-add, y obtendremos una salida como la siguiente:

[hell@local] $ ssh-add -l
2048 1f:2b:61:83:c7:f8:27:73:4d:03:0a:92:40:da:b8:bb /home/hell/.ssh/id_rsa (RSA)
1024 78:f2:ac:c0:0b:80:57:e7:fb:98:05:cd:1e:36:69:84 /home/hell/.ssh/id_dsa (DSA)
2048 d1:a7:cb:de:1b:bf:ef:04:04:2f:33:fc:31:f3:80:b3 millave.key (DSA)
[hell@local] $

Cada línea representa una llave. La primera columna muestra el tamaño en bits de la llave, la segunda se corresponde con la huella dactilar de la llave, la tercera columna es el archivo que contiene la llave y la última columna, indica entre paréntesis el tipo de llave que es, RSA o DSA.

También se puede emplear la opción -L que mostrará las llaves públicas, lo cual puede ser útil para añadirlas al archivo authorized_keys de una máquina remota.

[hell@local] $ ssh-add -L
ssh-rsa AAAAB3NzaC1...XnFBZjRf8cqDbugZRVeHYGvRqrNdv/9w== /home/hell/.ssh/id_rsa
ssh-dss AAAAB3NzaC1...6GRYhh2JxuPcr9kwlD7ZUjFrgElDFrng== /home/hell/.ssh/id_dsa
ssh-dss AAAAB3NzaC1...ZumWVFBO5E+fhyaZegOb8Rsz08J8LxOQ== millave.key
[hell@local] $

Nota: Cada llave aparece en una línea, pero como cada línea es muy larga, he eliminado parte del contenido de la llave pública, sustituyéndolo por puntos suspensivos para que así quepa bien en la pantalla.

Eliminar llaves del agente

También podemos eliminar llaves del agente empleando la herramienta ssh-add con la opción -d seguida de la llave pública que le corresponde a la llave privada que queremos que el agente borre de su memoria. Por ejemplo, para que olvide nuestra llave RSA:

[hell@local] $ ssh-add -d .ssh/id_rsa
Identity removed: .ssh/id_rsa (.ssh/id_rsa.pub)
[hell@local] $

No obstante, también podemos eliminar todas las llaves que tenga el agente empleando la opción -D, ejemplo:

[hell@local] $ ssh-add -D
All identities removed.
[hell@local] $

Bloquear el agente

Cuando no necesitamos usar el agente, pero no queremos que se olvide de nuestras llaves, como en el caso de dejar el equipo en el que estamos trabajando para ir a tomar un cafetín, podemos optar por bloquear el agente, para ello tan sólo hace falta pasarle la opción -x a la herramienta ssh-add, la cual nos pedirá una contraseña con la que luego podremos desbloquear el agente:

[hell@local] $ ssh-add -x
Enter lock password: 
Again: 
Agent locked.
[hell@local] $

Luego, cuando necesitemos volver a usar el agente, podemos desbloquearlo ejecutando la herramienta ssh-add con la opción -X, ssh-add entonces nos pedirá la contraseña para desbloquear el agente:

[hell@local] $ ssh-add -X
Enter lock password: 
Agent unlocked.
[hell@local] $

Reenviar el agente

Probablemente más de una vez tengamos que acceder a un equipo remoto que se encuentra dentro de una red privada (LAN), pero tendremos que hacerlo a través de un router, primero conectando al router, y después conectando al equipo remoto. Estableciendo así dos conexiones, una entre el equipo local y el router, y la otra entre el router y el equipo remoto dentro de la LAN.

El agente ssh será capaz de autenticarnos en la primera conexión sin ningún problema, pero para que nos autentique en la segunda, este deberá ser reenviado a través de la primera conexión. Por defecto, OpenSSH no está configurado para reenviar el agente, con lo que habrá que ejecutar el cliente con la opción -A, por ejemplo, para conectar con el router y reenviarle el agente:

[hell@local] $ ssh -A router.ejemplo.com
[hell@router] $

Ahora, si miramos las variables de entorno, podemos apreciar como en la sesión que hemos abierto en el router, efectivamente el agente se ha reenviado:

[hell@router] $ echo $SSH_AUTH_SOCK
/tmp/ssh-sQwzt23661/agent.23661
[hell@router] $

¿Cómo funciona esto realmente? Bien, al iniciar la sesión interactiva en el router, el cliente de SSH crea un socket UNIX y establece la variable SSH_AUTH_SOCK apuntando hacia el socket. Cuando se ejecuta otro cliente de SSH para conectar desde el router a otro equipo, el nuevo cliente de SSH se conecta a ese socket, y el primer cliente de SSH reenvia todo lo que recibe por ese socket hacia el agente que se esta ejecutando en nuestro equipo local.

Gracias a este mecanismo, podemos hacer que nuestro agente nos siga autenticando en el resto de equipos a los que nos conectemos, de alguna manera, es como si el agente pudiese viajar con nosotros. Por ejemplo, si desde la sesión interactiva del router queremos conectarnos a un equipo dentro de la LAN llamado remoto.ejemplo.com, podremos poner algo como lo siguiente:

[hell@router] $ ssh -A remoto.ejemplo.com
[hell@remoto] $ echo $SSH_AUTH_SOCK
/tmp/ssh-OsvWx13346/agent.13346
[hell@remoto] $

Se puede apreciar, que se ha creado un nuevo socket UNIX y se ha establecido la variable SSH_AUTH_SOCK apuntando hacia el, lo cual permitirá que nuestro agente, que esta ejecutandose en nuestro equipo local, pueda seguir autenticandonos en las conexiones que realicemos desde remoto.ejemplo.com.

Tiempo de vida para llaves

Se puede hacer que el agente recuerde las llaves durante un tiempo determinado, a partir del cual, el agente las olvidará. Por defecto, el agente no olvida las llaves núnca (mientras se siga ejecutando, o no se le fuerce a olvidarlas), pero se le puede especificar la opción -t seguida del tiempo de vida que se quiere que tengan las llaves:

[hell@local] $ ssh-agent -t 60 bash
[hell@local] $

El comando anterior inicia un nuevo shell bash con el agente, y establece el límite de vida de las llaves por defecto en 60 segundos. Pero también se puede establecer un tiempo límite de vida para cada llave al añadirla con el comando ssh-add, la forma de hacerlo, es la misma, especificando la opción -t seguida del tiempo límite de vida que se quiere que tenga la llave, por ejemplo:

[hell@local] $ ssh-add -t 120 remote
Enter passphrase for remote:
Identity added: remote (remote)
Lifetime set to 120 seconds
[hell@local] $

De esta forma, pasados dos minutos, el agente eliminará la llave remote de su memoria y no podremos seguir empleandola para autenticarnos a no ser que se la añadamos de nuevo al agente.

Por HellGuest