Redirigir puertos a través de SSH

En ocasiones necesitamos transmitir datos a través de un socket entre distintas máquinas, como por ejemplo una conexión Telnet, una descarga de ficheros FTP, una consulta SQL o cualquier otro tipo de transmisión.

Esos datos viajan en crudo por la red, de modo inseguro, lo cual significa que podrían ser interceptados por cualquier nodo que se encuentre en el camino entre el origen y el destino, es decir, robados.

No podemos evitar que estos datos sean capturados, pero lo que sí podemos evitar es que sean interpretados y entendidos por terceros, encriptando la comunicación.

SSH es la herramienta que nos permite hacer conexiones seguras entre máquinas. Su uso más habitual es el de conectarse remotamente a un intérprete de comandos.

Sin embargo, ofrece otras posibilidades, como crear túneles encriptados entre distintas máquinas.
Supongamos que queremos realizar una conexión telnet desde el host1 hacia el host2:

host1$ telnet host2

Esta comunicación es totalmente abierta y puede ser interceptada. Para protegerla, redirigiremos un puerto escogido arbitrariamente (por ejemplo 5000) en el host 1 hacia el puerto 23 (telnet) del host2.

De este modo conseguiremos que todos los datos enviados al puerto 5000 del host1 viajen encriptados por el túnel que ssh le abre a través del puerto 22 del host2 y luego sean redirigidos al puerto 23 del host2, llegando así a su destino final.

Para hacerlo, es necesario que conozcamos el nombre de usuario y contraseña del host2.

Para abrir el túnel escribimos:

host1$ ssh -R 5000:localhost:23 usuariohost2@host2

o bien:

host1$ ssh -L 5000:host2:23 usuariohost2@host2

Ambas opciones son equivalentes. Para establecer la conexión telnet, ya no nos referimos al host2 sino al puerto elegido en el host1:

host1$ telnet localhost 5000

Con esto convertimos cualquier comunicación en segura, sea telnet o de otro tipo. Investigando un poco más veremos que gracias a la potencia de SSH estas redirecciones también pueden realizarse a terceras máquinas, lo que nos permitiría que con un sólo punto de entrada pudiéramos acceder de forma segura desde toda una LAN hasta otra LAN distinta.


15 comentarios, deja el tuyo

Deja tu comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

*

