6

I have a set of SSH keys to login to accounts and servers. However, ever since I moved my main work profile to a USB drive (for sync and ease of use among other reasons) I have been unable to directly use the SSH keys in the profile for authentication, having to create local copies instead.

Normal SSH workflow usually goes

ssh-add $HOME/.ssh/id_server_key 
ssh username@domain

Which works without problems. However, to prevent each machine from having a copy of my keys I moved them to an xexternal drive, USB formatted as vfat. Then workflow should become like this:

ssh-add  /run/media/myself/USB/.ssh/id_server_key
ssh username@domain

...Which doesn't work. SSH complains about doing something to protect me:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for 'id_server_key' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
bad permissions: ignore key: id_server_key
Permission denied (publickey).

Which, while I can understand, it's not really protecting me in this case.

The USB drive automounts in my distro, with a fmask of (I think) 022. I could unmount and remount the USB drive with a fmask of 077 but that would (1) require superuser privilege each time and (2) affect every single file in the device, not only the SSH keys.

I've tried creating a symlink to the key, even with previous use of umask as I've seen in some tips&tricks:

cd .ssh
umask 077
ln -s /run/media/myself/USB/.ssh/id_server_key 

But the permissions can not be used this way for a symbolic link, so I get nothing.

So, what options do I have here available if the goal is to not have a physical copy of the key on the machine? One of the machines is a family laptop that goes to various places, so I have an interest in avoiding some of the keys being discovered.

So far I've considered the following:

  • Is there for example an option to force SSH (ssh-add primarily) to accept the keys from the external device? (I presume there should be - most programs follow a "I-know-what-I'm-doing" flag, but so far I can't find it in the manpage.
  • Setting a bindfs over the .ssh/ directory, but the problem is that the directory is non-empty (as it contains known_hosts and other data).
  • fuse-zip-ing the keys over /dev/shm seems to be a possible path as well.

EDIT: As per @Gilles 's comment, yes, bindfs solves the issue. After a checking of the manpage, initial testing succeeded using the following invocation:

bindfs -n -r -p 0700 -o nonempty /run/media/myself/USB/.ssh/ ~/.ssh 

Which binds disallowing access from other users (apparently even from root!), read-only, with reflected 0700 permissions. That reflection was the part that I lacked when working with bindfs originally. The nonempty flag was needed because of preexisting files such as known_hosts. This preserves the original workflow exactly except for an extra warning messae about not being able to add information to known_hosts (which in the end I might not mind).

Of course, I'm bindfs-ing to another directory now (in /dev/shm) as originally suggested to make things slightly easier.

I'm not as conspiranoid so as to encfs my USB drive (yet) so privacy-wise this is good enough for me.

  • Is there a way of telling your automounter to mount the stick with umask 077? (You usually don't care about permissions for group and others on a stick.) – michas Jan 12 '13 at 00:20
  • To my knowledge it should be possible to do it via udev or similar (hal, udisks?), but I've found no good, centralized documentation on the process so far. – Luis Machuca Jan 12 '13 at 16:14

4 Answers4

3

You can load the external key through the named pipe, e.g.

$ mkfifo -m=600 fifo
$ cat /external/media/.ssh/id_server_key >fifo | ssh-add fifo

Using process substitution also could work (using bash/zsh-like syntax):

$ ssh-add <(cat /external/media/.ssh/id_server_key)

Above command is equivalent to: cat /external/media/.ssh/id_server_key | ssh-add -.

assuming your anonymous pipe has the right permissions (check via: stat <(:)).

Or try loading it from the standard input:

$ cat /external/media/.ssh/id_server_key | ssh-add -
kenorb
  • 20,988
  • ssh-add <... won't work, this will add ~/.ssh/id_rsa (or similar) by default. Man: "When run without arguments, it adds the files ~/.ssh/id_rsa, ~/.ssh/id_dsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ed25519 and ~/.ssh/identity." – Piotr Findeisen Mar 29 '16 at 13:26
  • ssh-add <(cat /foo/bar) -> cat: /foo/bar: No such file or directory. This command expects external file in order to load. This syntax should work at least in Bash. Otherwise use standard syntax: cat /foo/bar | ssh-add. – kenorb Mar 29 '16 at 16:32
  • You're right. I mis-read <(cat file) as <file. But now you're wrong too. cat /foo/bar | ssh-add won't add /foo/bar. Try cat /dev/urandom | ssh-add. My ssh-add adds ~/.ssh/id_rsa in that case. – Piotr Findeisen Mar 29 '16 at 20:02
  • Forgot dash (-), cat /dev/urandom | ssh-add - -> Error loading key "(stdin)": invalid format. – kenorb Mar 29 '16 at 20:04
1

ssh-add doesn't have an option to bypass its check of the key permissions. You could recompile the program and disable the check.

A bindfs should work. You don't need to mount it at ~/.ssh, mount it at a special-purpose location and write a script that does ssh-add ~/.ssh-private-keys-bindfs.

Note that ssh is right in that your setup is pretty insecure. You must make sure never to plug that drive into a computer where you are not the sole user.

  • Good point about bindfsing it at a different location, I'll test it. And a better point about the security. While I'm the sole user of the distro, I'm not the sole user of the physical computer. – Luis Machuca Jan 12 '13 at 00:14
  • @LuisMachuca If you're the only user of that operating system on that computer, you're probably fine (while hardware backdoors are possible in theory, they are not (yet?) common in the wild). But if there are other users using the same operating system (even if they aren't logged in at the same time as you), they can easily read your keys. – Gilles 'SO- stop being evil' Jan 12 '13 at 00:18
  • Luckily I'm not too concerned with HW backdoors (yet?). Laptops are too finicky for dongle-backdooring and at that point the attacker is close to me enough that on a practical level http://xkcd.com/538/ is more feasible. – Luis Machuca Jan 12 '13 at 17:19
0

It is a permissions problem, as identified by this line:

Permissions 0644 for 'id_server_key' are too open.

It happens, because your permissions are too open on the private key, then ssh cannot guarantee the authenticity of the key, and will balk at using it.

So taking into account the VFATness of the thumbdrive (which doesn't support changing the permissions), you could do something like adding this line into /etc/fstab file:

LABEL=USB none msdos -u=USERID,-m=PERMS

Where USERID is your numerical userid, and PERMS is 700. This should tell the automounter to always mount the USB drive as that user, with no rights for group or other.


In case your file-system would support permissions, it would be much easier to fix it by:

chmod 700 /run/media/myself/USB/.ssh
chmod 400 /run/media/myself/USB/.ssh/id_server_key
kenorb
  • 20,988
Tim Kennedy
  • 19,697
0

On Ubuntu 20.04 the following works just fine:

cat ~/.ssh/my-key.pem | ssh-add -
Identity added: (stdin) ((stdin))