You already saw the main point: if one of your machines is compromised, the private key contained on this machine must be "revoked": you must configure all servers on which you connect to reject further authentication attempts using that key (i.e. you remove the corresponding public key from the .ssh/authorized_keys
of the servers). There is a mitigation technique, which consists in securing the private key with a password (or passphrase). This comes with a price, namely that you have to type the password (ssh-agent
can be quite handy for that); on the other hand, this may temporarily deter the attacker from obtaining the private key (this depends on the kind of compromise, but if it is a theft of a complete machine -- a plausible scenario with mobile devices -- then the password will prevent immediate access to the private key and give you some time to reconfigure the servers).
One may note that "PKI" means "Public Key Infrastructure" and SSH is rudimentary in that respect. In a full-blow PKI, certificates would be used, with delegation, and centralization of revocation. With certificates:
- you would create one CA key pair, stored safely somewhere;
- for each client machine, you would obtain a fresh key pair, the public key being signed by the CA;
- the servers would be configured to automatically accept any public key signed by the CA (they would know the CA public key, but not the individual client machine keys);
- the CA would maintain and regularly publish revocation information, i.e. the list of public keys which must no longer be accepted even though these keys are signed by the CA (revocation information must be pushed to the servers, or pulled on demand).
The great thing about certificates is that you centralize decisions, which, in practical terms, means that if you connect to 20 servers from your client machines, and then add a new client machine, you do not have to manually push the new public key to all the 20 servers.
OpenSSH, since version 5.4 (released March 8, 2010), has some support for certificates; see the eponymous section in the man page for ssh-keygen
. The OpenSSH certificates have a much simpler format than "usual" X.509 certificates (as used with SSL). The simplification also has a price: there is no centralized revocation support. Instead, if a private key is compromised, you still have to blacklist the corresponding public key on all the servers, and the blacklist is, in OpenSSH, a whitelist (option AuthorizedPrincipalsFile
in sshd_config
) which is, normally, under the control of root
. So revocation does not work well and you still have to manually configure things on each server whenever you create or loose a key, the exact inconvenient that PKI was supposed to abolish.
You could still make time-limited keys, because OpenSSH certificates can embed time-limited keys. In that case, you would give to each client machine a key which is good for, say, one week. With keys which die after a week, and a CA public key known by the servers, you have the main CA goodness (no need to push anything on all the servers when a new machine is added to the client pool), and if a private key is compromised, the damage is "limited", assuming you had a key password which, presumably, would resist one week of cracking (but this will not work if the compromise is an hostile takeover with a key logger). Time-limited keys can grow tedious over time, and they assume that all servers have a correctly set clock, which is not always a given (it would be unfortunate to be locked out of a server because the server clock is wildly off, and resetting the clock requires SSH access to the server...).
An additional issue with SSH is that it is easy to add public keys on each server. This means that if an attacker compromises a private key and gains access to a server once, he can add his own public key to the .ssh/authorized_keys
on that server, and no amount of revocation will fix that. Revocation is, by nature, an asynchronous process. Hence, it does not implement a sufficiently strict damage control.
Given the shortcomings of SSH support for certificates, there is no reasonable scheme which avoids having to do some configuration on all the servers in some situations. So you have basically the following choices, when you add a new client machine:
You copy the private key from another client machine (that's what you are doing right now). This requires no extra configuration on the servers.
You create a new key pair for that machine. You have to push the public key to all the servers.
In the advent of a key compromise, you must connect to all the servers to remove the corresponding public key from all the .ssh/authorized_keys
. This is unavoidable (to avoid it, you would have to use certificates, and SSH is not good at certificates, see above). Then, if you used choice 1, then you must also create a new key pair and push it to all the client machines which were using a copy of the compromised private key.
Hence, choice 1 entails less configuration work than choice 2 in the normal case, but things are reversed if a key compromise occurred. Since compromises are normally rare events, this would favour choice 1 (which is what you already do). So I suggest that you protect your private key with a strong password, and copy it to all your client systems.
Note: in all of the above, I assumed that you wanted to connect to a list of servers with SSH, and you wanted to access any of the servers from any of your client machines. You might want to restrict access, such as accessing a given server only from one or two specific client machines. This can be done with multiple client keys, but configuration complexity increases quadratically.