Sesión SSH a través de jumphost mediante reenvío de puerto remoto

Sesión SSH a través de jumphost mediante reenvío de puerto remoto

Tenemos un problema al realizar conexiones SSH a través del reenvío de puertos remoto.

El escenario es una red empresarial, donde un servidor en la red interna (llamémoslo "origen") debe iniciar sesión a través de SSH en un servidor en la DMZ ("destino"). Dado que el servidor de destino en la DMZ está bloqueado para conexiones desde la red interna (y ni siquiera puede verse desde la red interna), tenemos un host de salto en la DMZ por el que pasamos ("jumphost"). Hacemos esto configurando el reenvío de puertos remoto en el jumphost.

Ejecutamos este comando desde el servidor de origen en la red interna, al jumphost:

origin> ssh -R *:1234:target:22 myusername@jumphost

Esto es para establecer una sesión SSH en el jumphost, hacer que comience a escuchar en el puerto 1234 (solo un ejemplo de número de puerto arbitrario) y reenviar conexiones en ese puerto al puerto 22 (SSH) del servidor de destino.

Luego establecemos una segunda sesión SSH, aún desde el servidor de origen al jumphost, en el puerto 1234, que luego se conecta al servidor de destino en el puerto 22; esta es nuestra sesión SSH "real" donde podemos hacer nuestro trabajo en el servidor de destino:

origin> ssh jumphost -P 1234

Configuración

El host de salto se ha configurado para permitir el reenvío de puertos remoto, con las siguientes configuraciones en sshd_config:

AllowTcpForwarding yes
GatewayPorts yes

Además, existen aberturas de firewall entre el servidor de origen y el host de salto, para el puerto 22 (para la conexión SSH inicial para configurar el reenvío de puerto remoto) y el puerto 1234 (para la conexión SSH posterior en el puerto reenviado). También hay un firewall entre el jumphost y el objetivo, que se abrió en el puerto 22.

Resultado

Cuando establecemos la segunda conexión (la que pasa por el puerto reenviado), la conexión se cierra inmediatamente ("conexión cerrada por host remoto").

La ejecución de tcpdump en el servidor de destino no muestra actividad, es decir, parece que la conexión se bloquea.

Sin embargo, podemos establecer con éxito una sesión SSH regular desde el jumphost hasta el objetivo. Solo cuando ingresa a través del puerto reenviado se cierra la conexión, aunque ambos se conectan al destino en el puerto 22.

Es más, si hacemos que el reenvío de puertos apunte a un servidor en la red interna (es decir, una conexión desde el origen en la red interna, al jumphost en la DMZ y de regreso a un tercer servidor en la red interna), entonces el SSH la sesión se establece exitosamente.

Especulación y preguntas.

Todo esto me lleva a creer que está en juego alguna configuración de seguridad de red, que impide la conexión a través del puerto reenviado en el servidor de salto al servidor de destino dentro de la DMZ. Desafortunadamente no tengo el conocimiento suficiente para saber:

(1) ¿Es una conexión SSH proveniente del servidor de origen, a través de un puerto reenviado en el servidor de salto, "diferente", desde el punto de vista de la política de seguridad de la red, que técnicamente podría bloquearse y, de ser así, cómo? ¿Y qué habría que hacer para levantar esa restricción?

(2) ¿Alguna otra razón por la que esta conexión no está permitida: configuración del firewall, configuración del enrutador, configuración de SSH en el origen o jumphost, algo más?

(3) ¿Podría fallar porque el servidor de origen no conoce el servidor de destino y, por lo tanto, el primer comando ssh no funciona según lo previsto? En otras palabras, ¿el nombre de host especificado en el primer comando ssh ("destino") se interpreta en el cliente (origen) o en el servidor al que nos estamos conectando para crear el túnel (el jumphost)?

Lo que más me desconcierta es que se puede establecer una sesión SSH regular desde el jumphost hasta el objetivo. Pensaría que la conexión SSH que ingresa a través del puerto reenviado sería la misma, pero de alguna manera no lo es.

Cualquier aportación es muy apreciada.

Respuesta1

Parece que debería utilizar el reenvío de puertos local en lugar del reenvío de puertos remoto. Es posible que desee consultar la siguiente publicación de blog útil de Dirk Loss:

Incluye el siguiente diagrama ilustrativo:

Reenvío de puertos ssh: local vs remoto

Para leer el diagrama necesita saber que describe las relaciones entre 4 roles diferentes involucrados en la creación y utilización de un túnel SSH:

  • un cliente ssh (es decir ssh, el cliente de línea de comandos OpenSSH) utilizado para establecer el túnel;
  • un servidor ssh (es decir sshd, el demonio del servidor OpenSSH) utilizado para mantener el otro extremo del túnel;
  • un servidor de aplicaciones (por ejemplo, otro servidor ssh o un servidor http);
  • un cliente de aplicación (por ejemplo, otro cliente ssh o un navegador web) que desea acceder al servidor de aplicaciones a través del túnel.

También es importante comprender que los dos tipos diferentes de reenvío corresponden a dos casos de uso diferentes:

  • Reenvío local: donde el cliente de la aplicación se conecta a través del cliente ssh

  • Reenvío remoto: donde el cliente de la aplicación se conecta a través del servidor ssh

El reenvío remoto se denomina así porque el reenvío se realiza de forma remota (en el servidor ssh) en lugar de localmente (en el cliente ssh). También encuentro que "reenvío remoto = reenvío inverso" es un mnemónico útil.

Como puede ver, para iniciar una conexión desde un sshcliente en el originhost a través de un sshdservidor en un proxy jumphosta un tercer targethost, tendría que utilizar el reenvío de puertos local. El reenvío de puertos remoto es para el caso en el que desea que el punto de entrada al túnel esté ubicado en el host que ejecuta el sshdservidor en lugar de en el host que ejecuta el sshcliente.

En la página de manual, la sintaxis de reenvío de puertos local está escrita de la siguiente manera:

ssh -L [bind_address:]port:host:hostport user@remote

Esto se puede escribir de forma más intuitiva como sigue:

ssh -L [local_bind_address:]local_port:remote_host:remote_host_port user@proxy_host

O, usando sus convenciones de nomenclatura:

ssh -L [origin_bind_address:]origin_port:target_host:target_host_port user@jump_host

Si modificamos su comando para usar el reenvío de puerto local, terminaremos con lo siguiente:

user@origin:~$ ssh -L *:1234:target:22 myusername@jumphost

información relacionada