Diferencia entre revisiones de «Tunneling Vía SSH»

De FJWiki
Saltar a: navegación, buscar
 
Línea 28: Línea 28:
 
Digamos que estamos en "A", en una red privada detrás de un "proxy" (o gateway, o lo que hubiera), y necesitamos copiar archivos y entrar desde una máquina externa "C". Se necesita tener acceso a C.
 
Digamos que estamos en "A", en una red privada detrás de un "proxy" (o gateway, o lo que hubiera), y necesitamos copiar archivos y entrar desde una máquina externa "C". Se necesita tener acceso a C.
  
<source lang=bash>
+
<source>
 
+-+                              +-+
 
+-+                              +-+
 
|A| ---> Proxy <--> internet <--> |C|
 
|A| ---> Proxy <--> internet <--> |C|

Revisión actual del 16:23 17 oct 2011

Motivación

¿Cuántas veces hemos necesitado conectarnos a máquinas detrás de proxys en forma directa? ¿Sólo hay salida de algunos puertos y se necesitan pasar algunos servicios extra en un momento particular? Estas cuestiones se pueden resolver fácilmente con SSH, que usando la implementación de OpenSSH permite hacer túneles de puertos específicos hacia hosts específicos. Para hacer un proxy "genérico" pueden ver Proxy Vía SSH.

Sintáxis

La sintaxis que necesitamos conocer del SSH necesaria para el tunneling es la siguiente (sacada del man ssh(1)):

# ssh [-p port] [-f]
      [-L [bind_address:]port:host:hostport]
      [-R [bind_address:]port:host:hostport]
      [user@]hostname [command]

La opción -p nos permite especificar un puerto de conexión de ssh distinto al estándar.

La opción -f manda el comando ssh después de pedirte el password a background.

La opción -L nos permite crear un puente entre el puerto local port (siempre visto desde el cliente) hacia host:hostport abierto en el servidor ssh.

La opción -R nos permite crear un puente entre el puerto remoto port hacia host:hostport abierto desde el cliente.

Si la conexión sólo se va a usar como túnel, puede especificarse algún comando de bajos recurso repetitivo para mantener la conexión activa, por ejemplo ping -i 60 localhost >/dev/null, ó "while test 1; do sleep 10; done". Además se puede combinar con la opción -f. Si se utiliza con -f se debe luego usar kill para terminar con la conexión.

Ejemplos

Caso 1: Permitir entrada externa a una máquina en una red privada

Digamos que estamos en "A", en una red privada detrás de un "proxy" (o gateway, o lo que hubiera), y necesitamos copiar archivos y entrar desde una máquina externa "C". Se necesita tener acceso a C.

+-+                               +-+
|A| ---> Proxy <--> internet <--> |C|
+-+                               +-+

En "A" podría ejecutarse el siguiente comando (si el acceso es vía el puerto 22, si no fuera así usar la opción -p #puerto-para-llegar-a-C):

[usuarioA@A ~]$ ssh -R 8022:localhost:22 usuarioC@C

Esto permitirá que desde C se pueda ejecutar lo siguiente para copiar archivos o loguearse vía ssh en A:

[usuarioC@C ~]$ scp -P 8022 /origen usuarioA@127.0.0.1:/destino
[usuarioC@C ~]$ ssh -p 8022 usuarioA@127.0.0.1

Ahí lo que se hizo fue crear un túnel entre el puerto 8022 en C hacia el 22 en A.

Hay que tener en cuenta que al no especificar el bind_address en la opción -R se está abriendo el puerto remoto sólo en "localhost". Además, si se quieren abrir puertos privilegiados hay que tener los privilegios de root o que la configuración del sshd permita eso.

Caso 2: Copiar entre dos servidores que no se pueden conectar directamente vía un intermediario

Deseamos copiar archivos desde "C" hacia "A" vía un puente en "B" (para no dejar ahí los archivos, quizás por falta de espacio ahí). Tenemos el siguiente esquema:

+-+      +-+      +-+
|A| <--> +B+ <--> |C|
+-+      +-+      +-+

Queremos que desde "A" podamos "jalar" los archivos en "C", entonecs necesitaremos el siguiente túnel:

+-+      +-+      +-+
|A| ---> +B+ ---> |C|
+-+      +-+      +-+
 |                 ^
 |                 |
 \-----------------/

Para ello estando en "A" podemos hacer:

[usuarioA@A ~]$ ssh -L 8022:<hostC>:22 usuarioB@B

Con esto, hemos abierto el puerto 8022 en el localhost de "A" como túnel hacia el puerto 22 del host "C".

Lo cual nos permite hacer desde "A" ssh o scp a "C":

[usuarioA@A ~]$ scp -P 8022 usuarioC@127.0.0.1:/origen/en/C /destino
[usuarioA@A ~]$ scp -P 8022 /origen usuarioC@127.0.0.1:/destin/en/C
[usuarioA@A ~]$ ssh -p 8022 usuarioC@127.0.0.1

Caso 3: Encadenando varios servidores

En este caso tenemos cuatro máquinas A, B, C y D, y queremos acceder desde "A" hacia "D". Este sería el esquema final al que se quiere llegar:

+-+      +-+      +-+      +-+
|A| ---> +B+ ---> |C| ---> |D|
+-+      +-+      +-+      +-+
 |                          ^
 |                          |
 \--------------------------/

Una propuesta sería encadenarlo así:

+-+      +-+      +-+      +-+
|A| ---> +B+ ---> |C| ---> |D|
+-+      +-+      +-+      +-+
 |                          ^
 |                          |
 \--------O                 |
          |                 |
          |                 |
          \-----------------/

Donde la O representa el primer nodo de puentes.

Entonces debemos crear un puente de un puerto en A hacia un puerto en B y luego desde ese puerto hacia D vía C:

[usuarioA@A ~]$ ssh -L 8022:localhost:8023 usuarioB@B
[usuarioB@B ~]$ ssh -L 8023:<hostD>:22 usuarioC@C

Encontes ya en "A" se pueden ejecutar cosas como:

[usuarioA@A ~]$ scp -P 8022 usuarioD@127.0.0.1:/origen/en/D /destino
[usuarioA@A ~]$ scp -P 8022 /origen usuarioD@127.0.0.1:/destin/en/D
[usuarioA@A ~]$ ssh -p 8022 usuarioD@127.0.0.1