¿Cuál es la mejor manera de llevar un archivo de un host remoto a un host local a través de una sesión SSH?

StackOverflow https://stackoverflow.com/questions/49896

  •  09-06-2019
  •  | 
  •  

Pregunta

Cuando me conecto a hosts remotos a través de ssh, con frecuencia quiero llevar un archivo de ese sistema al sistema local para verlo o procesarlo.¿Hay alguna manera de copiar el archivo sin (a) abrir una nueva terminal/pausar la sesión ssh (b) autenticarse nuevamente en los hosts locales o remotos, lo cual funciona (c) incluso cuando uno o ambos hosts están detrás de un ¿Enrutador NAT?

El objetivo es aprovechar al máximo el estado actual:que hay una conexión entre las dos máquinas, que estoy autenticado en ambas, que estoy en el directorio de trabajo del archivo, por lo que no tengo que abrir otra terminal y copiar y pegar el host remoto y camino de entrada, que es lo que hago ahora.La mejor solución tampoco requeriría ninguna configuración antes de que comenzara la sesión, pero si la configuración fuera única o pudiera automatizarse, entonces es perfectamente aceptable.

¿Fue útil?

Solución 7

Aquí está mi solución preferida para este problema.Configure un túnel ssh inverso al crear la sesión ssh.Esto se hace fácil gracias a dos funciones bash:grabfrom() debe definirse en el host local, mientras que grab() debe definirse en el host remoto.Puede agregar cualquier otra variable ssh que utilice (p. ej.-X o -Y) como mejor le parezca.

function grabfrom() { ssh -R 2202:127.0.0.1:22 ${@}; };
function grab() { scp -P 2202 $@ localuser@127.0.0.1:~; };

Uso:

localhost% grabfrom remoteuser@remotehost
password: <remote password goes here>
remotehost% grab somefile1 somefile2 *.txt
password: <local password goes here>

Positivos:

  • Funciona sin software especial en ninguno de los hosts más allá de OpenSSH
  • Funciona cuando el host local está detrás de un enrutador NAT
  • Se puede implementar como un par de dos funciones bash de una línea.

Negativos:

  • Utiliza un número de puerto fijo para que:
    • no funcionará con múltiples conexiones al host remoto
    • podría entrar en conflicto con un proceso que utiliza ese puerto en el host remoto
  • Requiere que localhost acepte conexiones ssh.
  • Requiere un comando especial al iniciar la sesión.
  • No maneja implícitamente la autenticación en el host local.
  • No permite especificar el directorio de destino en localhost
  • Si toma de varios hosts locales al mismo host remoto, a ssh no le gustará que las claves cambien

Trabajo futuro:Esto sigue siendo bastante complicado.Obviamente, sería posible manejar el problema de autenticación configurando las claves ssh adecuadamente y es aún más fácil permitir la especificación de un directorio remoto agregando un parámetro a grab()

Más difícil es abordar los otros aspectos negativos.Sería bueno elegir un puerto dinámico pero, hasta donde yo sé, no existe una forma elegante de pasar ese puerto al shell en el host remoto;Lo mejor que puedo decir es que OpenSSH no le permite establecer variables de entorno arbitrarias en el host remoto y bash no puede tomar variables de entorno de un argumento de línea de comando.Incluso si pudiera elegir un puerto dinámico, no hay forma de garantizar que no se utilice en el host remoto sin conectarse primero.

Otros consejos

zssh (a ZMODEM wrapper over openssh) hace exactamente lo que quieres.

  • Instalar zssh y úsalo en lugar de openssh (que supongo que usas normalmente)

  • Tendrás que tener el lrzsz paquete instalado en ambos sistemas.

Luego, para transferir un archivo zyxel.png Del host remoto al local:

antti@local:~$ zssh remote
Press ^@ (C-Space) to enter file transfer mode, then ? for help
...
antti@remote:~$ sz zyxel.png
**B00000000000000
^@
zssh > rz
Receiving: zyxel.png
Bytes received:  104036/ 104036   BPS:16059729

Transfer complete
antti@remote:~$ 

La carga es similar, excepto que simplemente cambias rz(1) y tamaño(1).

Los usuarios de Putty pueden probar La masilla, que tiene una funcionalidad similar.

En una máquina Linux utilizo ssh-agent y sshfs.Debe configurar el sshd para aceptar conexiones con pares de claves.Luego usa ssh-add para agregar su clave al ssh-agent para que no tenga que escribir su contraseña cada vez.Asegúrese de usar -t segundos, para que la clave no permanezca cargada para siempre.
ssh-add -t 3600 /home/user/.ssh/ssh_dsa

