Securing SSH Keys on Shared Hosts
First a warning:
Don’t put your ssh private keys on a shared host!
The issue is that you can’t trust your fellow users on the shared host. You may have set the items in the ~/.ssh/
directory with chmod 400
but that doesn’t prevent root users from seeing them.
In this article we will discuss an alternative for using ssh keys to connect to git, or other servers, on a shared system.
Background
I’ve recently started to develop some small software projects on ctrl-c.club. Ctrl-c is a shared server (tilde) with a few hundred other users. We have local mail, irc, and a bulletin board that we use to create a community of command-line aficionados. Since I’m developing software on this shared space I want to use version control. The server has git
installed so I can easily send my software assets to github or TildeGit.
On my localhost I have created an easy workflow for pushing
changes to github using SSH. I have a public/private key pair in my local .ssh
directory and have shared my public key with github.com
To replicate this on the shared server I would need to copy those keys to the .ssh
directory (or create a new set of keys) on the server. This, however, is a bad security practice. I trust the server’s admins not to steal my keys and modify my github account but you may not. Or more correctly I shouldn’t have to trust the admins. Security should be the default of my workflow.
Local Configuration
Here are the contents of my .ssh
directory on my local work station:
1 | pilot@morlock:~$ ls -l .ssh |
id_rsa
is my private key. id_rsa.pub
is my public key, that has been shared with github.com, and is also used to log into Ctrl-c.club. authorized_keys
is a list of public keys that can login to my local desktop (it contains the public key I use on my laptop). known_hosts
are the public key finger prints that I trust (github.com, ctrl-c.club, and others).
Finally the config
file has information on where and when to use my ssh keys:
1 | Host ccc |
You can learn more about the configurations at my blog post that about setting them up.
The Control*
properties are for reusing an open ssh connection for new terminals and scp
secure copies.
Agent Forwarding
Installing OpenSSL in Linux or MacOS[0] includes the ssh-agent
utility to hold private keys used in public key authentication. When you unlock your private keys, using their password, ssh-agent stores the key contents as part of your login shell (or key chain on MacOS). It is a handy way to prevent you from needing to type the password for every authenticated request (similar to the function of sudo
remembering your password for a while).
One of the bonuses of using ssh-agent is that you can tell OpenSSH to forward your unlocked keys along to other secure connections you create.
Setup
This is the easy part. Under the Host
heading in your ~/.ssh/config
file add ForwardAgent yes
.
Here is my updated Ctrl-c.club config:
1 | Host ccc |
DONE!
In Practice
Let’s test that my local agent’s private keys are accessible on the shared server by first logging in and then running ssh to see if we get a connection.
1 | timemachine@copper:~$ ssh -T git@github.com |
We are on a shared host so we don’t want to blindly accept that public key! Software could have been installed on the server to intercept our connections to Github and listen in. This is called a man-in-the-middle-attack. Let’s discuss how to verify the public key fingerprint is authentic.
Look Up Public Keys
Github publishes their public key fingerprints but not every server you connect to will have a web page to verify.
From our localhost (ie, not the remote server that is asking for confirmation) we can save the public key and then test it.
1 | pilot@morlock:~$ ssh-keyscan github.com > github.pub |
Passing -l
to ssh-keygen asks to compute the fingerprint, -f
says what file to use.
Oh no! OpenSSH on the Ctrl-c server shows the data as an md5 fingerprint and my localhost uses sha256. You can specify the hash algorithm with the -E
option to ssh-keygen:
1 | pilot@morlock:~$ ssh-keygen -E md5 -l -f github.pub |
Good! Those are the same. We can trust the connection.
1 | timemachine@copper:~$ ssh -T git@github.com |
ssh will save the public key in ~/.ssh/known_hosts
and warn us if it changes in the future.
Concussion
We have shown how to use ssh-agent forwarding to allow us to use our local private keys on remote servers only when we are logged in over a secure and trusted connection. Then we showed how to verify that we are only using those keys if we can verify that the security of the connection has not been snooped on.
For a man in the middle to compromise my connection from Ctrl-c.club to Github they would need to not only compromise the Crtl-c.club server, but also the Github.com website and my local network. We can feel pretty confident at this point that our connections are secure.
- 0.
After Lion.
↩