tutorial invoke_shell example python ssh paramiko

python - invoke_shell - Paramiko: Reenvío de puertos alrededor de un enrutador NAT



python ssh paramiko tutorial (2)

Configuración

  • LOCAL: una máquina local que creará una conexión ssh y emitirá comandos en un cuadro REMOTO.
  • PROXY: una instancia EC-2 con acceso ssh a LOCAL y REMOTO.
  • REMOTO: una máquina remota que se encuentra detrás de un enrutador NAT (inaccesible por LOCAL, pero que abrirá una conexión a PROXY y permitirá a LOCAL hacer un túnel hacia él).

Pasos de reenvío de puerto (a través de la línea de comando)

  1. Cree una conexión ssh desde REMOTO a PROXY para reenviar el tráfico ssh en el puerto 22 de la máquina REMOTE al puerto 8000 en el servidor PROXY.

    # Ejecutar desde la máquina REMOTE
    ssh -N -R 0.0.0.0:8000:localhost:22 PROXY_USER @ PROXY_HOSTNAME

  2. Cree un túnel ssh de LOCAL a PROXY y reenvíe el tráfico ssh de LOCAL: 1234 a PROXY: 8000 (que luego lo reenvía a REMOTO: 22).

    # Ejecutar desde la máquina LOCAL
    ssh -L 1234: localhost: 8000 PROXY_USER @ PROXY_HOSTNAME

  3. Cree la conexión ssh reenviada de LOCAL a REMOTO (a través de PROXY).

    # Ejecutar desde la máquina LOCAL en una nueva ventana de terminal
    ssh -p 1234 REMOTE_USER @ localhost

    # Ahora he ssh''d al cuadro REMOTO y puedo ejecutar comandos

Paramiko Research

He analizado un puñado de preguntas relacionadas con el reenvío de puertos utilizando Paramiko, pero no parecen abordar esta situación específica.

Mi pregunta

¿Cómo puedo usar Paramiko para ejecutar los pasos 2 y 3 anteriores? Básicamente me gustaría ejecutar:

import paramiko # Create the tunnel connection tunnel_cli = paramiko.SSHClient() tunnel_cli.connect(PROXY_HOSTNAME, PROXY_PORT, PROXY_USER) # Create the forwarded connection and issue commands from LOCAL on the REMOTE box fwd_cli = paramiko.SSHClient() fwd_cli.connect(''localhost'', LOCAL_PORT, REMOTE_USER) fwd_cli.exec_command(''pwd'')


¿El objetivo es solo despedir comandos SSH de PROXY o necesita reenviar otros puertos que no sean SSH también?

Si solo necesita SSH en el cuadro REMOTO, Paramiko admite el gateway de nivel SSH (le dice al PROXY sshd que abra una conexión a REMOTE y reenvíe el tráfico SSH en nombre de LOCAL) y el soporte ProxyCommand (reenvía todo el tráfico SSH a través de un comando local, que podría ser cualquier cosa capaz de hablar con la caja remota).

Parece que quieres lo primero para mí, ya que PROXY claramente ya tiene un sshd funcionando. Si revisa una copia de Fabric y busca ''gateway'' encontrará indicadores sobre cómo Fabric usa el soporte de Gateway de Paramiko (no tengo tiempo para desenterrar los sitios específicos por mi cuenta en este momento).


Una explicación detallada de lo que Paramiko está haciendo "debajo del capó" se puede encontrar en el blog de @ bitprohet aquí .

Asumiendo la configuración anterior, el código que tengo funciona se ve así:

from paramiko import SSHClient # Set up the proxy (forwarding server) credentials proxy_hostname = ''your.proxy.hostname'' proxy_username = ''proxy-username'' proxy_port = 22 # Instantiate a client and connect to the proxy server proxy_client = SSHClient() proxy_client.load_host_keys(''~/.ssh/known_hosts/'') proxy_client.connect( proxy_hostname, port=proxy_port, username=proxy_username, key_filename=''/path/to/your/private/key/'' ) # Get the client''s transport and open a `direct-tcpip` channel passing # the destination hostname:port and the local hostname:port transport = proxy_client.get_transport() dest_addr = (''0.0.0.0'', 8000) local_addr = (''127.0.0.1'', 1234) channel = transport.open_channel("direct-tcpip", dest_addr, local_addr) # Create a NEW client and pass this channel to it as the `sock` (along with # whatever credentials you need to auth into your REMOTE box remote_client = SSHClient() remote_client.load_host_keys(hosts_file) remote_client.connect(''localhost'', port=1234, username=''remote_username'', sock=channel) # `remote_client` should now be able to issue commands to the REMOTE box remote_client.exec_command(''pwd'')