Después,
nombre de host sshfs:/ /PathToMountTo/
montará el sistema de archivos del servidor en su máquina para que tenga acceso a él.

Personalmente, escribí un pequeño script bash que agrega mi clave y monta los servidores que uso más, así que cuando empiezo a trabajar solo tengo que iniciar el script y escribir mi contraseña.

¡Usando algunas características poco conocidas y raramente utilizadas de la implementación de OpenSSH, puede lograr con precisión lo que desea!

  • aprovecha el estado actual
  • puede usar el directorio de trabajo donde se encuentra
  • no requiere ninguna configuración de túnel antes de que comience la sesión
  • no requiere abrir un terminal o conexión separada
  • se puede utilizar como un trato único en una sesión interactiva o se puede utilizar como parte de una sesión automatizada

Sólo debes escribir lo que hay en cada uno de los local>, remote>, yssh> indicaciones en los ejemplos siguientes.

local> ssh username@remote
remote> ~C
ssh> -L6666:localhost:6666
remote> nc -l 6666 < /etc/passwd
remote> ~^Z
[suspend ssh]
[1]+  Stopped                 ssh username@remote
local> (sleep 1; nc localhost 6666 > /tmp/file) & fg
[2] 17357
ssh username@remote
remote> exit
[2]-  Done                    ( sleep 1; nc localhost 6666 > /tmp/file )
local> cat /tmp/file
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
...

O, más a menudo desea seguir la otra dirección, por ejemplo, si desea hacer algo como transferir su ~/.ssh/id_rsa.pub Archivo de su máquina local a la ~/.ssh/authorized_keys archivo de la máquina remota.

local> ssh username@remote
remote> ~C
ssh> -R5555:localhost:5555
remote> ~^Z
[suspend ssh]
[1]+  Stopped                 ssh username@remote
local> nc -l 5555 < ~/.ssh/id_rsa.pub &
[2] 26607
local> fg
ssh username@remote
remote> nc localhost 5555 >> ~/.ssh/authorized_keys
remote> cat ~/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2ZQQQQBIwAAAQEAsgaVp8mnWVvpGKhfgwHTuOObyfYSe8iFvksH6BGWfMgy8poM2+5sTL6FHI7k0MXmfd7p4rzOL2R4q9yjG+Hl2PShjkjAVb32Ss5ZZ3BxHpk30+0HackAHVqPEJERvZvqC3W2s4aKU7ae4WaG1OqZHI1dGiJPJ1IgFF5bWbQl8CP9kZNAHg0NJZUCnJ73udZRYEWm5MEdTIz0+Q5tClzxvXtV4lZBo36Jo4vijKVEJ06MZu+e2WnCOqsfdayY7laiT0t/UsulLNJ1wT+Euejl+3Vft7N1/nWptJn3c4y83c4oHIrsLDTIiVvPjAj5JTkyH1EA2pIOxsKOjmg2Maz7Pw== username@local

Conviene una pequeña explicación.

El primer paso es abrir una LocalForward;Si aún no tiene uno establecido, puede usar el ~C Escapar del personaje para abrir una línea de comandos SSH que le dará los siguientes comandos:

remote> ~C
ssh> help
Commands:
      -L[bind_address:]port:host:hostport    Request local forward
      -R[bind_address:]port:host:hostport    Request remote forward
      -D[bind_address:]port                  Request dynamic forward
      -KR[bind_address:]port                 Cancel remote forward

En este ejemplo establezco un LocalForward en el puerto 6666 de localhost tanto para el cliente como para el servidor;El número de puerto puede ser cualquier puerto abierto arbitrario.

El nc el comando es del netcat paquete;Se describe como la "navaja suiza TCP/IP";Es un programa simple, pero muy flexible y útil.Conviértalo en una parte estándar de su cinturón de herramientas Unix.

En este punto nc está escuchando en el puerto 6666 y esperando que otro programa se conecte a ese puerto para que pueda enviar el contenido de/etc/passwd.

A continuación hacemos uso de otro carácter de escape. ~^Z cual es tildeseguido por control-Z.Esto suspende temporalmente el proceso SSH y nos deja de regreso a nuestro caparazón.

Uno de vuelta en el sistema local que puedes usar. nc para conectarse al puerto reenviado 6666.Nótese la falta de un -l En este caso porque esa opción dice nc escuchar en un puerto como si fuera un servidor que no es lo que queremos;en lugar de eso queremos simplemente usar nc como cliente para conectarse a la escucha ya escuchada nc en el lado remoto.

