Wiki Transmissió de Dades

Secure Shell

Índice

1. Introducción
2. Descripción del tema en concreto

  • 2.1 SSH1
    2.2 SSH2
    2.3 Distribuciones

3. Ejemplo práctico de su utilidad
4. Conclusiones
5. Fuentes




1. Introducción

SSH es un protocolo muy usado, sobretodo en sistemas UNIX-like. Se trata de un protocolo abierto, fiable y seguro que inicialmente servía para conectar a máquinas remotas, pero que con el tiempo se ha usado para encapsular otros datos, de manera que podemos hacer pasar cualquier cosa por él. Pretende ser un reemplazo seguro para aplicaciones tradicionales no seguras, como telnet, rlogin, rsh y rcp. Su versión 2 (SSH2) proporciona también sftp, un reemplazo seguro para FTP.

Es un protocolo con un alto nivel de cifrado, cosa que lo hace propicio para comunicaciones de datos sensibles.

SSH (Secure SHell) es también el nombre del programa que implementa dicho protocolo.




2. Descripción del tema en concreto


SSH trabaja de forma similar a como lo hace TelNet (explicado también en esta wiki) permitiendo las mismas aplicaciones que él y ampliando funcionalidades en la versión 2. La diferencia principal es que SSH usa técnicas de cifrado que hacen que la información que viaja por el medio de comunicación vaya de manera no legible y ninguna tercera persona pueda descubrir el usuario y contraseña de la conexión ni lo que se escribe durante toda la sesión.

Básicamente, sus aplicaciones son:

  • Manejar por completo un ordenador remoto mediante un intérprete de comandos.
  • Redirigir el tráfico de X para poder ejecutar programas gráficos si tenemos un Servidor X arrancado en el ordenador local. Ésto se hace redirigiendo la variable DISPLAY del ordenador remoto para que apunte a la pantalla X del ordenador local y aceptando el host remoto en el servidor X local con el comando xhost +IP-remota.
  • Copiar datos de forma segura (tanto ficheros sueltos como simular sesiones FTP cifradas, SFTP).
  • Gestionar claves RSA para no escribir claves al conectar a las máquinas.
  • Pasar los datos de cualquier otra aplicación por un canal seguro de SSH mediante un túnel SSH.

La primera versión del protocolo y el programa eran libres y los creó un sueco llamado Tatu Ylönen, pero su licencia fue cambiando y terminó apareciendo la compañía 'SSH Communications Security', que lo ofrecía gratuitamente para uso doméstico y académico, pero exigía el pago a otras empresas.

En el año 1997 (dos años después de que se creara la primera versión) se propuso como borrador en la IETF.

A principios de 1999 se empezó a escribir una versión que se convertiría en la implementación libre por excelencia, la de OpenBSD, llamada OpenSSH.

A partir de entonces han salido muchas versiones de programas que lo implementan. Cabe destacar la ausencia de SSH en el ?HyperTerminal de Windows en todas sus versiones.


SSH es un protocolo para iniciar sesiones en máquinas remotas que ofrece autenticación, confidencialidad e integridad. Consta de tres componentes:

  • Protocolo de transporte: normalmente opera sobre TCP/IP dando autenticidad, confidencialidad e integridad.

  • Protocolo de autenticación de usuario: autentica al usuario ante el servidor.

  • Protocolo de conexión: multiplexa un canal encriptado en diversos canales lógicos. Éste requiere que los servidores tengan "llaves", las cuales son usadas por los clientes cada vez que se conectan a un servidor para verificar que no fue suplantado. Una llave es un número codificado y encriptado en un archivo. Para la encriptación de llaves, OpenSSH ofrece los algoritmos RSA y DSA (de los cuales para la versión 2 se recomienda DSA).


El protocolo SSH cuenta con dos versiones. La primera de ellas se mantiene por motivos de compatibilidad, pero se recomienda generalmente el uso de la segunda, por su mayor seguridad. Entre los fallos de la primera versión caben destacar:

  • Fallos estructurales que le hacen vulnerable a ciertos tipos ataques (ataques de replay)

  • Ataque del tipo "Man In The Middle" (intercepción las claves públicas en el intercambio de las mismas)

En cambio, aún conserva ciertas ventajas sobre SSH2:

  • Está soportado en más plataformas que SSH2
  • Permite autentificación de tipo .rhosts (propuesta en SSH2), mientras que permite métodos de autentificación más diversos (AFS, Kerberos, etc.)
  • Tiene mejor rendimiento que SSH2


SSH, dependiendo de su versión utiliza diferentes algoritmos de cifrado:

  • SSH1: DES, 3DES, IDEA, Blowfish

  • SSH2: 3DES, Blowfish, Twofish, Arcfour, Cast128-cbc

El cifrado utilizado para cuestiones de autentificación utiliza RSA para SSH1 y DSA para SSH2.


SSH permite autentificarse utilizando uno o varios de los siguiente métodos:

  • Password
  • Sistema de clave pública
  • Kerberos (SSH1)
  • Basado en el cliente (por relaciones de confianza en SSH1 y sistema de clave pública en SSH2)

Existen además parches que permiten realizar autentificación de otras maneras.


SSH protege contra los siguientes tipos de ataques:

  • IP Spoofing: un ordenador trata de hacerse pasar por otro ordenador (en el que confiamos) y nos envía paquetes "procedentes" del mismo. SSH es incluso capaz de proteger el sistema contra un ordenador de la propia red que se hace pasar por el router de conexión con el exterior.

  • Enrutamiento de la IP de origen: un ordenador puede cambiar la IP de un paquete procedente de otro, para que parezca que viene desde un ordenador en el que se confía.

  • DNS spoofing: un atacante compromete los registros del servicio de nombres.

  • Intercepción de passwords y datos a través de la red.

  • Manipulación de los datos en ordenadores intermediarios.

  • Ataques basados en escuchar autentificación contra servidores X-Windows remotos.


