Cómo hacer scp con un segundo host remoto

82

Me pregunto si hay alguna forma de SCP del archivo desde el host remoto2 directamente desde mi máquina local pasando por un host remoto1.

Las redes solo permiten conexiones al host remoto2 desde el host remoto1. Además, ni el host remoto1 ni el host remoto2 pueden conectarse a mi máquina local.

Hay algo como:

scp user1@remote1:user2@remote2:file .

Primera ventana:, ssh remote1luego scp remot2:file ..

Segundo caparazón: scp remote1:file .

Primera ventana: rm file; logout

Podría escribir un script para hacer todos estos pasos, pero si hay una forma directa, prefiero usarla.

Gracias.

EDITAR: Estoy pensando en algo como abrir túneles SSH pero estoy confundido sobre qué valor poner y dónde.

Por el momento, para acceder remote1, tengo lo siguiente en $HOME/.ssh/configmi máquina local.

Host remote1
   User     user1
   Hostname localhost
   Port     45678

Una vez encendido remote1, para acceder remote2, es el DNS local estándar y el puerto 22. ¿Qué debo ponerme remote1y / o cambiar localhost?

Danosaure
fuente

Respuestas:

94

No conozco ninguna forma de copiar el archivo directamente en un solo comando, pero si puede aceptar ejecutar una instancia SSH en segundo plano para mantener un túnel de reenvío de puertos abierto, entonces puede copiar el archivo en un solo comando.

Me gusta esto:

# First, open the tunnel
ssh -L 1234:remote2:22 -p 45678 user1@remote1
# Then, use the tunnel to copy the file directly from remote2
scp -P 1234 user2@localhost:file .

Tenga en cuenta que se conecta como user2@localhosten el scpcomando real , porque es en el puerto 1234 en localhost donde la primera sshinstancia escucha las conexiones de reenvío remote2. Tenga en cuenta también que no es necesario ejecutar el primer comando para cada copia de archivo posterior; simplemente puede dejarlo funcionando.

Dolda2000
fuente
1
Gracias, esto parece estar cerca de lo que necesito. Así que creé el túnel, la huella dactilar coincide con la del servidor, pero tengo un error de "Permiso denegado (clave pública)". Creo que necesito preguntarle a mi administrador de red / sysadmin por qué no funciona.
Danosaure
3
¡Gracias! Tuve que cambiar -p 45678a -p 22porque mi SSH remoto1 está escuchando el puerto 22
Montaro
También tuve que usar en -p 22lugar de -p 45678. Tampoco scp -P 1234 ...me funciona. Estoy consiguiendo ssh: connect to host localhost port 1234: Connection refused. Cuando lo intenté scp -P 22 ..., funciona, pero está copiando el archivo remote 1y no en mi máquina local ( remote2).
pecador
¿Alguna herramienta de interfaz de usuario para lo mismo?
ExploringApple
70

Doble ssh

Incluso en su caso complejo, puede manejar la transferencia de archivos usando una sola línea de comando, simplemente con ssh;-)
Y esto es útil si remote1no puede conectarse a localhost:

ssh user1@remote1 'ssh user2@remote2 "cat file"' > file

tar

Pero pierde propiedades de archivo (propiedad, permisos ...).

Sin embargo, tares amigo tuyo mantener estas propiedades de archivo:

ssh user1@remote1 'ssh user2@remote2 "cd path2; tar c file"' | tar x

También puede comprimir para reducir el ancho de banda de la red:

ssh user1@remote1 'ssh user2@remote2 "cd path2; tar cj file"' | tar xj

Y tartambién te permite transferir un directorio recursivo a través de básico ssh:

ssh user1@remote1 'ssh user2@remote2 "cd path2; tar cj ."' | tar xj

ionice

Si el archivo es enorme y no desea molestar a otras aplicaciones de red importantes, puede perder la limitación de rendimiento de la red proporcionada por las herramientas scpy rsync(por ejemplo scp -l 1024 user@remote:file, no usa más de 1 Mbits / segundo).

Pero, se utiliza una solución alternativa ionicepara mantener una única línea de comando:

ionice -c2 -n7 ssh u1@remote1 'ionice -c2 -n7 ssh u2@remote2 "cat file"' > file

Nota: ionicepuede que no esté disponible en distribuciones antiguas.

oHo
fuente
Gracias por toda la descripción, pero creo que la solución de Dolda2000 es más fácil. Era algo que estaba intentando pero no podía resolverlo.
Danosaure
5
Esta es una respuesta espectacularmente buena y merece más votos. También es mucho más fácil que la respuesta aceptada en mi opinión.
Rik Smith-Unna
2
Estoy de acuerdo en que esta es una solución mejor que la respuesta aceptada. De esta forma, la conexión se limpia automáticamente.
Doug
Gracias, muy buena respuesta! ¿Qué tal al revés, copiando de local a remoto?
DomTomCat
31

