How to transfer files over ssh while already ssh'd into the server

I transfer files using this command

scp <localfile> user@host:<destination>

The above command only works when I'm not ssh'd into the server.

How do I transfer local files to the host machine when I'm already ssh'd in??

I ssh in using ssh user@hostname


Nice question. scp again, but the opposite way. I did it and here it is:

chris@local ~$ ls hos*
hosts
chris@local ~$ ssh remote
Last login: Fri Mar  8 15:52:25 2013 from local
chris@remote ~$ scp chris@local:hos* .
chris@local's password: 
hosts                                              100% 1850     1.8KB/s   00:00    
chris@remote ~$ ls hos*
hosts
chris@remote ~$ 

edited to add: as pointed out in the comments, this requires that the remote computer can access the local computer. And sshd or (openssh-server) needs to be installed and running on the local machine.


It would help to know what you're running on the host machine. If you're using Linux,

scp user@host:/path/myfile .

should work.


All these "scp" answers don't answer the question IMHO.

Easiest way

You do standard I/O redirection using ssh like so

$ ssh user@host "dd if=path-of-file" | dd of=where-to-copy

You can control flow here with bs and even compress in more than 1 way:

$ ssh -C user@host "dd if=path-of-file" | dd of=where-to-copy

or something like:

$ ssh user@host "lzma -c path-of-file" | lzma -d - > where-to-copy

Another way!

For the 2nd way, let's assume you do not have root access, for some reason the first thing doesn't work, and you can't really install things on the remote host. You'll probably have python which has a built in webserver. So here's the trick.

Let's assume you are trying to get say, a file test.txt in the directory /tmp/test

$ ssh user@hostname
host$ cd /tmp/test
host$ python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...

Now normally we can't access that because it's bound to localhost.

So we're going to break out into the SSH command shell with the escape sequence

~C

Next we're going to do SOCKS forwarding to the remote machine. Pick a higher order port, say 4321

ssh> -D 0.0.0.0:4321
Forwarding port.

Alright, leave this running. Terminal 2 time! We're going to use our port 4321 as a SOCKS proxy, which will get us to the remote machine. From there, we'll access "localhost" which will be the remote machines localhost. curl gives that to us easily.

$ curl --preproxy SOCKS://localhost:4321 http://localhost:8000/test.txt

And Yet a 3rd

You balk back at me, "I don't even have python!". Do you have bash? You probably have bash. Let's do that.

On your localhost we'll use netcat. Let's pick a port, say 5445. So Terminal 1

$ nc -lp 5445 > where-to-put-it

Terminal 2 We're going to ssh using reverse port forwarding. Also we'll just save ourselves some typing and use 0 as a collapse of 0.0.0.0.

$ ssh -R 0:5000:0:5445 user@host 'bash -c "cat path-of-file > /dev/tcp/0/5000"'   

And yet a 4th!

Alright, say you don't have scp, you don't have bash, no python, the pipe solution isn't working, GatewayPorts are disabled, jeez, you're really stuck now right?

Nonsense! base64 to the rescue! This is included in busybox, you'll find it on just about everything. Here we go!

First we establish what's called a "barrier condition". We'll use UUIDs

$ uuidgen
14184b38-5fec-41ba-a94e-0de94d5a417a

Now we're going to log in and tee the entire session to a file

$ ssh user@remote | tee /tmp/session
host> echo 14184b38-5fec-41ba-a94e-0de94d5a417a;base64 somefile;echo 14184b38-5fec-41ba-a94e-0de94d5a417a

Wait for it to flash past your session and logout.

Now we'll use our barrier conditions and a newline to extract our payload

$ cat /tmp/session |\
  sed -zE -s/'(^.*?14184b38-5fec-41ba-a94e-0de94d5a417a\r\n)(.*?)(\r\n4184b38-5fec-41ba-a94e-0de94d5a417a.*)/\2/g'

This should now just have our base64 of the file. We're almost done, just need to get rid of the newlines

$ cat /tmp/session |\
  sed -zE -s/'(^.*?14184b38-5fec-41ba-a94e-0de94d5a417a\r\n)(.*?)(\r\n4184b38-5fec-41ba-a94e-0de94d5a417a.*)/\2/g' |\
  tr -d '\r\n' |\
  base64 -d > where-to-put-it

Self-directed study

Using the last one you can do something really fun, which I'll leave as an exercise to the reader.

  1. Instead of redirecting to a file, use a fifo pipe.
  2. Create a small shell function to do the barrier condition thing above and add a way to include the filename, we'll call it sz.
  3. Create a parser that reads the fifo pipe, looks for the barrier conditions in real time, extracts the payloads and saves them disk, let's call it rz

So you'll have this.

$ mkfifo something
$ rz something &
$ ssh user@localhost | tee something
host> sz() {
 ...
}
host> sz file1
host> sz file2

This flow (and even the names) is based on modem transfer protocols like zmodem