SSH considera la red como un medio hostil en el que no se puede confiar. Un atacante, podrá forzar a que SSH se desconecte, pero no podrá descifrar o reproducir el tráfico, o introducirse en la conexión.

Todo esto, de todos modos, es sólo posible si se utiliza algún tipo de cifrado. SSH permite no usar cifrado (cifrado de tipo "none"), pero esta opción no debería utilizarse. Hay que tener en cuenta que SSH no sirve de nada si el atacante consigue hacerse con el control de la máquina como root, ya que podrá hacer que SSH quede inutilizado.




2.1 SSH1


Características del protocolo

  • El sevidor y el cliente se conectan a través de una red IP no segura.
  • La conexión siempre se inicia por parte del cliente. El servidor está escuchando un puerto determinado, esperando la conexión, y puede atender a varios clientes.
  • Cuando el cliente se conecta al servidor, el servidor acepta la conexión y responde enviando su identificación de versión, a lo que el cliente responde enviando la suya. Esta información valida que la conexión se realizó en el puerto correcto, establece la versión del protocolo utilizada, y la versión del software utilizada por cada uno de ellos. Esta información no se envía cifrada, y es perfectamente legible. Si cualquier lado de la conexión no acepta o no entiende esta información, se cierra la conexión.
  • Una vez a terminado la fase de identificación, ambos lados comienzan una transmisión según un protocolo binario. El servidor envía su clave de equipo (la clave RSA del propio equipo), la clave del servidor (una clave RSA generada cada hora), y otras informaciones al cliente. El cliente genera una clave de sesión de 256 bits, la cifra utilizando ambas claves RSA y envía la clave cifrada, junto con el tipo de cifrado seleccionado al servidor.
  • Ambos lados comienzan ahora a enviar datos cifrados mediante la clave generada y el algoritmo seleccionado. El servidor envía un mensaje de confirmación cifrado al cliente.
  • Tras eso, el cliente se autentifica utilizando uno de los métodos de autentificación soportados:
    • basada en los ficheros ".rhosts" o "/etc/hosts.equiv", por defecto no permitida
    • esta misma junto con autentificación del ordenador cliente basada en RSA
    • autentificación RSA
    • y autentificación por password
  • Tras una correcta autentificación, el cliente envía una serie de peticiones para comenzar la sesión, como establecer una sesión de consola remota, forwarding de X11 o de un puerto TCP/IP, ejecutar un comando, etc.

Al ejecutar una consola o un comando, la sesión entra en modo interactivo. En este modo, se envían datos en ambos sentidos, pueden abrirse nuevas conexiones, etc. Esta sesión generalmente termina cuando el servidor envía el código de terminación del programa ejecutado al cliente.

El protocolo reserva cierta información para permitir extenderlo en el futuro:

  • Envío de la versión del protocolo
  • El primer paquete enviado por ambas partes, contiene una serie de flags, que pueden utilizarse para acordar el uso de extensiones compatibles
  • En las fases de autentificación y preparación de la sesión, el cliente realiza peticiones al servidor, de modo que si se envía una petición no permitida por el servidor, éste simplemente devuelve que la petición ha fallado. Esto permite añadir nuevos métodos de autentificación y operaciones de preparación. En cambio, la sesión interactiva, no permite la negociación de extensiones. Éstas deberían negociarse en las fases anteriores.

Formato de los paquetes

Tras el envío de los strings de identificación, ambas partes envían paquetes con el siguiente formato:

  • 1

    2

    3

    4

    Tamaño del paquete

    1 a 8 bytes de relleno aleatorio

    (cont.relleno aleat.)

    Tipo paquete

    DATOS

    CRC

*Nota: Longitud de relleno + tipo + datos + CRC siempre múltiplo de 8 bytes.

  • Tamaño del paquete: 32 bits. Es el tamaño del paquete, sin incluir el campo tamaño, y el relleno. El máximo es de 262144 bytes.
  • Relleno: 1 - 8 bytes de datos aleatorios (o ceros si no se utiliza cifrado). El tamaño del relleno es de (8 - (tamaño % 8)) bytes. El hecho de que este relleno sea aleatorio dificulta los ataques.
  • Tipo de paquete: 8 bits. El valor 255 está reservado para futuras ampliaciones.
  • Datos: con un tamaño igual al valor del campo "tamaño" menos 5.
  • Bytes de chequeo: 4 bytes. CRC con el polinomio 0xedb88320 del relleno, tipo de paquete y datos. Se calcula antes del cifrado.

Los paquetes de datos tienen, además, las siguientes características:

  • El paquete puede cifrarse utilizando cualquiera de los algoritmos soportados.
  • La longitud de la parte cifrada (relleno + tipo + datos + chequeo) es siempre múltiplo de 8 bytes.
  • Típicamente, el cifrado se utiliza sobre todos los paquetes, como si fuesen una única secuencia.
  • El cifrado se activa cuando el cliente envía la clave de sesión. El algoritmo de cifrado es seleccionado por el cliente.

Compresión de los paquetes:
Si la compresión está soportada, el tipo de paquete y los datos se comprimen utilizando el algoritmo gzip. En este caso, el tamaño del paquete indica el tamaño de los datos comprimidos, más 4 para el CRC. El relleno se calcula según los datos comprimidos, para que los datos cifrados sean múltiplo de 8 bytes.


Cifrado de paquetes:
El protocolo soporta distintos métodos de cifrado. Durante la inicialización de la sesión, el servidor envía al cliente los métodos que soporta, y el cliente elige uno de estos métodos, y genera una clave aleatoria de 256 bits que también envía al servidor. Todas las implementaciones deben de soportar el algoritmo 3DES, siendo los demás opcionales. Para cifrar los datos, las partes cifradas de cada paquete se consideran un flujo de datos continuo, cuyo tamaño es siempre múltiplo de 8 bytes. Las partes cifradas de paquetes consecutivos se cifran como si se tratase de un buffer continuo de datos. Los datos se cifran independientemente en cada dirección.


