Glenn Gillen

Don't put your private key on a public server

You're administering a server (Server A), and you need access to something on another server (Server B) but access is denied from Server A because you don't have your private key on there. If this is a scenario you've run into while trying to deploy an application it's almost certain that you don't want to put your private key on the server in the home directory of your deployment user, readable to anyone that can log in as that account (i.e, people other than you!).

SSH Agent Forwarding to the rescue

To get around this SSH has built in support for forwarding on your private credentials. What happens is that when you connect to a remote server the ssh-agent creates a unix socket and then listens to connections from ssh, this socket is accessible only by your user account… and root.

Yes, what this in fact means is that the root user on the remote server has access to the unix socket you've created. They can't see your private keys, they're still safely held on your client, but while you're connected to the remote server the root user on that machine could potentially use that socket to connect as you to another server. In short, make sure you trust root before you set this up (still, it's better than putting your private key in your home directory where root would now be able to see they key and use it whenever they wanted).

Configure your SSH client to use Agent Forwarding

Getting it to work is as simple as adding an entry to ~/.ssh/config (create the file if it doesn't exist):

1
2
Host remote-server.example.com
  	  ForwardAgent yes

Just replace the Host value with the hostname or IP address of the server you are connecting to, or with * if you're brave and want to do it automatically for all hosts.

Restarting your local SSH Agent

On my Macbook Pro I've added the following to my ~/.bash_profile to make sure that the SSH Agent is started when I open a new terminal and that my identities (private keys) are added to it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
	SSH_ENV=$HOME/.ssh/environment

	function start_agent {
	     echo "Initializing new SSH agent..."
	     /usr/bin/ssh-agent | sed 's/^echo/#echo/' > ${SSH_ENV}
	     echo succeeded
	     chmod 600 ${SSH_ENV}
	     . ${SSH_ENV} > /dev/null
	     /usr/bin/ssh-add;
	}

	if [ -f "${SSH_ENV}" ]; then
	     . ${SSH_ENV} > /dev/null
	     ps -x | grep "^ *${SSH_AGENT_PID}" | grep ssh-agent$ > /dev/null || {
	         start_agent;
	     }
	else
	     start_agent;
	fi

Glenn Gillen

I'm an advisor to, and investor in, early-stage tech startups. Beyond that I'm an incredibly fortunate husband and father. Working on a developer-facing tool or service? Thinking about starting one? Email me and let me know or come to one of our days to help make it a reality.