ssh -L reenvía varios puertos


129

Actualmente estoy ejecutando un montón de:

sudo ssh -L PORT:IP:PORT root@IP

donde IP es el objetivo de una máquina segura y PORT representa los puertos que estoy reenviando.

Esto se debe a que utilizo muchas aplicaciones a las que no puedo acceder sin este reenvío. Después de realizar esto, puedo acceder a través de localhost:PORT.

El problema principal ocurrió ahora que en realidad tengo 4 de estos puertos que tengo que reenviar.

Mi solución es abrir 4 shells y buscar constantemente mi historial hacia atrás para buscar exactamente qué puertos necesitan ser reenviados, etc., y luego ejecutar este comando, uno en cada shell (tener que completar contraseñas, etc.).

Si tan solo pudiera hacer algo como:

sudo ssh -L PORT1+PORT2+PORT+3:IP:PORT+PORT2+PORT3 root@IP

entonces eso ya sería de gran ayuda.

¿Hay alguna forma de hacer esto más fácil?

Respuestas:


195

La -Lopción se puede especificar varias veces dentro del mismo comando. Cada vez con diferentes puertos.


20
Al principio no entendí esta respuesta. Así que publicando un ejemplo aquí por si alguien sufre lo mismo. El autor quiso decir "ssh -L puerto0: ip: puerto0 -L puerto1: ip: puerto1 ..."
Mong H. Ng

96

Exactamente lo que respondió NaN , especifica varios argumentos -L. Hago esto todo el tiempo. A continuación, se muestra un ejemplo de reenvío multipuerto:

ssh remote-host -L 8822:REMOTE_IP_1:22 -L 9922:REMOTE_IP_2:22

Nota : Esto es lo mismo que -L localhost:8822:REMOTE_IP_1:22si no lo especifica localhost.

Ahora con esto, ahora puede (desde otra terminal) hacer:

ssh localhost -p 8822

para conectarse al REMOTE_IP_1puerto22

y de manera similar

ssh localhost -p 9922

para conectarse al REMOTE_IP_2puerto22

Por supuesto, no hay nada que le impida envolver esto en un script o automatizarlo si tiene muchos hosts / puertos diferentes para reenviar y a ciertos específicos.

Espero que esto ayude.


Gran complemento a la respuesta de Nan. Gracias.
AFP_555

1
Tenga cuidado con esto: "Nota: Esto es lo mismo que -L localhost: 8822: REMOTE_IP_1: 22 si no especifica localhost". Esto solo es cierto si la configuración de GatewayPorts es 'no', que es ciertamente el predeterminado. Pero considerando las implicaciones si no es así, debería verificar la configuración o, mejor aún, ser explícito y usar "-L localhost: 8822 ...".
David

Estoy de acuerdo con @David By default, anyone (even on different machines) can connect to the specified port on the SSH client machine. However, this can be restricted to programs on the same host by supplying a bind address: ssh -L 127.0.0.1:80:intra.example.com:80 gw.example.com ssh.com/ssh/tunneling/example
Karl Pokus

24

Puede usar la siguiente función bash (solo agréguela a su ~/.bashrc):

function pfwd {
  for i in ${@:2}
  do
    echo Forwarding port $i
    ssh -N -L $i:localhost:$i $1 &
  done  
}

Ejemplo de uso:

pfwd hostname {6000..6009}

2
Utilizar -fpara ejecutar en segundo plano
Karl Pokus

Ehmmm ... ¿por qué quieres hacerlo de esa manera?
Anton Bessonov

14

Para las personas que reenvían varios puertos a través del mismo host, pueden configurar algo como esto en su ~ / .ssh / config

Host all-port-forwards Hostname 10.122.0.3 User username LocalForward PORT_1 IP:PORT_1 LocalForward PORT_2 IP:PORT_2 LocalForward PORT_3 IP:PORT_3 LocalForward PORT_4 IP:PORT_4

y se convierte en una simple ssh all-port-forwardsdistancia.


Me gusta este enfoque.
BMW

8

jbchichoko y yuval han dado soluciones viables. Pero la respuesta de jbchichoko no es una respuesta flexible como función, y los túneles abiertos por la respuesta de yuval no se pueden cerrar ctrl+cporque se ejecutan en segundo plano. Doy mi solución a continuación resolviendo los dos defectos:

Definir una función en ~/.bashrco~/.zshrc :

# fsshmap multiple ports
function fsshmap() {
  echo -n "-L 1$1:127.0.0.1:$1 " > $HOME/sh/sshports.txt
  for ((i=($1+1);i<$2;i++))
  do
    echo -n "-L 1$i:127.0.0.1:$i " >> $HOME/sh/sshports.txt
  done
  line=$(head -n 1 $HOME/sh/sshports.txt)
  cline="ssh "$3" "$line
  echo $cline
  eval $cline
}

Un ejemplo de ejecución de la función:

fsshmap 6000 6010 hostname

Resultado de este ejemplo:

Puedes acceder 127.0.0.1:16000~16009al mismo quehostname:6000~6009


3

Uno de los beneficios de iniciar sesión en un servidor con reenvío de puertos es facilitar el uso de Jupyter Notebook. Este enlace proporciona una excelente descripción de cómo hacerlo. Aquí me gustaría hacer un resumen y una expansión para que todos ustedes se refieran.