Esto hará el truco:

scp -o 'Host remote2' -o 'ProxyCommand ssh user@remote1 nc %h %p' \ 
    user@remote2:path/to/file .

Para SCP el archivo desde el host remote2directamente, agregue las dos opciones ( Hosty ProxyCommand) a su archivo ~ / .ssh / config (vea también esta respuesta sobre superusuario). Entonces puedes ejecutar:

scp user@remote2:path/to/file .

desde su máquina local sin tener que pensar remote1.

John Manak
fuente
Buen enfoque! Aunque -o 'Host remote2'no parece ser realmente necesario cuando se inicia desde la línea de comandos (es decir, para copiar una vez sin tocar ~ / .ssh / config)
Mike
Igual que aquí. Esto funciona para mí sin -o 'Host remote2'. Gracias.
pecador
7

Con openssh versión 7.3 y posteriores, es fácil. Utilice la opción ProxyJump en el archivo de configuración.

# Add to ~/.ssh/config 
Host bastion
    Hostname bastion.client.com
    User userForBastion
    IdentityFile ~/.ssh/bastion.pem

Host appMachine
    Hostname appMachine.internal.com
    User bastion
    ProxyJump bastion                   # openssh 7.3 version new feature ProxyJump
    IdentityFile ~/.ssh/appMachine.pem. #no need to copy pem file to bastion host  

Comandos para ejecutar para iniciar sesión o copiar

ssh appMachine   # no need to specify any tunnel. 
scp helloWorld.txt appMachine:.   # copy without intermediate jumphost/bastion host copy.** 

por supuesto, puede especificar el servidor bastion Jump utilizando la opción "-J" del comando ssh, si no está configurado en el archivo de configuración.

Nota SCP no no parece apoyar la bandera "-J" a partir de ahora. (No pude encontrar en las páginas de manual. Sin embargo, el scp anterior funciona con la configuración del archivo de configuración)

usuario3851404
fuente
1
No es necesario agregar el servidor bastión al archivo de configuración si solo se usa para el proxy (es decir, no hay un IdentityFile diferente, etc.), simplemente agregue ProxyJump bastion.client.com a la sección appMachine.
Tomer Cohen
1

Hay una nueva opción en scpese agregado recientemente para exactamente este mismo trabajo que es muy conveniente -3.

TL; DR Para el host actual que ya tiene la autenticación configurada en los archivos de configuración ssh, simplemente haga:

scp -3 remote1:file remote2:file

Su scpdebe ser de versiones recientes.

Todas las demás técnicas mencionadas requieren que configure la autenticación de remoto1 a remoto2 o viceversa, lo que no siempre es una buena idea.
El argumento -3significa que desea mover archivos desde dos hosts remotos utilizando el host actual como intermediario, y este host en realidad realiza la autenticación en ambos hosts remotos, por lo que no tienen que tener acceso entre sí.
Solo tiene que configurar la autenticación en los archivos de configuración ssh, que es bastante fácil y está bien documentado, y luego simplemente ejecutar el comando en TL; DR

La fuente de esta respuesta es https://superuser.com/a/686527/713762

FazeL
fuente
0

Esta configuración funciona bien para mí:

Host jump
   User username
   Hostname jumphost.yourorg.intranet
Host production
   User username
   Hostname production.yourorg.intranet
   ProxyCommand ssh -q -W %h:%p jump

Entonces el comando

scp myfile production:~

Copia myfile en la máquina de producción .

Anydoby
fuente
0

Pequeña adición a la solución de Olibre aquí, con la que trabajé usando esta fuente.

Del mismo modo que tiene las tres formas de usar tarpara copiar desde un host remoto a local, lo siguiente funciona para la copia de host local a host remoto en situaciones de doble ssh: (ejecútelos en el directorio donde los archivos deben ser copiados, de lo contrario use fullpath /nombre del archivo)

Transfiera un solo archivo sin compresión:

tar c filename |  ssh user1@remote1 'ssh -Y user2@remote2 "path2 && tar x"'

Transfiera un solo archivo con compresión:

tar cj filename |  ssh user1@remote1 'ssh -Y user2@remote2 "path2 && tar xj"'

Transferencia de directorio recursiva:

tar cj . |  ssh user1@remote1 'ssh -Y user2@remote2 "path2 && tar xj"'

El && aquí evita que el comando se ejecute si la primera mitad del comando no funciona, por ejemplo, si falta el directorio o hay un error en los nombres de ruta de origen / destino.

Aparna
fuente