SSH es uno de los programas con los que tendremos que lidiar todos los días que estamos trabajando en una máquina con Unix o Linux. Veámos algunos ejemplos de uso típicos.
Para acceder al host remoto utilizamos el cliente ssh. En ese momento se producirá el proceso de autentificación del servidor y el proceso de identificación y autentificación del usuario. Dependiendo del esquema de autentificación de usuario existen distintas alternativas:
usuario$ ssh host_remoto
|
Con este comando estamos accediendo al host utilizando el usuario usuario. Cuando queramos acceder con otro nombre de usuario utilizaremos:
usuario$ ssh nombre_de_usuario@host_remoto
|
# Por curiosidad mostramos el contenido del directorio "~/.ssh".
usuario$ ls -l $HOME/.ssh/ total 4 -rw-r--r-- 1 usuario usuario 1866 2007-02-08 15:12 known_hosts v # Generación de la clave usando RSA. usuario$ ssh-keygen -t rsa # Selecionar el fichero de salida que se especifica por defecto. # La clave debería tener al menos 20 caracteres. # Por curiosidad mostramos el contenido del directorio "~/.ssh". usuario$ ls -l $HOME/.ssh/ total 12 -rw------- 1 usuario usuario 1743 2007-02-08 22:19 id_rsa -rw-r--r-- 1 usuario usuario 405 2007-02-08 22:19 id_rsa.pub -rw-r--r-- 1 usuario usuario 1866 2007-02-08 15:12 known_hosts # Comprobamos que la clave pública se ha generado. usuario$ cat ~/.ssh/id_rsa.pub ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA5HgtUR6OfvEIUv6m2xXM6QK3MH0Z6\ 74btlJ20XDTAfh0llRgiDxnqrH492ZwH0r6EjVfkH6KhB9R2Duxvpzp4LeBWZ0ouL\ E5MiJBe0aR7CBUcjkq8FzLL3Caf0c7w3Dbtldn4zQdIoHswsD8sFyk2vT4a3QXBV/\ U3Q0DvCXyb5kZp7JOfzNAMJbCD6IVEbDrwqfu4JfTOXAWY8ckofq9zFK+JtkB9XJy\ a7pVJVtI0dKCnVTw3oU4eufj4OxwSGnAyVrf9rEv6jB+4R7tCQZdtuJO7SPAUbJsc\ rD4qjnOz/BDvx2LUQuQXMrbr7GQ+lBNC6gZWcUF33RGc+wIAjvR8Q==\ usuario@debian.ace.ual.es |
# Añadimos la clave pública a nuestro fichero de claves públicas en el
# host remoto. usuario$ ssh <host_remoto> "mkdir .ssh/; umask 077; cat >> .ssh/authorized_keys" < ~/.ssh/id_rsa.pub |
En este punto deberíamos tener ya acceso al host remoto. Para ello se nos preguntará por la frase que usamos cuando generamos las claves de autentificación. Esta forma de autentificación sólo se establecerá cuando accedemos desde el host local usando el usuario usuario. Si accedemos desde otro host o con otro nombre de usuario, se utiliza la autentificación mediante password.
Debido a que necesitamos disponer de la clave de root en el host remoto, esta forma de autentificación es poco corriente. Además, como veremos a continuación, la autentificación basada en clave pública es muy cómoda y segura si utilizamos un agente SSH.
Para que la identificación basada en clave pública sea realmente segura la frase que usemos para generar la clave de autentificación debe ser suficientemente larga (20 caracteres o más). Esto puede suponer un embrollo cuando accedemos muchas veces al host remoto.
Para solucionar este problema, el SSH incorpora un demonio llamado ssh-agent que se encarga de escribir por nosotros las frases. Este demonio puede ser invocado por el usuario de la siguiente manera:
# ¿Qué procesos se están ejecutando?
usuario$ ps x PID TTY STAT TIME COMMAND : : : : : 3096 pts/1 R+ 0:00 ps x # Comprobamos que entre las variables de entorno declaradas # no aparecen SSH_AGENT_PID y SSH_AUTH_SOCK. usuario$ export declare -x HISTCONTROL="ignoredups" declare -x HOME="/home/usuario" declare -x LANG="es_ES.UTF-8" : declare -x TERM="xterm" declare -x USER="usuario" # Lanzamos el demonio. Este comando comprueba primero que no existe # ya un agente ejecutándose. La directiva del shell "eval" permite # ejecutar ssh-agent con su parámetro. usuario$ test -z "$SSH_AUTH_SOCK" && eval ‘ssh-agent -s‘ Agent pid 3256 usuario@debian:~$ export declare -x HISTCONTROL="ignoredups" declare -x HOME="/home/usuario" : declare -x SSH_AGENT_PID="3256" declare -x SSH_AUTH_SOCK="/tmp/ssh-kVGvUg3255/agent.3256" : declare -x TERM="xterm" declare -x USER="usuario" usuario$ ps x PID TTY STAT TIME COMMAND : : : : : 3056 ? Ss 0:00 ssh-agent -s 3099 pts/1 R+ 0:00 ps x |
Una vez que el demonio está ejecutándose, informarle de nuestra clave de autentificación pública es sencillo:
# Deberemos introducir la clave pública introducida en
# la fase de autentificación basada en clave pública... usuario$ ssh-add |
En este punto, accederemos al host remoto sin necesidad de escribir la frase de acceso porque ssh-agent lo ha hecho por nosotros.
Evidéntemente, como podemos tener acceso a distintas máquinas con distintas frases de acceso, podemos usar tantas veces ssh-add como deseemos. Para saber qué frases son admistradas en un momento dado por ssh-agent:
usuario$ ssh-add -l
|
Las frases puede ser eliminadas del demonio usando:
usuario$ ssh-add -d [fichero_con_la_clave]
|
Usar man ssh-add para ver el resto de opciones.
Con SSH es posible ejecutar comandos no interactivos en el host remoto. Un ejemplo:
# Averiguando los usuarios actuales en el host remoto
usuario$ ssh <host_remoto> who # Viendo el contenido actual del directorio /tmp en el host remoto usuario$ ssh <host_remoto> ls /tmp # Copiando un fichero al host remoto usuario$ cat fichero | ssh <host_remoto> "cat > fichero" # Copiando un directorio completo al host remoto usuario$ tar cvf - directorio/ | gzip -9c | ssh <host_remoto> "tar xz" |
Como vimos al comienzo de este módulo, SSH incorpora un mecanismo para autentificar al servidor basado en la comparación de la host key que envía el servidor con la que hay almacenada en el fichero /.ssh/known_hosts. Si es la primera vez que nos conectamos o por algún motivo, la host key ha cambiado, es una buena costumbre que comprobemos que dicha clave coindice con la que el servidor generaría utilizando las herramientas del SSH. Para mostrar la host key en el servidor podemos utilizar el siguiente comando:
# Mostrando la host key del servidor.
usuario$ ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key.pub |
En el fichero /etc/ssh/ssh_host_rsa_key.pub se almacena la host key pública de forma cifrada usando el algoritmo RSA. En el fichero /etc/ssh/ssh_host_rsa_key se almacenan la host key privada de forma cifrada usando el algoritmo RSA.
SSH incorpora una utilidad semejante a cp para copiar ficheros entre hosts de una forma muy sencilla. Algunos ejemplos:
# Copiando "fichero" al home del host remoto:
usuario$ scp fichero <host_remoto>:~ # Copiando "fichero" al /tmp del host remoto: usuario$ scp fichero <host_remoto>:/tmp # Copiando "fichero" al /tmp del host remoto y cambiando el nombre: usuario$ scp fichero <host_remoto>:/tmp/file # Copiando un "directorio" con todos sus contenidos al home del host remoto: usuario$ scp -r directorio <host_remoto>:~ # También podemos utilizar sftp (un intérprete semejante a ftp) para # mover ficheros entre hosts: usuario$ sftp <host_remoto> # Los comandos de sftp son similares a los del programa ftp. # Por último, podemos hacer copias incrementales con la utilidad rsync: usuario$ rsync * <host_remoto> |
El SSH tiene la habilidad de multiplexar varias conexiones sobre un mismo tunnel cifrado. A esta propiedad se le conoce como forwarding (encaminamiento). Veámos algunos ejemplos interesantes:
Como vimos anteriormente, el agente de autentificación es muy útil para lidiar con las frases de clave. El problema es que si hemos accedido a un host remoto A y desde él queremos acceder a otro B usando de nuevo el agente, deberíamos ejecutarlo en A y añadirle las frases. Para conseguir esto podemos hacer dos cosas:
# También vale el fichero /etc/ssh/ssh_config
usuario$ cat ~/.ssh/config : Host nombre_host_remoto ForwardAgent yes : |
# Este comando lanzará ssh-agent en el host remoto y copiará las claves.
usuario@host_local$ ssh -A <host_remoto> |
Para verificar que el redireccionamiento ha funcionado, comprobaremos que el agente en el host remoto contempla nuestras claves:
usuario@host_remoto$ ssh-add -l
|
Cuando usamos SSH desde una consola gráfica, podemos ejecutar aplicaciones gráficas en el host remoto y presentarlas en el host local. Para conseguir esto debemos:
# También vale el fichero /etc/ssh/ssh_config
usuario$ cat ~/.ssh/config : Host nombre_host_remoto ForwardX111 yes : |
usuario@host_local$ ssh -X nombre_host_remoto
|
En este punto podríamos ejecutar una aplicación gráfica, un xterm, por ejemplo:
usuario@host_remoto$ xterm &
|
startx &
|
Transcurridos unos segundos debería aparecer una ventana con un terminal gráfico (este terminal se invoca con la aplicación xterm).
# Habilitamos el sistema gráfico para que cualquier host pueda
# enviar su salida gráfica X11 a nuestro sistema. usuario$ xhost + # Accedemos al host virtual usuario$ ssh -X <dir_IP_del_host_virtual> |
usuario$ xeyes &
|
El redireccionamiento de puertos es una característica utilísima de SSH. Con esto podemos acceder a servicios que están filtrados por un cortafuegos y cifrar transmisiones sobre redes no seguras.
Antes de mostrar cómo se realiza el redireccionamiento, una aclaración importante. El objetivo del redireccionamiento es codificar la comunicación desde nuestro host a otro distinto, situado fuera de nuestra red “segura”. En este sentido podemos encontrarnos los siguientes contextos:
Bien, una vez hecha estas aclaraciones explicaremos cómo redireccionar puertos en cada caso. En los ejemplos que se muestran a continuación supondremos que hemos configurado nuestro navegador Web para que utilize un proxy Web situado en nuestro host (home_host) escuchando en el puerto 1234, aunque dicho servidor esté realmente ejecutándose en un host remoto que llamaremos squid_host y al que tenemos acceso mediante SSH. Supondremos además que en la red local (y por tanto, segura) de squid_host existe otro host remoto remote_host en el que también tenemos cuenta.
# La forma estándar es:
home_host@usuario$ ssh -L 1234:squid_host:3128 squid_host # Nota importante: si "usuario" no tiene cuenta como "usuario" en # "squid_host" y por lo tanto tiene que especificarlo, este # procedimiento puede no funcionar :-( # Aunque también funciona: home_host@usuario$ ssh -L 1234:localhost:3128 squid_host |
Con este ejemplo, hemos redirigido el puerto 1234 del home_host al puerto 3128 de host squid_host.
home_host@usuario$ ssh -L 1234:squid_host:3128 remote_host
# Nota importante: si "usuario" no tiene cuenta como "usuario" en # "squid_host" y por lo tanto tiene que especificarlo, este # procedimiento puede no funcionar :-( |
En este ejemplo el puerto 1234 del host local se ha redirigido al puerto 3128 del host squid_host a través del host remote_host.
squid_host@usuario$ ssh -R 1234:localhost:3128 home_host
|
Redireccionamos el puerto 3128 del host squid_host al puerto 1234 del host home_host.