Situación 1. Inicie sesión desde una máquina local llamada Host-A (por ejemplo, su propia computadora portátil) a una máquina de trabajo remota llamada Host-B.

ssh user@Host-B -L port_A:localhost:port_B
jupyter notebook --NotebookApp.token='' --no-browser --port=port_B

Luego puede abrir un navegador e ingresar: http: // localhost: port_A / para hacer su trabajo en el Host-B pero verlo en el Host-A.

Situación 2. Inicie sesión desde una máquina local llamada Host-A (por ejemplo, su propia computadora portátil) a una máquina de inicio de sesión remota llamada Host-B y desde allí inicie sesión en la máquina de trabajo remota llamada Host-C. Este suele ser el caso de la mayoría de los servidores analíticos dentro de las universidades y se puede lograr utilizando dos ssh -Lconectados con -t.

ssh -L port_A:localhost:port_B user@Host-B -t ssh -L port_B:localhost:port_C user@Host-C
jupyter notebook --NotebookApp.token='' --no-browser --port=port_C

Luego puede abrir un navegador e ingresar: http: // localhost: port_A / para hacer su trabajo en el Host-C pero verlo en el Host-A.

Situación 3. Inicie sesión desde una máquina local llamada Host-A (por ejemplo, su propia computadora portátil) a una máquina de inicio de sesión remota llamada Host-B y desde allí inicie sesión en la máquina de trabajo remota llamada Host-C y finalmente inicie sesión en la máquina de trabajo remota Host- RE. Este no suele ser el caso, pero puede suceder en algún momento. Es una extensión de la Situación 2 y la misma lógica se puede aplicar en más máquinas.

ssh -L port_A:localhost:port_B user@Host-B -t ssh -L port_B:localhost:port_C user@Host-C -t ssh -L port_C:localhost:port_D user@Host-D
jupyter notebook --NotebookApp.token='' --no-browser --port=port_D

Luego puede abrir un navegador e ingresar: http: // localhost: port_A / para hacer su trabajo en Host-D pero verlo en Host-A.

Tenga en cuenta que port_A, port_B, port_C, port_D pueden ser números aleatorios, excepto los números de puerto comunes que se enumeran aquí . En la situación 1, port_A y port_B pueden ser iguales para simplificar el procedimiento.


Un recordatorio, el mismo puerto en diferentes servidores son puertos diferentes. Por lo tanto, siempre podría facilitar las cosas especificando un número de puerto idéntico.
Fei Yao

3

En mi empresa, tanto yo como los miembros de mi equipo necesitamos acceso a 3 puertos de un servidor "objetivo" no accesible, así que creé un túnel permanente (es decir, un túnel que puede ejecutarse en segundo plano de forma indefinida, consulte los parámetros -fy -N) desde un servidor accesible a el objetivo. En la línea de comando del servidor accesible ejecuté:

ssh root@reachableIP -f -N  -L *:8822:targetIP:22  -L *:9006:targetIP:9006  -L *:9100:targetIP:9100

Usé usuario rootpero tu propio usuario funcionará. Deberá ingresar la contraseña del usuario elegido (incluso si ya está conectado al servidor accesible con ese usuario).

Ahora el puerto 8822 de la máquina accesible corresponde al puerto 22 de la de destino (para ssh / PuTTY / WinSCP) y los puertos 9006 y 9100 en la máquina accesible corresponden a los mismos puertos de la de destino (alojan dos servicios web en mi caso ).


1

Desarrollé loco para que me ayude con el reenvío ssh. Se puede utilizar para compartir los puertos 5000 y 7000 en forma remota localmente en los mismos puertos:

pip install loco

loco listen SSHINFO -r 5000 -r 7000

1

Si desea una solución simple que se ejecute en segundo plano y sea fácil de matar, use un conector de control

# start
$ ssh -f -N -M -S $SOCKET -L localhost:9200:localhost:9200 $HOST
# stop
$ ssh -S $SOCKET -O exit $HOST

1

Aquí hay una solución inspirada en la de Yuval Atzmon.

Tiene algunos beneficios sobre la solución inicial:

  • primero crea un proceso en segundo plano único y no uno por puerto
  • genera el alias que te permite matar tus túneles
  • se une solo a 127.0.0.1 que es un poco más seguro

Puede usarlo como:

  • tnl your.remote.com 1234
  • tnl your.remote.com {1234,1235}
  • tnl your.remote.com {1234..1236}

Y finalmente matarlos a todos con tnlkill.

function tnl {
  TUNNEL="ssh -N "
  echo Port forwarding for ports:
  for i in ${@:2}
  do
    echo " - $i"
    TUNNEL="$TUNNEL -L 127.0.0.1:$i:localhost:$i"
  done
  TUNNEL="$TUNNEL $1"
  $TUNNEL &
  PID=$!
  alias tnlkill="kill $PID && unalias tnlkill"
}

-1

Puedes usar esta función zsh (probablemente también funcione con bash) (Ponlo en ~/.zshrc):

ashL () {
    local a=() i
    for i in "$@[2,-1]"
    do
        a+=(-L "${i}:localhost:${i}")
    done
    autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -NT "$1" "$a[@]"
}

Ejemplos:

ashL db@114.39.161.24 6480 7690 7477

ashL db@114.39.161.24 {6000..6050} # Forwards the whole range. This is simply shell syntax sugar.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.