scp from distant host to local server in a script - shell

I have been able to find lots of examples of server hopping and ProxyCommand but none relating to my specific need.
I want to transfer a file from a distant server to a local server. Currently, I can ssh from local to jump and from jump to distant (can not ssh from local to distant directly). Then from distant I can scp a file back to local. Right now I do this manually:
from local: ssh userJ#jump
then from jump: ssh userD#distant
then from distant: scp \path\file userL#local:\dest\path\
But I want to be able to do this in a script that I run from local. I have rsh keys stored in the appropriate places to eliminate password prompts. I just can't figure out the syntax for a single command.

Do you have to "push" the files on distant back to local?
It'd be easier to simply "pull" the files while on local from distant.
Setup ~/.ssh/config on local:
[userL#local]# cat ~/.ssh/config
Host distant
HostName Distant
user userD
ProxyCommand ssh -A userJ#jump nc %h %p
Test the connection using ssh:
[userL#local]# ssh -A userD#distant [or even: ssh -A distant]
Last login: Tue Oct 23 16:05:59 2018 from jump
[userD#distant]#
Now pull a file from distant:
[userL#local]# scp userD#distant:/distantpath/distantfile /localpath/localfile
distantfile 100% 129KB 128.9KB/s 00:01
[userL#local]#
In the example above, I used ssh's agent forwarding to pass credentials from local to jump and ultimately distant. You just need to pre-populate the authorized keys on jump and distant before agent forwarding will work.

I usually address this by configuring my ssh client in the ~/.ssh/config file to do the jump automatically:
Host distant-jump
User userD
Hostname distant
ProxyCommand ssh -q -W %h:%p jump
Host jump
User userJ
Then you can just: scp distant-jump:/path/file ./

Related

Complex SSH tunnel

I have a complex SSH tunnel problem I'm trying to solve and can't seem to get it quite right.
Simply put:
ME -> Bastion:22 -> Instance:8500
Bastion uses a different username and key than instance. I would like to be able to access port 1234 on instance from localhost:1234
Right now I have the following:
Host bastion
HostName bastion.example.com
ForwardAgent yes
IdentityFile ~/.ssh/id_ecdsa
User spanky
Host internal
ForwardAgent yes
HostName consul.internal
IdentityFile ~/.ssh/aws.pem
ProxyJump bastion
User ec2-user
Port 8500
But I don't think I've got it.
The following two commands work, but I'm trying to distill them into a working config:
ssh -L 2222:10.0.0.42:22 bastion.example.com -N -i ~/.ssh/id_ecdsa
ssh -L 8500:localhost:8500 ec2-user#localhost -N -i ~/.ssh/aws.pem -p 2222
With a current version of ssh, you should be able to use:
ssh -L1234:localhost:1234 -J spanky#bastion.example.com ec2-user#consul.internal
From man ssh:
-J destination
Connect to the target host by first making a ssh
connection to the jump host described by destination and then
establishing a TCP forwarding to the ultimate destination from there.
Multiple jump hops may be specified separated by comma characters.
This is a shortcut to specify a ProxyJump configuration directive.

Secure copy over two IPs on the same network to the local machine [duplicate]

I wonder if there is a way for me to SCP the file from remote2 host directly from my local machine by going through a remote1 host.
The networks only allow connections to remote2 host from remote1 host. Also, neither remote1 host nor remote2 host can scp to my local machine.
Is there something like:
scp user1#remote1:user2#remote2:file .
First window: ssh remote1, then scp remot2:file ..
Second shell: scp remote1:file .
First window: rm file; logout
I could write a script to do all these steps, but if there is a direct way, I would rather use it.
Thanks.
EDIT: I am thinking something like opening SSH tunnels but i'm confused on what value to put where.
At the moment, to access remote1, i have the following in $HOME/.ssh/config on my local machine.
Host remote1
User user1
Hostname localhost
Port 45678
Once on remote1, to access remote2, it's the standard local DNS and port 22. What should I put on remote1 and/or change on localhost?
I don't know of any way to copy the file directly in one single command, but if you can concede to running an SSH instance in the background to just keep a port forwarding tunnel open, then you could copy the file in one command.
Like this:
# 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 .
Note that you connect as user2#localhost in the actual scp command, because it is on port 1234 on localhost that the first ssh instance is listening to forward connections to remote2. Note also that you don't need to run the first command for every subsequent file copy; you can simply leave it running.
Double ssh
Even in your complex case, you can handle file transfer using a single command line, simply with ssh ;-)
And this is useful if remote1 cannot connect to localhost:
ssh user1#remote1 'ssh user2#remote2 "cat file"' > file
tar
But you loose file properties (ownership, permissions...).
However, tar is your friend to keep these file properties:
ssh user1#remote1 'ssh user2#remote2 "cd path2; tar c file"' | tar x
You can also compress to reduce network bandwidth:
ssh user1#remote1 'ssh user2#remote2 "cd path2; tar cj file"' | tar xj
And tar also allows you transferring a recursive directory through basic ssh:
ssh user1#remote1 'ssh user2#remote2 "cd path2; tar cj ."' | tar xj
ionice
If the file is huge and you do not want to disturb other important network applications, you may miss network throughput limitation provided by scp and rsync tools (e.g. scp -l 1024 user#remote:file does not use more than 1 Mbits/second).
But, a workaround is using ionice to keep a single command line:
ionice -c2 -n7 ssh u1#remote1 'ionice -c2 -n7 ssh u2#remote2 "cat file"' > file
Note: ionice may not be available on old distributions.
This will do the trick:
scp -o 'Host remote2' -o 'ProxyCommand ssh user#remote1 nc %h %p' \
user#remote2:path/to/file .
To SCP the file from the host remote2 directly, add the two options (Host and ProxyCommand) to your ~/.ssh/config file (see also this answer on superuser). Then you can run:
scp user#remote2:path/to/file .
from your local machine without having to think about remote1.
With openssh version 7.3 and up it is easy. Use ProxyJump option in the config file.
# 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
Commands to run to login or copy
ssh appMachine # no need to specify any tunnel.
scp helloWorld.txt appMachine:. # copy without intermediate jumphost/bastion host copy.**
ofcourse you can specify bastion Jump host using option "-J" to ssh command, if not configured in config file.
Note scp does not seems to support "-J" flag as of now. (i could not find in man pages. However above scp works with config file setting)
There is a new option in scp that add recently for exactly this same job that is very convenient, it is -3.
TL;DR For the current host that has authentication already set up in ssh config files, just do:
scp -3 remote1:file remote2:file
Your scp must be from recent versions.
All other mentioned technique requires you to set up authentication from remote1 to remote2 or vice versa, which not always is a good idea.
Argument -3 means you want to move files from two remote hosts by using current host as intermediary, and this host actually does the authentication to both remote hosts, so they don't have to have access to each other.
You just have to setup authentication in ssh config files, which is fairly easy and well documented, and then just run the command in TL;DR
The source for this answer is https://superuser.com/a/686527/713762
This configuration works nice for me:
Host jump
User username
Hostname jumphost.yourorg.intranet
Host production
User username
Hostname production.yourorg.intranet
ProxyCommand ssh -q -W %h:%p jump
Then the command
scp myfile production:~
Copies myfile to production machine.
a simpler way:
scp -o 'ProxyJump your.jump.host' /local/dir/myfile.txt remote.internal.host:/remote/dir

Is there a way to scp a file onto my local machine while logged into a server via ssh? [duplicate]

This question already has an answer here:
Is possible to copy files over ssh during an active connection
(1 answer)
Closed 6 years ago.
The title says most of it, but I'll be more specific:
When I want to scp a file from my local machine to a server I would use:
local_user#my_hostname:~$ scp local_file.txt remote_user#some_server:~/
remote_user#some_servers password:
local_file.txt 100% 0 0.0KB/s 00:00
local_user#my_hostname:~$
As you can see, I am prompted for a password for that ssh server, and the file would be securely copied.
Thus far, If I want a file copied to my local machine from a remote ssh server, I've been using scp like this:
local_user#my_hostname:~$ scp remote_user#some_server:~/server_file.txt ~/
remote_user#some_servers password:
server_file.txt 100% 0 0.0KB/s 00:00
local_user#my_hostname:~$
As you can see, I am asked again for the password. It would be nice to skip the password if I am already logged into the server via ssh with something along the lines of this:
local_user#my_hostname:~$ ssh remote_user#some_server
remote_user#some_servers password:
server login success!
remote_user#some_server:~$ scp server_file.txt local_user#my_hostname:~/
remote_user#some_sercer:~$
Is this possible? Or practical?
When you ssh into the remote host, set up a reverse tunnel.
ssh -R 12345:localhost:22 remote_user#some_server
Port 12345 on the remote host is now connected to port 22 on your host, meaning connections to 12345 are tunneled back over the existing ssh connection to your local machine's sshd service.
On the remote machine, run
scp -P 12345 server_file.txt localhost:~/
to copy the file back to your home directory.
If you don't want to remember to use -R, you can add the following to your local .ssh/config file:
Host *
RemoteForward 12345:localhost:22
and the tunnel will be set up for any connection automatically.
You can also specify a port of 0 (0:localhost:22) to let ssh choose an available port for you; the chosen port is written to standard output once the connection is established.

How to connect to a server using another server by ssh in shell script?

The scenario is like:
SERVER_A="servera.com"
SERVER_A_UNAME="usera"
SERVER_B="serverb.com"
SERVER_B_UNAME="userb"
I want to write a shell script which will fist connect to server A, and then only it would be connected to server B. Like:
#!/bin/sh
ssh $SERVER_A_UNAME#$SERVER_A ...and then
ssh $SERVER_B_UNAME#$SERVER_B
But I am not able to do it. It does connect to server A only. How can I achieve it?
You may be able to find some help with this previous question:
How to use bash/expect to check if an SSH login works
Depending on your situation you might also to execute an remote ssh command and wait for positive feedback.
See:
How to use SSH to run a shell script on a remote machine?
you should have a look at ssh ProxyCommands that lets you do indirect connects automatically. basically you put the following in you .ssh/config
Host gateway1
# nichts
Host gateway2
ProxyCommand ssh -q gateway1 nc -q0 gateway2 22
Host targethost
ProxyCommand ssh -q gateway2 nc -q0 targethost 22
and then you can run ssh targethost successfully even if targethost is not reachable directly. you can read more about this e.g. here http://sshmenu.sourceforge.net/articles/transparent-mulithop.html

Can I use an existing SSH connection and execute SCP over that tunnel without re-authenticating?

I'm wondering if I already have an established SSH tunnel and I want to minimize re-authenticating with an ssh server for each task, is there a way to use an existing tunnel to pull a file from the SSH server using SCP on the local machine without re-authenticating?
I'm trying to avoid using ssh keys, I'd just like to minimize the amount of times a password needs to be entered for a bash script.
ssh -t user#build_server "*creates a build file...*"
Once that command is completed there is a file that exists on build_server. So if the above tunnel was still open, is there way to use that tunnel from my LOCAL machine to run SCP to and bring the file to the local machines desktop?
Yes, session sharing is possible: man ssh_config and search for ControlMaster and/or check here and here. Is this what you are looking for?

Resources