Cómo configurar un acceso directo para una conexión SSH a través de un túnel SSH

22

Los servidores de producción de mi empresa (FOO, BAR ...) se encuentran detrás de dos servidores de puerta de enlace (A, B). Para conectarme al servidor FOO, tengo que abrir una conexión ssh con el servidor A o B con mi nombre de usuario JOHNDOE, luego desde A (o B) puedo acceder a cualquier servidor de producción que abra una conexión SSH con un nombre de usuario estándar (llamémoslo WEBBY).

Entonces, cada vez que tengo que hacer algo como:

ssh johndoe@a
...
ssh webby@foo
...
# now I can work on the server

Como puede imaginar, esto es una molestia cuando necesito usar scpo si necesito abrir rápidamente varias conexiones.

He configurado una clave ssh y también estoy usando .ssh / config para algunos accesos directos.

Me preguntaba si puedo crear algún tipo de configuración ssh para escribir

ssh foo

y dejar que SSH abra / reenvíe todas las conexiones por mí. ¿Es posible?

Editar

La respuesta de womble es exactamente lo que estaba buscando, pero parece que ahora no puedo usar netcat porque no está instalado en el servidor de puerta de enlace.

weppos:~ weppos$ ssh foo -vv
OpenSSH_5.1p1, OpenSSL 0.9.7l 28 Sep 2006
debug1: Reading configuration data /Users/xyz/.ssh/config
debug1: Applying options for foo
debug1: Reading configuration data /etc/ssh_config
debug2: ssh_connect: needpriv 0
debug1: Executing proxy command: exec ssh a nc -w 3 foo 22
debug1: permanently_drop_suid: 501
debug1: identity file /Users/xyz/.ssh/identity type -1
debug2: key_type_from_name: unknown key type '-----BEGIN'
debug2: key_type_from_name: unknown key type 'Proc-Type:'
debug2: key_type_from_name: unknown key type 'DEK-Info:'
debug2: key_type_from_name: unknown key type '-----END'
debug1: identity file /Users/xyz/.ssh/id_rsa type 1
debug2: key_type_from_name: unknown key type '-----BEGIN'
debug2: key_type_from_name: unknown key type 'Proc-Type:'
debug2: key_type_from_name: unknown key type 'DEK-Info:'
debug2: key_type_from_name: unknown key type '-----END'
debug1: identity file /Users/xyz/.ssh/id_dsa type 2
bash: nc: command not found
ssh_exchange_identification: Connection closed by remote host
Simone Carletti
fuente

Respuestas:

36

Como una versión más concreta de la respuesta de Kyle, lo que desea poner en su ~/.ssh/configarchivo es:

host foo
  User webby
  ProxyCommand ssh a nc -w 3 %h %p

host a
  User johndoe

Luego, cuando ejecutas "ssh foo", SSH intentará SSH a johndoe@a, run netcat( nc), luego realizará un SSH a webby@footravés de este túnel. ¡Mágico!

Por supuesto, para hacer esto, netcat necesita estar instalado en el servidor de puerta de enlace; Este paquete está disponible para todas las principales distribuciones y sistemas operativos.

womble
fuente
¡Excelente! Estaba tratando de resolver eso, nunca antes me había encontrado con esa situación exacta. Mantendré mi respuesta allí, en caso de que pueda ayudar a alguien con una situación menos específica en el futuro.
Kyle Brandt
He actualizado mi pregunta original, incluida la salida detallada de mi conexión. Parece que no puedo usar netcat. ¿Debería estar disponible por defecto?
Simone Carletti
No siempre, ¿tienes el poder de instalarlo? También podrías hacer esto con telnet, nunca lo he intentado ...
Kyle Brandt
También puede descargar netcat a su directorio de inicio y compilarlo allí. Luego, puede usar la ruta completa en el comando proxy, es decir, / home / userName / bin / nc
Kyle Brandt el
Acabo de comprobar la configuración del sistema. En Ubuntu netcat parece estar disponible de forma predeterminada, desafortunadamente los servidores de puerta de enlace funcionan con OpenSUSE. También consideraré instalar netcat en los servidores de puerta de enlace.
Simone Carletti
7

Puede usar la directiva ProxyCommand en su archivo ~ / .ssh / config, por ejemplo, para usar netcat como retransmisión:

host server2
    ProxyCommand ssh server1 nc server2 22

El simplemente usaría 'ssh server2'. La información de la página de manual para esta directiva se encuentra en 'man ssh_config'

Kyle Brandt
fuente
5

Prefiero un enfoque diferente que mantenga un túnel previamente autenticado para el servidor de puerta de enlace. En ~/.ssh/config:

Host a
    ControlMaster auto
    ControlPath ~/.ssh/control-master/%r@%h:%p

Luego en .bashrc:

s () {
        if ( ssh -O check a 2>&1 > /dev/null 2>&1 )
        then
                ssh -t a ssh $1
        else
                if [[ -S ~/.ssh/control-master/insyte@a:22 ]]
                then
                        echo "Deleting stale socket..."
                        rm ~/.ssh/control-master/insyte@a:22
                fi
                echo "Opening master session..."
                if ssh -Nf a
                then
                         ssh -t a ssh $1
                fi
        fi
 }

Entonces, para conectarse a foo:

s foo

La primera vez que lo conecte lo autenticará contra "a" y abrirá un túnel ssh persistente y en segundo plano. Las llamadas posteriores a "s" se abrirán casi instantáneamente a través del túnel previamente autorizado.

Funciona genial.

Insyte
fuente
2

Este tipo de funcionalidad existe en las versiones más recientes de OpenSSH y se puede usar haciendo

ssh -W server2 server1

¿Dónde server2está su destino previsto y server1es su servidor proxy? Puede hacer esto más fácil usando la ProxyCommandopción en su configuración ssh, algo como:

host = *.example.com
user = packs
port = 22
ProxyCommand ssh -W %h:%p server1
Scott Pack
fuente
Parece que para que esto funcione, necesita OpenSSH 5.4+ en las tres ubicaciones: escritorio, intermediario, destino. (Bueno, el primero y el último, sin duda).
Steve Bennett
@SteveBennett: He estado usando este método por un tiempo, funciona bastante bien. Tuve que volver al método netcat en un par de sistemas RHEL5, lo cual fue molesto.
Scott Pack
2

Cuando netcatno esté disponible en el proxy, intente este truco:

host foo
  User webby      
  ProxyCommand ssh a 'exec 3<>/dev/tcp/foo/22; cat <&3 & cat >&3;kill $!'

host a
  User johndoe

Entonces deberías poder hacerlo ssh foo.

Además, si tiene una versión reciente de ssh en un (es decir, con el -Wcomando para reenviar entradas y salidas estándar), puede usar:

host foo
  User webby
  ProxyCommand ssh -W foo:%p a

host a
  User johndoe

Finalmente, solo porque lo encontré genial (y no porque funcione en su caso particular, debido a las diferencias de nombre de usuario), la publicación de blog de un amigo señala cómo hacer que este tipo de cosas sea dinámico y recursivamente encadenar proxies SSH (junto con algunas cosas que no funcionan bien):

host */*
  ProxyCommand ssh ${$(dirname %h)/\%%/@} nc ${$(basename %h)#*%%} %p

Y luego ssh machine1/machine2debería darle un caparazón machine2, tunelizado machine1.

Me pregunto si usar sedcomandos personalizados en lugar de dirnamey basenamepodría no resolver el problema con diferentes nombres de usuario.

Paul Price
fuente
2

Esto se puede lograr haciendo ssh -At johndoe@a ssh webby@foo. El -Acomando reenvía su agente ssh (para que pueda evitar tener que volver a autenticarse en el proxy), mientras que -tasegura que existe un terminal en el proxy. La siguiente función bash puede ser útil:

ssh-bounce () {
    local cmd=""
    for i in "$@"; do
        cmd+="ssh -At $i "
    done
    $cmd
}
Marcin
fuente
Esta es, con mucho, la solución más simple. Ahora solo necesita otros 35 votos a favor. (Por cierto, el -A no hace nada por mí.)
Steve Bennett
0
weppos:~ weppos$ ssh foo -vv
[..]
bash: nc: command not found

Netcat no está instalado en a. Cuando ejecuta ssh host "command arg", commandse ejecuta en host, no en su máquina local.

Markdrayton
fuente
Sí, lo sé. Esto es exactamente lo que informé en un comentario a la respuesta de womble. :)
Simone Carletti el
0

Desde OpenSSH 7.3 (2016-08-01), la ProxyJumpopción y el -Jindicador de línea de comando correspondiente han estado disponibles para permitir una indirección más simple a través de uno o más bastiones SSH o "hosts de salto".

Eso elimina la dependencia del nccomando externo como se encuentra en la solución de Womble .

ssh -J johndoe@a webby@foo 

establecerá una conexión SSH desde su estación de trabajo al servidor de puerta de enlace acomo usuario johndoe y hará un túnel de la sesión SSH para alojar a un usuario Webby sobre eso.

Para simplificar eso, cree definiciones de host tanto en su ~/.ssh/configcomo en el que simplemente puede ejecutarssh foo

Host a
    User johndoe

Host foo
    User Webby 
    ProxyJump a
HBruijn
fuente