El resto de la magia alrededor del nc se requiere el comando porque si recuerdas arriba dije que el ssh el proceso fue suspendido temporalmente, por lo que el & Pondrá todo (sleep + nc) expresión en el fondo y el sleep te da suficiente tiempo para que SSH regrese al primer plano con fg.

En el segundo ejemplo, la idea es básicamente la misma, excepto que configuramos un túnel que va en la otra dirección usando -R en lugar de -L para que establezcamos un RemoteForward.Y luego en el lado local es donde quieres usar el -l argumento para nc.

El carácter de escape predeterminado es ~ pero puedes cambiarlo con:

 -e escape_char
         Sets the escape character for sessions with a pty (default: ‘~’).  The escape character is only recognized at the beginning of a line.  The escape character followed by a dot
         (‘.’) closes the connection; followed by control-Z suspends the connection; and followed by itself sends the escape character once.  Setting the character to “none” disables any
         escapes and makes the session fully transparent.

Una explicación completa de los comandos disponibles con los caracteres de escape está disponible en el página de manual ssh

ESCAPE CHARACTERS
     When a pseudo-terminal has been requested, ssh supports a number of functions through the use of an escape character.

     A single tilde character can be sent as ~~ or by following the tilde by a character other than those described below.  The escape character must always follow a newline to be interpreted
     as special.  The escape character can be changed in configuration files using the EscapeChar configuration directive or on the command line by the -e option.

     The supported escapes (assuming the default ‘~’) are:

     ~.      Disconnect.

     ~^Z     Background ssh.

     ~#      List forwarded connections.

     ~&      Background ssh at logout when waiting for forwarded connection / X11 sessions to terminate.

     ~?      Display a list of escape characters.

     ~B      Send a BREAK to the remote system (only useful for SSH protocol version 2 and if the peer supports it).

     ~C      Open command line.  Currently this allows the addition of port forwardings using the -L, -R and -D options (see above).  It also allows the cancellation of existing remote port-
             forwardings using -KR[bind_address:]port.  !command allows the user to execute a local command if the PermitLocalCommand option is enabled in ssh_config(5).  Basic help is avail‐
             able, using the -h option.

     ~R      Request rekeying of the connection (only useful for SSH protocol version 2 and if the peer supports it).

Usar ControlMaster (el interruptor -M) es la mejor solución, mucho más simple y fácil que el resto de las respuestas aquí.Le permite compartir una única conexión entre varias sesiones.Parece que hace lo que quiere el cartel.Aún así tendrás que escribir la línea de comando scp o sftp.Intentalo.Lo uso para todo mi sshing.

Para hacer esto, tengo el enrutador de mi casa configurado para reenviar el puerto 22 a mi máquina doméstica (que tiene un firewall para aceptar solo conexiones ssh desde mi máquina de trabajo) y también tengo una cuenta configurada con DynDNS para proporcionar DNS dinámico que se resolverá automáticamente en la IP de mi hogar.

Luego, cuando entro a mi computadora de trabajo, lo primero que hago es ejecutar un script que inicia un agente ssh (si su servidor no lo hace automáticamente).El script que ejecuto es:

#!/bin/bash

ssh-agent sh -c 'ssh-add < /dev/null && bash'

Me pide la contraseña de mi clave ssh para no tener que escribirla cada vez.No necesitas ese paso si usas una clave ssh sin una frase de contraseña.

Durante el resto de la sesión, enviar archivos a la máquina de su hogar es tan simple como

scp file_to_send.txt your.domain.name:~/

Aquí hay un hack llamado ssh-xfer que soluciona el problema exacto, pero requiere parchear OpenSSH, lo cual no es un comienzo en lo que a mí respecta.

Puede utilizar el protocolo SCP para transferir un archivo. Puede consultar este enlace

http://tekheez.biz/scp-protocol-in-unix/

Debería poder configurar claves públicas y privadas para que no se necesite autenticación.

La forma en que lo haga depende de los requisitos de seguridad, etc. (tenga en cuenta que existen gusanos ssh de Linux/Unix que buscarán claves para encontrar otros hosts a los que puedan atacar).

Hago esto todo el tiempo detrás de los enrutadores Linksys y Dlink.Creo que es posible que necesites cambiar un par de configuraciones, pero no es gran cosa.

Utilice el modificador -M.

"Coloca el cliente ssh en modo 'maestro' para compartir la conexión.Múltiples opciones -M colocan a ssh en modo "maestro" y se requiere confirmación antes de que se acepten las conexiones esclavas.Consulte la descripción de ControlMaster en ssh_config(5) para obtener más detalles."

No veo muy bien cómo responde eso a la pregunta del OP: ¿puedes ampliar esto un poco, David?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top