Otras opciones de los aquetes de datos:

  • El puerto por defecto para el servidor es el 22.
  • El cliente puede conectarse desde cualquier puerto, pero si quiere utilizar autentificación mediante ".rhosts" o "/etc/hosts.equiv", debe conectarse a través de un puerto privilegiado (menor a 1024).
  • El campo IP "Tipo de Servicio" debería de ser IPTOS_LOWDELAY para conexiones interactivas, y IPTOS_THROUGHPUT para las no interactivas.
  • Se recomienda así mismo que se utilicen señales para comunicar que la conexión sigue activa, para detectar si alguno de los lados ha cortado la conexión de modo inusual.

Identificación de la versión del protocolo:

  • Una vez que se ha abierto el socket, el servidor envía un string con el formato "SSH-<num_mayor_del_protocolo>.<num_menor_del_protocolo>-<versión>\n". Los dos primeros campos identifican la versión del protocolo, y el último campo, la versión del software del servidor.

  • El cliente envía después su propia información. Si el servidor tiene un protocolo menor que el cliente, y éste puede emularlo, envía la versión menor.
  • En caso contrario, envía su propia versión. El servidor compara la versión enviada por el cliente con la suya, y determina si pueden trabajar o no. El servidor decidirá desconectarse, o enviará el primer paquete binario, y ambas partes utilizarán después la versión del protocolo acordada.

Intercambio de claves y autentificación del equipo servidor:

  • El primer mensaje enviado por el servidor envía la clave del equipo, la clave pública del servidor, los algoritmos de cifrado soportados, los métodos de autentificación soportados y las extensiones. También contiene un número aleatorio de 64 bits (cookie). Este paquete se envía sin cifrar.

Ambas partes calculan un identificador de sesión del siguiente modo:

  • session_id = MD5(hostkey || serverkey || cookie)


  • El cliente responde con un mensaje que contiene el tipo de cifrado elegido, una copia del cookie, y la clave de sesión de 256 bits cifrada con ambas claves del servidor. Este mensaje no se cifra.
  • Una vez que se ha enviado la clave de sesión, el cliente cifrará todos los paquetes salientes y descifrará todos los paquetes entrantes.
  • Una vez que el servidor recibe la clave, y activa el cifrado, envía al cliente un mensaje indicando el éxito de la operación.
  • La clave de equipo del servidor se recomienda que tenga 1024 bits, y la clave del cliente, 768 bits. La clave mínima no puede ser menor de 512 bits.

El nombre de usuario:

  • El cliente envía al servidor un mensaje indicando el nombre de usuario con el que se quiere conectar.
  • El servidor valida que el usuario existe, si se necesita autentificación y responde con un mensaje de éxito (no se necesita autentificar el usuario) o fallo (se necesita autentificación, o el usuario no existe).
  • Si el usuario no existe, se devolverá fallo a todos los mensajes, excepto al mensaje de desconexión, al mensaje "ignore" y al mensaje "debug", pero seguirá escuchando al cliente, de modo que este no puede saber si el usuario existía o no.

Fase de autentificación:
Si no se acepta el login automáticamente, el cliente pide al servidor distintos métodos de autentificación de manera aleatoria tantas veces como desee. Si la autentificación es correcta se devolverá un mensaje de éxito, y si falla, un mensaje de fallo.


  • Autentificación por RHOSTS:

    • El cliente envía un mensaje con el nombre del usuario cliente. El servidor verifica este nombre contra los ficheros "/etc/hosts.equiv" y ".rhosts" (sistemas UNIX). La conexión debe de venir desde un puerto privilegiado.
    • Este tipo de verificación no suele activarse puesto que puede sufrir diversos ataques.
  • Autentificación por RHOSTS y RSA:

    • El cliente no sólo envía el nombre de usuario, sino también su clave pública RSA. El servidor autentifica al cliente por el método RHOSTS, y si se verifica, comprueba si conoce su clave pública, y si la enviada es la misma almacenada en el servidor.
    • Si cualquiera de estos pasos no se cumple, se devolverá un mensaje de fallo.
    • En caso contrario, se someterá al cliente a un desafío RSA con la clave pública del cliente. El cliente deberá descifrar un mensaje cifrado con su clave pública, utilizando su clave privada, y enviará la respuesta al servidor, que verificará si se ha conseguido pasar el desafío o no.
  • Autentificación por RSA:

    • En este caso, el cliente envía su clave pública, y si el servidor la admite, envía al cliente un desafío RSA.
    • En el caso de que el cliente lo supere, se permitirá el acceso del mismo.
  • Autentificación por password:

    • El cliente envía al servidor el password del usuario, en texto plano (aunque lo normal será que viaje cifrado).
    • Si el password es correcto, se permitirá el acceso.

Una vez que el servidor ha admitido la conexión por parte del cliente, se negocian las opciones que van a utilizarse durante el intercambio de datos.


Sesión interactiva e intercambio de datos:

  • Durante una sesión interactiva, los datos de salida el proceso en ejecución en el servidor se redireccionan a "stdout" o "stderr" en el cliente, y cualquier entrada disponible en "stdin" en el cliente se envía al programa en el servidor. El envío de datos es asíncrono, y tanto el cliente como el servidor pueden enviar datos al mismo tiempo.
  • Cuando la aplicación termine de ejecutarse en el servidor, se enviará un mensaje con el estado de finalización del programa, y se cerrará la conexión.
  • Además, de esto, la conexión puede ser cerrada en cualquier momento por cualquiera de los dos ordenadores.



