Túneles SSH

28 Sep 2008

¡Qué cosa tan útil y qué desconocida!

La verdad es que el tema de los túneles SSH es una herramienta útil para traer de cabeza a cualquier sysadmin que quiera “ver” qué es lo que hacen sus empleados. Pero mira que lo había utilizado veces y no terminaba de ver cómo funcionaba, lo que, habiendo trabajado con Infraestructuras de Clave Pública (PKI), servidores HTTPS y demás historias basadas en temas criptográficos me causaba desazón.

Y el problema es que el 99% de los tutoriales en los que se cuenta cómo hacer un túnel SSH no dejan ver (o yo he leído tan rápido o soy tan tonto que no lo he visto), con ánimo de mostrarlo todo más sencillo, un pequeño aspecto, que es el que voy a intentar mostrar aquí.

Lo que a mi me parecía extraño de los tutoriales era lo siguiente, utilizando como ejemplo un servidor de VNC (escritorio remoto): en ningún momento se ejecutaba en el servidor (el “otro” punto del túnel) un comando que enganchara el túnel al puerto deseado. Aunque esto no se haya entendido muy bien, espero que con mi tutorial se entienda “el todo”, incluyendo la teoría por debajo, un poco mejor:

<!--more-->SSH es un sistema que, utilizando SSL, permite iniciar una sesión remota en otro equipo que disponga de un servidor SSH.  Vale muy bien, tenemos sesión remota de línea de comandos. Y aquí llega el punto: con una sesión remota podemos hacer

lo que queramos en esa máquina, lo que sea. Muy bien, pues los túneles SSH son, simplemente, una “facilidad” que tiene el cliente SSH para hacer por nosotros algo más que conectarse y tener una terminal remota. ¿Cómo se consigue esta funcionalidad?  Pues, el comando es

ssh -L 666:server_remoto_2:80 server_remoto -l billy

y en palabras sencillas, es lo siguiente:

Mira, crea una terminal remota a la máquina server_remoto autenticándote como billy (seguramente pedirá una contraseña si no hemos hecho intercambio del hash de la clave privada, pero eso es otra historia). Acto seguido, ábreme aquí donde estamos el puerto 666. Cuando alguien se conecte a ese puerto en este ordenador te voy a pedir que hagas lo siguiente: coge todo lo que se envíe por ahí, llévalo a la máquina server_remoto, y como allí tienes permisos para hacer de todo ya que tenemos sesión remota, abre otra conexión normal a servidor_remoto_2 en el puerto 80, y envíalo. Haz lo mismo con los datos de vuelta.

Osea, que ahora, si abro un navegador y me conecto a localhost:666, el túnel SSH cifrará los datos, los llevará hasta server_remoto y desde ahí abrirá una conexión a server_remoto_2:80 (recordemos que tenemos una sesión abierta, y desde ahí nuestro cliente puede hacer lo que quiera, como abrir conexiones, por ejemplo). Por tanto, los datos estarán “ocultos” entre nosotros y server_remoto, pero no entre server_remoto y server_remoto_2 ya que, de hecho, en server_remoto_2 no tiene ni porqué haber un servidor de SSH.

¿Cómo podríamos conseguir que en ningún momento se mandaran datos en claro? Pues teniendo un servidor SSH en el mismo ordenador donde está el servicio al que nos queremos conectar. Por ello, como el ordenador donde estamos abriendo una sesión SSH y donde se encuentra el servicio al que queremos conectar es el mismo, el comando sería algo como:

ssh -L 666:localhost:80 server_remoto -l billy

Osea, que resumiendo, si tienes una máquina en la que hay un servidor VNC y no te quieres conectar mandando la contraseña, las pulsaciones de teclado, y todo lo demás en claro, lo que deberíashacer es lo siguiente (atención al punto 2, que puede tener algo de complicado conceptualmente, sobre todo el concepto “localhost”, que en este comando está bastante distorsionado con respecto a lo que uno podría pensar):

  1. Tener en ese mismo servidor un servidor SSH.
  2. Ejecutar ssh -L 666:localhost:5900 serverremoto -l billy
    (siendo server
    remoto donde están ambos servidores, le estamos diciendo que una vez ha llevado los datos encriptados ahí, se conecte a ese localhost en el puerto 80. Este “localhost” es el punto que normalmente no se explica, aquí “localhost” lo interpretará en server_remoto, con lo cual hace referencia a server_remoto, no al ordenador donde se ejecuta el comando. *666 es el puerto donde acaba el túnel en el ordenador donde ejecutamos el comando y 5900 donde está el servicio en *server_remoto).
  3. Conectar nuestro cliente de VNC a localhost:666 (ahora localhost sí que hace referencia a la máquina donde se ejecuta el comando). El proceso ejecutado en el paso dos ya sabe qué tiene que hacer con esos datos que envía el cliente de VNC (recomiendo ahora ir fijándose en el comando): llevarlos encriptados hasta server_remoto, donde ya hay una conexión de sesión abierta, abrir ahí una conexión a localhost:5900, y meter ahí los datos, haciendo lo mismo con los de vuelta.

Espero que haya quedado claro, ya que hay algunos puntos que no se explican bien en los tutoriales. Y lo que fastidia es que los sigues y todo funciona, cuando lo interesante es saber qué demonios está pasando por debajo y qué significa cada parámetro para poder adaptar esto a nuestras necesidades, por ejemplo, hacer un túnel de varios enlaces. En el caso de que quieras realizar algo, y que sea más complicado de seguir el origen, siempre puedes hacer que haya dos o tres túneles seguidos, túneles dentro de otros (como muñecas Matrioska), o incluso túneles de ida y vuelta que pueden desorientar al trabajador del CNI o el GDT menos pintado.