*

  1. Responsable de los datos: Miguel Ángel Gatón
  2. Finalidad de los datos: Controlar el SPAM, gestión de comentarios.
  3. Legitimación: Tu consentimiento
  4. Comunicación de los datos: No se comunicarán los datos a terceros salvo por obligación legal.
  5. Almacenamiento de los datos: Base de datos alojada en Occentus Networks (UE)
  6. Derechos: En cualquier momento puedes limitar, recuperar y borrar tu información.

  1.   nano dijo

    La teoría se ve sumamente interesante, pero aún más lo sería si viésemos un caso práctico.

    Pero la verdad es que, aún siendo cortito me encantó el artículo.

    1.    igual dijo

      quiza viendo la wiki te inspiras https://wiki.archlinux.org/index.php/Secure_Shell#Forwarding_other_ports
      y lo mismo, pero el apartado autossh https://wiki.archlinux.org/index.php/Secure_Shell#Autossh_-_automatically_restarts_SSH_sessions_and_tunnels
      en realidad, cualquier cosa podes mandar por ssh, sea streaming, conecciones a x host. etc. que por x motivo las quieras encriptar.
      y el securecrt rules

  2.   Tesla dijo

    Uso algunas veces SSH a nivel muy básico. El puerto por defecto es el 22, no?

    Entonces, si entiendo bien, mi pc es el host 1 y el que quiero conectar el host2, este túnel crearía una conexión entre el puerto 5000 y su puerto 23, para luego acabar en el puerto 22?

    Por que las razones de cambiar de puertos? Se puede crear un túnel con el puerto 22?

    Muy interesante el artículo. Al igual que nano, me quedo con ganas de mas!

    1.    Getafix dijo

      Efectivamente SSH usa por defecto el puerto 22 (aunque se puede cambiar). Este puerto es el que utilizaría la comunicación real entre los dos hosts. Es el que tienes que asegurarte que esté abierto y no te lo corte ningún firewall. Pero para el usuario es totalmente transparente. Puedes olvidarte de él. En el ejemplo, la redirección se hace entre los puertos 5000 y 23. Esos dos son los únicos de los que te tienes que preocupar. El usuario verá que todo lo que mande al puerto 5000 de su host aparece en el 23 del host de destino.
      Óbviamente, cada usuario puede redirigir los puertos que considere oportuno.

      Gracias por vuestros comentarios. Este es mi primer post y vuestras opiniones servirán para que el próximo sea mejor.

  3.   eliotime3000 dijo

    ¿Eso se puede hacer también con las VPS?

  4.   dhunter dijo

    Ok este es mi caso, PC1 tiene acceso a un server, pero PC2 no, ambas se conectan por ssh, quiero tener acceso en PC2, pero que puerto de PC1 redirecciono? si en realidad lo que quiero es llegar al puerto del server desde PC2 y que los paquetes tengan como ip origen a PC1. me hago entender?

    1.    Getafix dijo

      Te haces entender. En este caso necesitas que PC1 redirija un puerto de PC2 al puerto 22 del servidor:

      PC2$ ssh -L 5000:Servidor:22 usuarioPC1@PC1

      y, manteniendo esta conexión abierta, desde otro terminal:

      PC2$ ssh usuarioServidor@localhost -p 5000

      y ya estás dentro.

      1.    dhunter dijo

        Al fin una solución funcional!! Gracias Getafix, me has dado un mundo de posibilidades!!

        1.    Getafix dijo

          Me alegro!

  5.   elav dijo

    Excelente artículo. Bienvenido a DesdeLinux 😀

    ¿Y que hacer si tenemos el 22 bloqueado? Jajaja..

    1.    Getafix dijo

      Gracias elav.
      Si tienes el puerto 22 bloqueado, mmmm, tendremos que buscar una alternativa para hackear el firewall XD

    2.    eliotime3000 dijo

      Y lo peor de todo (caso hipotético): que esté bloqueado por el proveedor de VPS.

  6.   AGR dijo

    Acabo de hacer hace unas horas un examen con preguntas al respecto 😛

  7.   Mario dijo

    Yo no diria que :
    host1$ ssh -R 5000:localhost:23 usuariohost2@host2
    es equivalente a la otra linea de comandos… la que tiene el -L.
    Puesto que -R indica que el puerto que se abre a nuevas conexiones esta del lado remoto, es decir del lado de tu servidor ssh; mientras que -L abre un puerto del lado Local, del lado cliente para recibir nuevas conexiones.

    La traduccion de la linea:
    host1$ ssh -R 5000:localhost:23 usuariohost2@host2
    seria algo así: Estando en host1, conectarme al servidor ssh (puerto 22) del host2 con mi usuario usuariohost2 y reenviar las conexiones que se generen en el puerto remoto 5000 del host2 al puerto 23 en host1 (mi localhost)

    Si no es asi, corriganme! 😉

    —–

    Por otro lado … si en un servidor tenemos bloqueada la entrada de conexiones al puerto 22, es decir no podemos conectarnos remotamente al servidor ssh; lo que se puede hacer es; que desde el servidor (un sysadmin amigo detras del firewall del sistema remoto host2) se ejecute una linea de comandos:

    host2$ nohup ssh -fN -R 6000:localhost:22 usuariohost1@host1

    -f se va a background
    -N no ejecuta ningun comando en el remoto
    nohup evita que al hacer logout se corte la ejecucion del comando

    host1$ ssh usuariohost2@localhost -p 6000

    De esta manera desde host1 generamos una conexion a localhost (el mismo host1) en el puerto 6000 que nos reenviara la conexion al puerto 22 de sistema remoto host2, en el cual loguearemos con el usuariohost2.

    Esto permitiria (no lo probe, pero suena a que funciona) de loguearnos en un server ssh bloqueado por firewal con una ayudita desde adentro! 😀

    Esto ultimo lo lei de una explicacion hecha en la revista The Geek Stuff
    http://www.thegeekstuff.com/2013/11/reverse-ssh-tunnel/

    Me gusta mucho su publicación; los leo seguido!
    Saludos.

    1.    Getafix dijo

      Llevas razón. Hay un error en el artículo. Las redirecciones no son equivalentes. El comando host1$ ssh -R 5000:localhost:23 usuariohost2@host2 realiza la redirección inversa, es decir que redirige el puerto 5000 remoto al 23 local, lo contrario de lo que hace el comando con -L.
      Gracias por la corrección.