Which is the best way to bring a file from a remote host to local host over an SSH session?

zssh (a ZMODEM wrapper over openssh) does exactly what you want.

  • Install zssh and use it instead of openssh (which I assume that you normally use)

  • You'll have to have the lrzsz package installed on both systems.

Then, to transfer a file zyxel.png from remote to local host:

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:~$ 

Uploading goes similarly, except that you just switch rz(1) and sz(1).

Putty users can try Le Putty, which has similar functionality.


On a linux box I use the ssh-agent and sshfs. You need to setup the sshd to accept connections with key pairs. Then you use ssh-add to add you key to the ssh-agent so you don't have type your password everytime. Be sure to use -t seconds, so the key doesn't stay loaded forever.
ssh-add -t 3600 /home/user/.ssh/ssh_dsa

After that,
sshfs hostname:/ /PathToMountTo/
will mount the server file system on your machine so you have access to it.

Personally, I wrote a small bash script that add my key and mount the servers I use the most, so when I start to work I just have to launch the script and type my passphrase.


Using some little known and rarely used features of the openssh implementation you can accomplish precisely what you want!

  • takes advantage of the current state
  • can use the working directory where you are
  • does not require any tunneling setup before the session begins
  • does not require opening a separate terminal or connection
  • can be used as a one-time deal in an interactive session or can be used as part of an automated session

You should only type what is at each of the local>, remote>, and ssh> prompts in the examples below.

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
...

Or, more often you want to go the other direction, for example if you want to do something like transfer your ~/.ssh/id_rsa.pub file from your local machine to the ~/.ssh/authorized_keys file of the remote machine.

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

A little bit of explanation is in order.

The first step is to open a LocalForward; if you don't already have one established then you can use the ~C escape character to open an ssh command line which will give you the following commands:

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

In this example I establish a LocalForward on port 6666 of localhost for both the client and the server; the port number can be any arbitrary open port.

The nc command is from the netcat package; it is described as the "TCP/IP swiss army knife"; it is a simple, yet very flexible and useful program. Make it a standard part of your unix toolbelt.

At this point nc is listening on port 6666 and waiting for another program to connect to that port so it can send the contents of /etc/passwd.

Next we make use of another escape character ~^Z which is tilde followed by control-Z. This temporarily suspends the ssh process and drops us back into our shell.

One back on the local system you can use nc to connect to the forwarded port 6666. Note the lack of a -l in this case because that option tells nc to listen on a port as if it were a server which is not what we want; instead we want to just use nc as a client to connect to the already listening nc on the remote side.

The rest of the magic around the nc command is required because if you recall above I said that the ssh process was temporarily suspended, so the & will put the whole (sleep + nc) expression into the background and the sleep gives you enough time for ssh to return to the foreground with fg.

In the second example the idea is basically the same except we set up a tunnel going the other direction using -R instead of -L so that we establish a RemoteForward. And then on the local side is where you want to use the -l argument to nc.

The escape character by default is ~ but you can change that with:

 -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.

A full explanation of the commands available with the escape characters is available in the ssh manpage

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).

Tags:

Ssh