2.2 SSH2


Características del protocolo

Cada servidor debería de tener una clave de equipo. Es posible tener varias, con distintos algoritmos, e incluso varios equipos pueden compartir la misma clave. Si un equipo tiene claves, al menos debe de tener una clave utilizando el algoritmo obligatorio (DSS).

La clave se utiliza para verificar que el cliente está conectado al servidor correcto, para lo que el cliente debe conocer de antemano la clave pública del servidor. Pueden utilizarse dos modelos:

  • El cliente tiene una base de datos que asocia servidores con sus correspondientes claves públicas.

  • Las asociaciones vienen dadas por una autoridad de certificación.

El protocolo permite que, la primera vez que el cliente se conecte con un servidor, no se compruebe su clave pública, con lo que esta primera vez no sería necesaria, pero esto hace que la conexión sea vulnerable, por lo que no se recomienda, aunque a veces es necesaria esta opción. Todas las implementaciones del protocolo deberían hacer todo lo posible por comprobar siempre esta clave.

Además, está diseñado de manera que pueda resultar fácilmente extensible, añadiendo nuevos algoritmos, protocolos, tipos de datos, etc.

Asimismo permite negociar el cifrado, la integridad, el intercambio de claves, la compresión, y los algoritmos y formatos de las claves públicas. Los algoritmos de cifrado, integridad, clave pública y compresión pueden ser diferentes en cada sentido de la conexión.


Consideraciones de seguridad:

  • Los algoritmos de integridad, cifrado y clave pública utilizados son conocidos y ampliamente probados.
  • Los algoritmos utilizan claves lo suficientemente largas como para resistir durante décadas los más fuertes ataques de criptoanálisis.
  • Como los algoritmos se negocian, si uno se ve comprometido es posible negociar el uso de otro sin cambiar el protocolo.

Protocolo de transporte:
Este protocolo proporciona cifrado fuerte, autentificación del servidor y protección de la integridad de los datos. No autentifica al cliente, sino que permite hacer esto en un protocolo superior.

El protocolo de transporte negocia el método de intercambio de claves, el algoritmo de clave pública, el algoritmo de cifrado simétrico, el algoritmo de autentificación de mensajes y el algoritmo de hash. En el mejor de los casos, se necesitaran dos intercambios de mensajes entre el cliente y el servidor para esta negociación, y en el peor, tres.


Establecimiento de la conexión:

  • El servidor generalmente escucha conexiones en el puerto 22 de TCP/IP.
  • Cuando se establece la conexión, ambos lados deben enviar un string de identificación con el formato: "SSH-versión_protocolo-versión_software comentarios\r\n"

Formato de los paquetes:
Cada paquete tiene el siguiente formato:

  • 1

    2

    3

    4

    Tamaño del paquete

    Tamaño relleno

    DATOS

    (cont. DATOS)

    Relleno aleatorio

    MAC

*Nota: El tamaño mínimo del paquete es 16 bytes, y el tamaño máximo del paquete debe de poder enviar 32768 bytes de datos sin comprimir, con un tamaño total del paquete de 35000 bytes. Las implementaciones deberían de soportar paquetes mayores para tareas específicas.

  • Tamaño del paquete, 4 bytes: el tamaño del paquete sin incluir el campo MAC ni el propio campo tamaño.

  • Tamaño del relleno, 1 byte: el tamaño del relleno.

  • Datos, (tamaño paquete - tamaño relleno – 1) bytes: los datos útiles del paquetes. Si la compresión está activada, está comprimido. Inicialmente, la compresión debe de estar desactivada ("NONE").

  • Relleno aleatorio, tamaño del relleno bytes: relleno para que el tamaño de todo el paquete, excepto el campo mac, tenga un tamaño múltiplo de 8, o el tamaño del bloque de cifrado, lo que sea mayor. Tiene que tener, como mínimo, 4 bytes, y cómo máximo 255.

  • MAC (message authentication code), n bytes: bytes para la autentificación del mensaje.

Compresión y cifrado:
Si se ha negociado la compresión, el campo de datos estará comprimido según el algoritmo negociado. El campo del tamaño y la MAC se calcularán según los datos comprimidos. El cifrado se realizará tras la compresión.

La compresión debe de poder negociarse independientemente para cada sentido de la transmisión.

Es obligatorio no soportar compresión, y opcional soportar compresión con el algoritmo "zlib".


El algoritmo de cifrado se negociará durante el intercambio de claves. Los campos cifrados serán: tamaño del paquete, tamaño del relleno, datos y relleno, después de ser comprimidos si la compresión está activa.

Los datos enviados en una dirección deberían de ser tratados como un flujo continuo de datos, y las claves de los algoritmos deberían tener, al menos 128 bits.

Los algoritmos pueden ser diferentes en cada dirección de la comunicación.

El único algoritmo requerido es el 3des-cbc, aunque pueden implementarse una gran cantidad de algoritmos opcionales.

Es también posible especificar que el tráfico no sea cifrado, con lo que se perdería la confidencialidad, por lo que no se recomienda.


Integridad de los datos:
En cada paquete se introduce un código de autentificación de mensaje (MAC) calculado a partir de una clave compartida por el cliente y el servidor, el número de secuencia del paquete, y el contenido del mismo.

El algoritmo es independiente en cada sentido de la conexión.

El único algoritmo que ha de implementarse de manera obligatoria es el algoritmo hmac-sha1.


Métodos de intercambio de claves:

El algoritmo requerido por toda implementación es el algoritmo DSS, aunque pueden implementarse muchos más.

El tipo de clave debe conocerse de antemano (por ejemplo, especificándolo en la negociación del algoritmo). Por ello es denominada clave pública.


Intercambio de claves

