Saturday, April 7, 2012

SSH para dummies decididos

Recientemente, aconsejé a un amigo que use ssh para manejar un server; me sorprendió el número de problemas que tuvo, a pesar de tener larga experiencia con todo tipo de sistemas, incluso varios tipos de programación desde hace muchos años.

¿Que paso? No es que mi amigo estuviera poco preparado, ni tampoco que le haya sugerido algo muy difícil o complicado.  No, yo creo que el problema está en que nunca había tenido necesidad de usarlo, porque ha podido usar varias otras soluciones en cada caso que se le ha presentado.

Entonces, ¿por que mi insistencia en que use ssh, en lugar de esas otras opciones que ya conoce? Pues resulta que no sólo ssh es una única herramienta que hace muchas cosas, ayudando en muchos problemas diferentes; sino que en la mayoría de los casos es, por mucho, la mejor solución disponible.

Como tantas otras cosas, una vez dominado abre un sinnúmero de posibilidades que antes uno no habría imaginado que eran posibles, ni que estaba a sólo un paso de poder resolver problemas aparentemente difíciles con tanta facilidad que a veces ni vale la pena grabar la solución para usarla mas tarde. ¡Es igualmente fácil volver a resolverla desde cero!

Muy bien, bastante propaganda.  ¿Que hace el dichoso ssh?  En principio es simple: crea una conexión encriptada entre un cliente y un server, y sobre ella puede abrir un terminal o un túnel para otros programas. también incluye utilitarios para copiar files.  Para mantener la mayor seguridad, incluye un muy buen sistema de identificación y autentificación.  Y finalmente, es usado por varios otros programas o sistemas para facilitar toda clase de conexiones seguras y transferencias de datos.

Nota: aunque 'ssh' es el nombre original de un programa que ahora es comercial, existe también una versión Open Source cuyo nombre real es OpenSSH.  Personalmente, sólo he usado la versión Open Source y es de ella que hablo en esta nota; pero al igual que todo el mundo, la llamo simplemente 'ssh'.

Teoría:

Todo se basa en un esquema llamado Criptografía Asimétrica (o Criptografía de Clave Pública, o Public-key Cryptography).  En este esquema, cada individuo posee dos claves relacionadas: una clave pública y una clave privada.  Ambas son generadas como un par, y poseen varias propiedades matemáticas que las hacen muy útiles.

La clave pública se puede distribuir abiertamente, con la intención de que todo el mundo sepa a quién pertenece. La clave privada, en cambio debe permanecer en estricto secreto.  Si por algún motivo hay posibilidades de que una clave privada haya sido copiada, es importante revocar la contraparte pública y generar un nuevo par.

En principio, cuando se una una de estas claves para codificar un mensaje cualquiera, sólo se puede decodificar usando la otra clave. En esto se diferencia de la criptografía simétrica, o de una sola clave. De este modo, es fácil enviar un mensaje que sólo lo pueda leer una persona: basta con usar la clave pública del destinatario y sólo esa persona será capaz de decodificarlo.

Del mismo modo, si una persona codifica con su clave privada un mensaje, cualquiera puede decodificarlo usando la clave pública.  Esto sería útil para asegurar quién es el autor del mensaje.  Por comodidad, no suele codificarse el mensaje completo, sino sólo un checksum o hash generado con el contenido del mensaje, formando una "firma digital" que puede agregarse al mensaje para asegurar no sólo la autoría del mensaje, sino que no ha sido alterado desde que fue firmado.

Finalmente, dos personas pueden establecer un canal privado de comunicación usando un par de claves para cada uno. El "intercambio de claves Diffie-Hellman" es un algoritmo que cada uno de los dos involucrados realiza usando su propia clave privada y la clave pública del otro para calcular una tercera clave, que es la misma para ambos, sin necesidad de transmitirla en ningún momento.  Luego pueden usar esta clave común para aplicar una codificación simétrica a cualquier mensaje que deseen intercambiar.

Aplicación:

Tanto ssh como SSL usan la criptografía asimétrica, y principalmente el intercambio Diffie-Hellman para asegurar privacidad, seguridad y autenticidad en la transmisión de datos. Las claves utilizadas para el protocolo SSL se manejan en los llamados 'certificados', y existe una extensa infraestructura de entidades firmantes y procesos establecidos para distribuir dichos certificados.  Esto lo hace altamente práctico para encapsular otros protocolos de forma automática; pero esto implica una serie de requisitos que pueden ser muy confusos en su aplicación.

En cambio, ssh es una aplicación independiente, con su propio juego de claves en la que uno mismo es responsable de crear el par, distribuir la clave pública y proteger la privada, así como mantener la relación de identidad con las claves.

Uso básico:

El uso básico del ssh como cliente es simple:
    ssh [username@]hostname
Este comando intenta abrir una conexión con el server hostname, puerto TCP 22, intercambia varias claves, a veces hace algunas preguntas al usuario, intenta establecer la identidad de cada uno, quizás pregunte un pasword; y si todo va bien, abre un shell para ejecutar comandos remotamente de forma interactiva.
Si no se especifica username (separado del hostname con una '@') intenta usar el mismo nombre de usuario que en el cliente.

