== Some good practices for handling OpenSSH keypairs It all started with [[Ryan Zezeski's question on Twitter https://twitter.com/rzezeski/status/692768165252702208]]: > Twitter friends: I want to better manage my SSH keys. E.g. different > pairs for different things. Looking for good resources. Links please. I have opinions on this (of course) but it turns out that I've never actually written them all down for various reasons, including that some of them feel obvious to me by now. So this is my shot at writing up what I see as good practices for OpenSSH keypairs. This is definitely not the absolutely best and most secure practice for various reasons, but I consider it a good starting point (but see [[my general cautions about this SshIdentitiesTradeoff]]). There are some basic and essentially universal things to start with. ~~Use multiple SSH keypairs~~, with at least different keypairs for different services; there is absolutely no reason that your Github keypair should be the keypair that you use for logging in places, and often you should have different keypairs for logging in to different places. The fundamental mechanic for doing this is a _.ssh/config_ with _IdentityFile_ directives inside _Host_ stanzas; [[here is a simple example SSHConfigIdentities]]. ([[My personal preference is to have different keypairs for each separate machine I'll ssh from SshIdentitiesSuggestions]], but this could get hard to manage in a hurry if you need a lot of keypairs to start with. Consider doing this only for keypairs that give you broad access or access to relatively dangerous things.) ~~Encrypt all of your keys~~. Exactly what password(s) you should use are a tradeoff between security and convenience, but simply encrypting all keys stops or slows down many attacks. For instance, [[the recent OpenSSH issue http://www.undeadly.org/cgi?action=article&sid=20160114142733]] would only have exposed (some of) your encrypted keys, which are hopefully relatively hard to crack. Whenever possible, [[restrict where your keys are accepted from SshIdentitiesSuggestions]]. This is a straightforward way to limit the damage of a key compromise at the cost of some potential inconvenience if you suddenly need to access systems from an abnormal (network) location. In addition, if you have some unencrypted keys because you need some automated or unattended scripts, consider restricting what these keys can do on the server by using a '_command=_' setting in their ((.ssh/authorized_keys)) line; an example where we do this is [[here RsyncReplicationSetup]] (see also [[this EncryptedSshKeysAndScreen]]). You probably also want to set various ((no-*)) options, especially disabling port forwarding. At this point we're out of truly universal things, as the path splits depending on whether you will access all of your keys via ssh-agent or whether at least some of them will be handled only by ssh (with passphrase challenges every time you use them). There is no single right answer (and covering the issues needs [[another entry SSHAgentTradeoffs]]), but for now I'll assume that you'll access all keys via ssh-agent. In this case you'll definitely want to read the discussion of [[what identities get offered to a remote server SSHIdentitiesOffered]] and use _IdentitiesOnly_ to limit this. If you need to ssh to hosts that are only reachable via intermediate hosts, *do not forward ssh-agent to the intermediate hosts*. Instead, use _ProxyCommand_ to reach through the intermediates. This is sometimes called [[SSH jump hosts https://wiki.gentoo.org/wiki/SSH_jump_host]] and there are plenty of guides on how to do it. Note that modern versions of OpenSSH have a _-W_ argument for _ssh_ that makes this easy to set up (you no longer need things like netcat on the jumphost). (There are some cases that need ssh agent forwarding, but plain 'I have to go through A to get to B' is not one of them.) With lots of keys loaded, your ssh-agent is an extremely large basket of eggs. There are several things you can do here to reduce the potential damage of an attacker gaining access to its full authentication power, although all of them come with convenience tradeoffs: * Set infrequently used or dangerous keys so that you'll have to confirm it before they can be used, by loading them with _ssh-add_'s _-c_ 'have ssh-agent ask for confirmation' argument. * Treat some keys basically like temporary _sudo_ privileges by loading them into ssh-agent with a timeout via _ssh-add_'s _-t_ argument. This will force you to reload the key periodically, much as you have to _sudo_ and then re-_sudo_ periodically. * Arrange to wipe all keys from _ssh-agent_ when you suspend, screenlock, or otherwise clearly leave your machine; my setup for this is covered [[here ../linux/EncryptedSSHKeyMigration]]. (This is good practice in general, but it becomes really important when access to ssh-agent is basically the keys to all the kingdoms.) You'll probably want to script some of these things to make them more convenient; you might have an '_add-key HOST_' command or the like that runs _ssh-add_ on the right key with the right _-c_ or _-t_ parameters. Such scripts will make your life a lot easier and thus make you less likely to throw up your hands and add everything to ssh-agent in permanent, unrestricted form. (Also, check your [[((ssh_config)) manpage http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man5/ssh_config.5]] to see if you have support for _AddKeysToAgent_. This can be used to create various sorts of convenient 'add to ssh-agent on first use' setups. This is not yet in any released version as far as I know but will probably be in OpenSSH 7.2.) PS: You probably also want to set _HashKnownHosts_ to _yes_. I feel conflicted about this, but it's hard to argue that it doesn't increase security and most people won't have my annoyances with it. PPS: My personal views on [[SSH key types SSHKeyTypes]] are that you should use ED25519 keys when possible and otherwise RSA keys (I use 4096 bits just because). Avoid DSA and ECDSA keys; the only time you should generate one is if you have to connect to a device that only supports DSA (and then the key should be specific to the device).