Cada equipo envía una lista de los algoritmos que soporta. Cada una de las partes tiene un algoritmo preferido para cada una de las categorías, y se presupone que la mayoría de las implementaciones van a usar siempre el mismo algoritmo preferido. Cada parte puede suponer qué algoritmo está utilizando el otro equipo, y puede enviar un paquete de intercambio de claves según ese algoritmo si corresponde con el algoritmo predefinido.

Esta suposición es incorrecta si:

  • El algoritmo de intercambio y/o el algoritmo de clave de equipo se presuponen de manera incorrecta (el algoritmo predefinido es distinto en el cliente y en el servidor)
  • No pueden ponerse de acuerdo en cualquiera de los otros algoritmos

En caso contrario, la suposición se considera correcta, y el primer paquete enviado debe de ser gestionado como el primer paquete de intercambio de claves.

De todos modos, si la suposición es incorrecta, y se ha enviado algún paquete de intercambio de claves, estos paquetes serán ignorados, y el lado implicado deberá de enviar un paquete de inicio correcto.

La autentificación del servidor en el intercambio de claves puede ir implícita.

Tras un intercambio de claves con autentificación implícita, el cliente debe esperar una respuesta a su petición de servicio antes de enviar más datos.


Negociación de algoritmos

El intercambio de claves comienza con un paquete enviado por ambas partes con la siguiente información:

  • Código de comando: 1 byte.

  • cookie: 16 bytes.

  • Algoritmos de intercambio de claves: string.

  • Algoritmos de clave de servidor: string.

  • Algoritmos de cifrado cliente/servidor: string.

  • Algoritmos de cifrado servidor/cliente: string.

  • Algoritmos de compresión cliente/servidor: string.

  • Algoritmos de compresión servidor/cliente: string.

  • Algoritmos de mac cliente/servidor: string.

  • Algoritmos de mac servidor/cliente: string.

  • Lenguajes cliente/servidor: string.

  • Lenguajes servidor/cliente: string.

  • Aiguiente paquete es el primero de intercambio de claves: boolean.

  • Reservado para extensiones: Entero (32 bits).

El primer algoritmo de cada lista debe de ser el preferido por la parte (el que se presupondrá), y ninguna lista de algoritmos puede ser vacía.

Si ambas partes tienen el mismo algoritmo de intercambio de clave, se utilizará ese algoritmo. En caso contrario, se seguirá el siguiente algoritmo, iterando sobre los algoritmos soportados por el cliente. Se elegirá el primero que cimpla las siguientes condiciones:

  • Esté soportado por el servidor.
  • Si necesita cifrado, hay un algoritmo de cifrado de clave de host (clave del equipo servidor) en el servidor que también está soportada en el cliente.
  • Si necesita una clave del equipo servidor con firma, este algoritmo de firma existe en el servidor, y en el cliente.
  • Si ningún algoritmo satisface estas condiciones, ambos lados deben desconectarse.

Tras el envío de este paquete, se produce el intercambio de claves según el algoritmo escogido.


Compresión y cifrado:
Si se ha negociado la compresión, el campo de datos estará comprimido según el algoritmo negociado. El campo del tamaño y la MAC se calcularán según los datos comprimidos. El cifrado se realizará tras la compresión.

La compresión debe de poder negociarse independientemente para cada sentido de la transmisión.

Es obligatorio no soportar compresión, y opcional soportar compresión con el algoritmo "zlib".


El algoritmo de cifrado se negociará durante el intercambio de claves. Los campos cifrados serán: tamaño del paquete, tamaño del relleno, datos y relleno, después de ser comprimidos si la compresión está activa.

Los datos enviados en una dirección deberían de ser tratados como un flujo continuo de datos, y las claves de los algoritmos deberían tener, al menos 128 bits.

Los algoritmos pueden ser diferentes en cada dirección de la comunicación.

El único algoritmo requerido es el 3des-cbc, aunque pueden implementarse una gran cantidad de algoritmos opcionales.

Es también posible especificar que el tráfico no sea cifrado, con lo que se perdería la confidencialidad, por lo que no se recomienda.


Integridad de los datos:
En cada paquete se introduce un código de autentificación de mensaje (MAC) calculado a partir de una clave compartida por el cliente y el servidor, el número de secuencia del paquete, y el contenido del mismo.

El algoritmo es independiente en cada sentido de la conexión.

El único algoritmo que ha de implementarse de manera obligatoria es el algoritmo hmac-sha1.


Este intercambio produce dos valores: una clave secreta K, y un valor de intercambio H. El valor H del primer intercambio de claves es también el identificativo de sesión, y se genera a partir de una función de HASH.

El intercambio de claves termina con el envío de un comando SSH_MSG_NEWKEYS. Este mensaje se envía utilizando las claves y algoritmos que se utilizaban hasta ese momento, y tras su envío, todos los demás paquetes que se envíen lo harán con estas nuevas claves y algoritmos.

Cuando este mensaje se recibe, los nuevos algoritmos y claves deberán utilizarse para recibir.

Tras el intercambio de claves, este es el único paquete válido, junto con la orden de desconexión, el paquete "ignore" y el paquete "debug", para que ambos equipos confirmen que todo ha ido bien.

En el caso del intercambio de claves Diffie-Hellman, se calcula una clave secreta, compartida por ambos equipos, que no puede determinarse sino es por colaboración de ambos. El intercambio de claves se combina con una firma utilizando la clave del host del servidor para autentificar a éste.

Si se recibe un mensaje de intercambio claves (y no se está realizando ya uno), ambas partes vuelven a negociar la clave.

Este intercambio se realiza utilizando el cifrado activo en ese momento. Los métodos de cifrado, compresión y MAC no se cambian hasta que termine la negociación, y se procesa de manera idéntica al intercambio inicial (excepto que el identificativo de sesión no cambia).

Se recomienda cambiar las claves después de la transferencia de un gigabyte, o una hora de conexión.