Identificación del server:

La primera vez que un cliente se conecta con un server determinado, el ssh presenta al usuario con una serie de números hexadecimales y la pregunta:
    The authenticity of host 'shell.example.com (x.x.x.x)' can't be established.
    ECDSA key fingerprint is f7:ae:3a:90:de:f6:54:90:df:f2:e2:82:fc:62:64:d4.
    Are you sure you want to continue connecting (yes/no)?
Intimidante, ¿no? Es la primera vez, y empieza advirtiendo que no sabe si el server es el correcto.

Si uno lo piensa con cuidado, tiene sentido.  Si es la primera vez, no tiene forma de saber si estamos conectando con quien queremos conectarnos.  Usualmente no hay motivo para dudarlo, de modo que basta con responder 'yes'.

En casos de alta seguridad, o si hay motivos para creer que la red se encuentra comprometida, el responsable del server puede buscar alguna forma de enviar de antemano el 'fingerprint' del server para que el usuario lo compare con esa serie de hexadecimales.

En cualquier caso, el cliente ssh registra la clave pública del server, y la próxima vez que se conecte con el mismo server, no debe aparecer esa advertencia.  A menos que ocurra algún cambio en el server y en la nueva conexión utilice una clave pública diferente.  En ese caso, el cliente muestra una advertencia mucho más severa, y se rehúsa a conectar con ese server hasta que se resuelva la discrepancia.

Supuestamente, esto sólo debería ocurrir si ha ocurrido alguna interferencia con la comunicación y el server que nos está respondiendo no es el mismo que hemos contactado antes en la misma dirección.  Sin embargo, también ocurre lo mismo cuando el server ha sido reinstalado y se regeneró el par de claves.  En ese caso, el usuario debe borrar el registro de la clave anterior para hacer nuevamente el proceso de la primera conexión.  Para eso basta con borrar una línea del file ~/.ssh/known_hosts.  La línea exacta está indicada en el mensaje de advertencia.

Identificación del cliente:

Antes que el server permita al cliente ejecutar cualquier proceso, es necesario que acredite su identificación. Para esto existen varios métodos, los dos mas comunes son un pasword convencional, y una firma criptográfica.

El método mas conocido es el pasword convencional. Es también el menos seguro, por lo que sólo se usa cuando el cliente o el server han agotado todas las otras opciones.  Consiste simplemente en que el usuario conozca el pasword necesario para el username indicado en el server.  Por supuesto, este pasword es transmitido sólo después de haber establecido un canal seguro (usando claves criptográficas temporales, generadas en el momento de la conexión).

El segundo método es mucho más seguro y sólo resulta confuso las primeras veces. El primer paso es asegurar que el cliente tenga al menos un par estable de claves pública y privada. Luego hay que copiar la clave pública al server, de modo que cuando el cliente intente conectarse, pueda usar la contraparte privada para asegurar su identidad.

Las claves usadas por ssh para identificación suelen tener los nombres ~/.ssh/id_rsa o ~/.ssh/id_dsa, cada una con dos files, uno para la clave privada y otro con el mismo nombre mas la terminación .pub para la clave pública.

Cuando el cliente se conecta con el server, transmite un nombre de la forma username@clienthost que indica la identidad del usuario que intenta probar.  El server, entoncer verifica en el file ~/.ssh/authorized_keys si existe una línea con la clave pública para tal identidad. Si lo encuentra, se lo indica al cliente, junto con un bloque de datos aleatorio.  El cliente entonces usa su clave privada para codificar esos datos y los retransmite.  Si el server entonces es capaz de decodificarlos usando la clave pública, la identidad ha sido demostrada y se abre la conexión sin necesidad de ingresar un pasword.

ssh-keygen:

Es el programa usado para generar pares de claves.  En muchos casos, durante la instalación del paquete ssh, ya se ha generado un par de claves básico, que puede ser usado sin problemas.

De no ser así, o si es necesario un nuevo par, se usa el ssh-keygen; que permite una ampla variedad de opciones.  Las dos principales opciones son el tipo de clave, y un posible pasword.

Existen varios tipos de claves, y el ssh puede usar indistintamente varios de ellos, por lo que muchas veces no importa realmente cuál usar.  Los mas usados son RSA y DSA.  Siendo posiblemente mas común el RSA.

El pasword es una decisión personal.  En este caso, no se aplica al cliente, ni al server, ni a la conexión entre uno y otro, sino al par mismo.  Mas exactamente, a la clave privada.  La idea es: para reducir las probabilidades de que una clave privada sea robada, no se almacena directamente en el file ~/.ssh/id_rsa, sino que se encuentra codificada mediante el pasword.  Solo conociendo el pasword es posible desencriptar la clave privada para poder usarla.

Estrictamente hablando, no es necesario ponerle una clave a la clave.  De este modo, es posible abrir conexiones ssh sin que se haga ninguna pregunta al usuario, lo que puede ser importante para ejecutar comandos en un script.

Continuará...

Hasta ahora hemos visto la base teórica y cómo se conecta el cliente con el server.  En la próxima, hablaré de los diferentes usos del ssh: un shell remoto, transferencia de files, túneles, etc.