WakeLift
wakelift / posts /

typing your password into an scp prompt considered unnecessary

This situation will probably be familiar to some of you: You just want to get a file from a friends computer, so you offer to SCP it to your computer, since you have password-auth turned on. You figure it's safe, because when the scp process is done, the session is automatically closed and the 'friend' of yours has no way of gaining access to a shell on your computer. Right? No!

There's a very, very useful setting for your ssh config called "ControlMaster". Set that to auto and a fitting path to the control master socket and you'll be able to open up another ssh session - a shell, for instance, or another scp process - and as long as any ssh-based process is logged on to the remote computer, you can start another. And here's the kicker: You don't have to unlock a private key or type in a password or do any other kind of auth (actually, pam might have a way of interfering, but if it does, I don't know about it) a single time.

Now that I've demonstated how doing it this way can be harmful (and you might not want to trust your friend just because he's your friend. Their machine might be running a rootkit or something.), I'll tell you how you can do it more securely.

scponly

One big reason you'd want to use ssh/scp to copy over the file is because it's convenient. Most of the time you have your sshd running anyway or can quickly start it up without much configuration work, whereas you might be too lazy to set up an FTP server or an HTTP based upload script or sendfile or whathaveyou.

The obvious solution to keeping ssh as a transport medium (even though it usually severely limits the amount of data that goes through) is using this neat little shell-replacement scponly. scponly makes sure, when a connection came through, that the connecting person uses only scp and can only do things they could otherwise do with scp, that is: upload files, create folders, download files. What it does not allow, though, is execute arbitrary (or just uploaded) files.

In addition to that, you can also use scponly in combination with a chrooting feature, that will lock a user logging in to the scponly user into their home directory. This makes it possible to hide the complete rest of your filesystem from friends and intruders.

netcat, netcat6, socat and pv

This is more of a ghetto-approach, but I've used it successfully a bunch of times and it feels very geeky :)

What you do is you run netcat, netcat6 or socat as a server on either the receiving or sending end and run netcat, netcat6 or socat as a client on the other end. Then you use pv from the moreutils package (which neatly displays the current speed, completion percentage, estimated time of completion and, most importantly, when the upload has finished) and pipe it through {netcat{,6},socat} and it will come out on the other machine.

Of course, this requires more setup than the scp method (because you don't have a *cat instance running all the time), but it's worth it for the flexibility. Once I even used netcat to voicechat with a friend (the pipe looked like this on both ends: arecord -f dat | speexenc - - | netcat | speexdec - - | aplay) and there's lots more fun to be had with it :)

sendfile/SAFT and woof

There are other, even simpler methods, though. One of them is sendfile/SAFT, which relies on a server running on the receiving end. It will accept an upload and notify the user it was uploaded to, who can then copy the file to the intended target folder with the receive command. This is nice, but it still requires both users to have sendfile installed.

There's an even simpler method, though, which is woof. woof simply starts up, offers a single file via HTTP - or a folder as a tar file - and shuts down after count (by default one) download has finished. If you want to receive files back, woof even has an option to offer itself for download.

The obvious benefit of woof over all other methods is, that probably every person has some client that allows file downloading via HTTP. But not everyone has woof and even though you can easily download and install it with modern linux distributions, you might not want to bother, which is why there's an even simpler method than every other one on this list!

python -m SimpleHTTPServer

Since most distros (and also macs) come with python pre-installed, you can just go to the folder that you want to serve and type python -m SimpleHTTPServer. Python will start up a basic http server listening by default on 0.0.0.0:8000 and serve up a directory listing of the current folder. And when you're done, you can just hit ctrl-c and be done with it.

This is by far the easiest method of sending a file from A to B, because it takes no preparation whatsoever, but neither allows for link-layer encryption, even though browsers are generally capable of that.

There is, however, a way to fix this, although this is getting a bit more ghetto.

OpenSSL with socat turns HTTP into HTTPS.

With socat you can expose every HTTP server over HTTPS. This requires a bit of work, though.

Generating a private key and certificate

This is actually not too hard, when using certtool. You just have to run

certtool --generate-privkey > ~/.ssl_key
chmod 400 ~/.ssl_key
certtool --generate-self-signed --load-privkey ~/.ssl_key > ~/.ssl_cert

Generating the selfsigned certificate will ask you lots of questions, but you can input anything you like except that it's a TLS server certificate maybe and probably an expiration date in the future.

Then you can use your cert and key with socat, like this:

socat OPENSSL-LISTEN:8080,key=/home/foo/.ssl_key,cert=/home/foo/.ssl_cert,verify=0 TCP:localhost:8000

Then you can grab the index with curl - for instance - like this:

curl --insecure https://localhost:8080/

This will connect to socat via HTTPS, which will then open a connection to your server of whatever type (woof or python or whatever), which will send the data encrypted to the HTTP client.

Most browsers will complain about the self-signed certificate, but that shouldn't bother you or your recipient.

Summary

So there you go. I've suggested several methods of getting data from A to B with varying degrees of ease and security. You should feel no more need to give out your password to others so they can scp stuff to your users home.

If you've come across even neater ways, please let me know using the feedback form below and I'll make sure to write an update to this post.

Thank you for your kind attention.