Tras el intercambio se puede continuar enviado datos.


Petición de servicio:

Tras el intercambio inicial de claves, el cliente solicita un servicio, identificado por un nombre. Los servicios inicialmente implementados son el de autentificación y el de petición de conexión.

Si el servidor no acepta la petición, deberá desconectarse, y si lo acepta, deberá notificarlo al cliente.

El servicio puede tener acceso al identificador de sesión generado en el intercambio de claves.


Protocolo de autentificación

El protocolo de autentificación SSH es un protocolo de autentificación de propósito general que trabaja sobre el protocolo de la capa de transporte SSH. Presupone que los protocolos inferiores proporcionan integridad y confidencialidad de los datos.

Este protocolo recibe el identificador de sesión generado por el protocolo inferior. Este identificador de sesión es único para la misma, y adecuado para realizar firmas, de modo que pueda probarse la posesión de una clave privada.

También necesita conocer si el protocolo inferior realmente proporciona confidencialidad.

El servidor dirige la autentificación diciendo al cliente los métodos soportados. El cliente puede elegir cualquiera de ellos e ir probando en cualquier orden. De este modo el servidor tiene el control, pero cliente la suficiente flexibilidad para resultar cómo para el usuario.

Todas las peticiones de autentificación deben de tener el siguiente formato:

  • Código de comando (SSH_MSG_USERAUTH_REQUEST): 1 byte.
  • Nombre de usuario: string.
  • Nombre del servicio: string.
  • Método de autentificación: string.
  • Datos dependientes del método: binario.

Si el usuario no existe, el servidor puede desconectarse, o enviar un listado incorrecto de métodos de autentificación, pero nunca aceptar ninguno.

El resto de mensajes dependerán del método de autentificación escogido, que puede ser cambiado por el cliente en cualquier momento, con lo que el servidor deberá abandonar el proceso anterior, comenzar el nuevo.

Si el servidor rechaza la petición, enviará un mensaje de fallo con los métodos de autentificación portados. En caso de que la autentificación se acepte, se enviará un mensaje indicándolo.

Si la autentificación consta de varios pasos, se responderá a cada paso individual con un mensaje de fallo, que contendrá un campo éxito parcial a verdadero. El mensaje de aceptación sólo se enviará al final de todo el proceso.

Cualquier mensaje que no sea de autentificación enviado por el cliente una vez se haya aceptado su petición, deberá pasarse al servicio activo sobre este protocolo.

En ciertas jurisdicciones, puede ser necesario enviar un mensaje de aviso al comenzar la sesión para obtener asistencia legal. Este protocolo permite al servidor enviar un mensaje (como el mostrado en sistemas UNIX) al cliente, para que este lo muestre, tras cualquier autentificación que se halla llevado a cabo con éxito.


Método de autentificación por clave pública:

Es el único método requerido en todas las implementaciones.

Con éste método, la autentificación se prueba si se posee una clave privada. Se envía una firma creada con la clave privada del usuario. El servidor comprueba que la clave es válida para el usuario, y que la firma también es válida. Si ambas condiciones se cumplen, la petición se acepta. En caso contrario, se rechaza.

  • El cliente envía al servidor la petición de autentificación con su clave pública.
  • Si el servidor no acepta el método, envía un mensaje de fallo. En caso contrario, envía un mensaje de aceptación del método pedido.
  • Si se acepta, el cliente enviará un nuevo paquete de petición de autentificación de clave pública, pero incluyendo una firma creada con su clave privada, que firma todos los demás campos del mensaje, incluyendo el identificativo de sesión como campo firmado.
  • Cuando el servidor recibe este mensaje, comprueba que la clave proporcionada es correcta, y si lo es, comprueba también la firma. El servidor entonces responderá con un mensaje de éxito o fallo.

Método de autentificación por password:

El cliente envía un mensaje de autentificación con su password, con el formato siguiente:

  • SSH_MSG_USERAUTH_REQUEST: 1 byte.
  • User name: string.
  • Service: string.
  • "Password": string.
  • FALSE: boolean.
  • plaintext password: string.

Generalmente, el servidor responderá con éxito o fallo, pero en el caso de que el password haya caducado, enviará el siguiente mensaje:

  • SSH_MSG_USERAUTH_PASSWD_CHANGEREQ: byte.
  • Prompt: string .
  • Language tag: string.

En este caso, el cliente puede continuar con un método de autentificación diferente, o pedir un nuevo password al usuario y volver a intentarlo, con el siguiente mensaje:

  • SSH_MSG_USERAUTH_REQUEST: byte.
  • User name: string.
  • Service: string.
  • "password": string.
  • TRUE: boolean.
  • plaintext old password: string.
  • plaintext new password: string.

El servidor puede responder con un mensaje de éxito, fallo, o una nueva petición de cambio de clave, en el caso de que considere que el nuevo password no es válido.


Autentificación basada en la máquina cliente:

Es un método de autentificación similar al "rhosts" o "hosts.equiv", pero más riguroso.

El método funciona del siguiente modo: el cliente envía una petición de autentificación, firmada con su clave privada de equipo, que el servidor comprueba con la clave pública del mismo. Una vez que se ha establecido la identidad el equipo cliente, la autorización se realiza basándose en el nombre de usuario y el nombre de la máquina.

La firma incluye todos los campos del paquete de petición de autentificación, y el identificativo de sesión.

El servidor verificará que la clave pública pertenece al equipo indicado, que el usuario en ese equipo tiene permiso de conexión, y que la firma es válida para esa clave.


Protocolo de conexión

El protocolo de conexión SSH está diseñado para funcionar sobre los protocolos de transporte y autentificación de usuario SSH. Proporciona sesiones de conexión interactivas, ejecución remota de comandos, redirección de conexiones TCP/IP y redirección de conexiones X11.

Existen peticiones que afectan al estado del equipo remoto de manera "global", independientemente de cualquier canal. Un ejemplo sería comenzar la redirección de un determinado puerto TCP/IP.

El destinatario responderá a estas peticiones con un mensaje de éxito o fallo, y se indica en la petición que se espera una respuesta.


Canales:

Cualquier parte de la conexión puede abrir un canal, y los distintos canales se multiplexan sobre una sola conexión.

Los canales se identifican con un número en cada extremo, que puede ser distinto en cada parte. Cualquier mensaje perteneciente a un canal, incluye el número de canal en el extremo opuesto.

Los canales tienen control de flujo, y no se envían datos al canal hasta que se reciba un mensaje diciendo que existe espacio en la ventana de recepción.

Cuando cualquier parte quiere abrir un nuevo canal, reserva un número local para el mismo, y envía un mensaje al otro extremo, que incluye el número local, el tipo de canal que quiere abrir y el tamaño inicial de la ventana. El extremo remoto decide si puede abrir el canal, y responde con un mensaje de confirmación, que contiene el número que usará él para el canal, y el tamaño de la ventana, o bien con un mensaje de fallo, que contiene el motivo del fallo (un código, y un mensaje).

El tamaño de la ventana indica cuántos bytes puede enviar el otro lado antes de recibir un mensaje de ajuste de ventana.

Tras recibir un mensaje de ajuste de ventana, el receptor del mismo podrá enviar más datos, según el nuevo tamaño de la misma.

La transferencia de datos se realiza con paquetes con el siguiente formato:

  • SSH_MSG_CHANNEL_DATA: byte.
  • Canal del receptor: Entero de 32 bits.
  • Datos: string.

El máximo tamaño es el actual tamaño de la ventana de transmisión, y el tamaño de ésta se decrementará en el tamaño de los datos enviados.

En ciertos tipos de canales, además, se puede enviar un código que indica el tipo de datos que se están enviando:

  • SSH_MSG_CHANNEL_EXTENDED_DATA: byte
  • Canal del receptor: Entero de 32 bits.
  • Tipo de datos: Entero de 32 bits.
  • Datos: String.

Cuando una parte no va a enviar más datos por un canal, debería enviar un mensaje de fin de datos con la siguiente estructura:

  • SSH_MSG_CHANNEL_EOF: byte.
  • Canal del receptor: entero de 32 bits.

Tras este mensaje, el canal continúa abierto, y se pueden enviar datos desde el otro extremo.

Cuando cualquier extremo de la conexión quiere cerrar el canal, manda un mensaje de cierre:

  • SSH_MSG_CHANNEL_CLOSE: byte.
  • Canal del receptor: entero de 32 bits.

Al recibir este mensaje, el otro extremo debe devolver un mensaje de cierre, a no ser que lo hubiera enviado antes.

Muchos canales tienen extensiones propias. Un ejemplo puede ser solicitar un pty (pseudo terminal) para una sesión interactiva. En ese caso, se enviará un comando de petición que será propio del canal.

Si no se espera petición, no se enviará. En caso contrario, se enviará un mensaje de éxito o fallo de la petición.


Sesiones interactivas:

Una sesión es una ejecución remota de un programa. El programa puede ser una consola, una aplicación, un comando del sistema o un subsistema. Puede tener o no una terminal y puede requerir redirección de trafico sobre X11. Además, múltiples sesiones pueden estar activas a la vez.

Para realizar todas estas operaciones, se enviarán diferentes tipos de mensajes para apertura de canales y solicitud de opciones en los mismos, que no se describen aquí por no extender aún mas esta ampliación.



2.3 Distribuciones

  • SSH Tectia - http://www.ssh.com - Servidor y cliente SSH comercial. Versiones para muchísimos sistemas operativos, tanto Windows como UNIX.

  • OpenSSH - http://www.openssh.com - Implementación SSH (servidor, cliente y utilidades) gratuita y para sistemas UNIX-like. Está desarrollado por OpenBSD.

  • ossh - ftp://ftp.pdc.kth.se/pub/krypto/ossh/ - Implementación gratuita del protocolo SSH (servidor y cliente) para sistemas UNIX-like. Dispone de compresión de datos (incluye los datos de las X) y alta seguridad.

  • Dropbear SSH - http://matt.ucc.asn.au/dropbear/dropbear.html - Implementación del protocolo SSH (servidor y cliente) para sistemas UNIX-like. Hace hincapié en el consumo mínimo de recursos, para servidores limitados o con alta carga.

  • ?MindTerm - http://www.appgate.com/products/80_MindTerm/ - Cliente JAVA para SSH. Deb ido a estar hecho en java es altamente portable.

  • PuTTY - http://www.chiark.greenend.org.uk/~sgtatham/putty/ - Cliente gráfico SSH, Telnet, rlogin... Muy popular debido a su simplicidad y que no necesita instalarse, es un único EXE. En la versión en desarrollo tiene soporte para terminales en el puerto série. Dispone de versión Windows y UNIX-like (requiere X).

  • otras: Existen otras soluciones SSH, miles, y muchas mas si tenemos en cuenta la ingente cantidad de programas FTP que soportan SFTP.
    Para instalar un servidor OpenSSH, que le permita conectarse a su sistema de forma segura, instale el paquete ssh preferiblemente tomando la versión más reciente.

Unas opciones comunes de configuración del servidor SSH son:

  • ?PermitRootLogin [yes/no]: Permite entrar al usuario root (administrador) de manera remota.

  • RSAAuthentication [yes/no]: Permite usar la identificación RSA para autentificar los usuarios/servidores remotos y así no tener que escribir las contraseñas.

  • ?PubkeyAuthentication [yes/no]: Permite usar la identificación por clave pública para autentificar los usuarios/servidores remotos y así no tener que escribir las contraseñas.

  • ?RhostsAuthentication [yes/no]: Es un método de identificación basado en la combinación del método rhosts o hosts.equiv combinado con autentificación basada en RSA.

  • hostsRSAAuthentication [yes/no]: Es un método de identificación basado en autentificación mediante RSA.

  • ?HostbasedAuthentication [yes/no]: Es un método de identificación basado en la llave pública del host.

  • ?X11Forwarding [yes/no]: Permite hacer un túnel para forwaddear las X y poder ejecutar aplicaciones X en el servidor mientras vemos las ventanas en la máquina local.

Un usuario también puede crear un par de llaves que le faciliten su autentificación al emplear ssh o scp. Estos programas por defecto piden clave al usuario que se conecte a un servidor SSH. Si un usuario genera sus llaves pública y privada, puede saltarse esta autentificación pues se hará de forma automática con las llaves. Para lograrlo su llave pública debe estar en el servidor al cual se conecta (en ~/.ssh/authorized_keys) y su llave privada en el ordenador loca (normalmente en ~/.ssh/id_dsa).

La generación de llaves puede hacerse con:

 ssh-keygen -t dsa

que por defecto dejará su llave pública en ~/.ssh/id_dsa.pub y su llave privada en ~/.ssh/id_dsa (que además quedará protegida por una palabra clave que usted especifica). Como el nombre lo indica la llave privada no debe compartirla, por el contrario la llave pública puede transmitirla y puede ser vista por cualquiera.

En el computador en el que desee conectarse, agregue en el archivo ~/.ssh/authorized_keys (o ~/.ssh/authorized_keys2 si usa DSA y una versión de OpenSSH anterior a la 3.1), su llave pública.



Volver al índice.


3. Ejemplo práctico de su utilidad

Conexión SSH habitual:

 ssh -o ordenador.remoto.org

SSH sin cifrado:

 ssh -o cipher=none ordenador.remoto.org

El comando scp permite copiar ficheros de manera segura entre dos ordenadores:

De local a remoto:

 scp dir/local/fichero usuario@host:/directorio/destino

Para mantener los mismos atributos del fichero será necesario utilizar la opción -p, para usar compresión en el envío -C y para moverlos en lugar de copiarlos existe la opción -u.

En sentido inverso:

 scp usuario@host:/directorio/origen/fichero dir/local

scp se puede usar con la mayoría de parámetros del comando cp de unix, como podría ser la opción -r para copiar recursivamente.

El comando sftp permite realizar transacciones ftp de manera segura, cifrando tanto la conexión de datos como la conexión de control. Para ello el servidor remoto tiene que estar ejecutando el daemon sshd2.

 sftp servidor_remoto usuario

Si queremos utilizar el puerto 10110 para crear una conexión segura al puerto 110 de una máquina remota usando las técnicas de tunneling y port-forwarding haremos:

 ssh -P -L 10110:popmail.correo.net:110

Un ejemplo de ssh se pude ver en http://www.naguissa.com/sshapplet.php (necesita java), que permite conectarse, por ejemplo, a la sala de ordenadores de TD con nuestro usuario y password (servidor: ccd-dc0.uab.es ).



Volver al índice.


4. Conclusiones

Ya sabíamos del uso de SSH como shell remota segura, pues la habíamos utilizado como acceso remoto a las estaciones de trabajo de las aulas de práctica, pero es posible que muchos no nos hayamos dado cuenta que lo usamos también en otros contextos, como son las conexiones a las workstations SUN de la universidad, usando la técnica de X-forwadding a través de un tunel SSH; o algunas coexiones a servidores de correo electrónico, que están cifradas a través de un port-forwadding usando un túnel SSH. Y qué decir de la utilidad sftp de la sala de ordenadores que nos ermite administrar los archivos de nuestra máquina remota.

Ésto nos demuestra la grandísima facilidad de uso que tiene SSH, que unido a su grandísima seguridad (mayor en SSH1) y el hecho de que sea un protocolo rápido (poco overhead, mas rápido SSH1 que SSH2) y el hecho de que SSH2 sea libre han ayudado a que se popularice, sobretodo en entornos UNIX-like, donde tiene mas experiéncia, y para conectarse desde clientes, ya sean windows o UNIX, desde cualquier entorno, por poco fiable que sea, como un cibercafé.

Realmente creo que se tendrían que potenciar las posibilidades de los túneles SSH, que harían que todas las comunicaciones fuesen seguras y no habría problemas de sniffing ni hacking.

Como cosas en contra podríamos citar el liero overhead que genera, que es mínimo, la moléstia del intercambio de claves y los problemas con direciones dinámicas. El resto de problemas ya se arreglaron con la versión 2.



Volver al índice.


5. Fuentes

  • http://es.wikipedia.org/wiki/Secure_Shell
    http://www.ietf.org/internet-drafts/draft-ietf-secsh-architecture-13.txt
    http://rcfile.org/ssh/
    http://www.akadia.com/services/ssh_scp_without_password.html
    http://packages.gentoo.org/search/?sstring=ssh
    http://www.ssh.com/
    http://www.openssh.com/
    ftp://ftp.pdc.kth.se/pub/krypto/ossh/
    http://matt.ucc.asn.au/dropbear/dropbear.html
    http://www.appgate.com/products/80_MindTerm/
    http://www.chiark.greenend.org.uk/~sgtatham/putty/
    http://130.206.100.150/docs/articulo.ssh.html
    http://www.ayahuasca.net/ssh
    http://www.snailbook.com/docs/protocol-1.5.txt
    http://www.snailbook.com/docs/architecture.txt
    http://www.snailbook.com/docs/transport.txt
    http://www.snailbook.com/docs/userauth.txt
    http://www.snailbook.com/docs/connection.txt










Volver al índice.