== What SSH identities will be offered to a remote server and when I've already written an entry on [[what SSH keys in your .ssh/config will be offered to servers SSHConfigIdentities]], but it wasn't quite complete and I still managed to confuse myself about this recently. So today I'm going to try to write down in one place more or less everything I know about this. Assuming that you're using _ssh-agent_ and you don't have _IdentitiesOnly_ set anywhere, the following is what keys will be offered to the remote server: # All keys from _ssh-agent_, [[in the order they were loaded into _ssh-agent_ SshAgentAndMultipleKeys]]. # The key from a _-i_ argument, if any. # Any key(s) from matching _Host_ or _Match_ stanzas in _.ssh/config_, in the order they are listed (and matched) in the file. Yes, all keys from all matching stanzas; [[_IdentityFile_ directives are cumulative SSHConfigIdentities]], which can be a bit surprising. (If there are no _IdentityFile_ matches in _.ssh/config_, OpenSSH will fall back to the default ((.ssh/id_*)) keys if they exist.) (If you aren't using _ssh-agent_, only #2 and #3 are applicable and you can pretty much ignore the rest of this entry.) If there is a '_IdentitiesOnly yes_' directive in *any* matching _.ssh/config_ stanza (whether it is in a '_Host *_' or a specific '_Host _'), the only keys from _ssh-agent_ that will be offered in #1 are the keys that would otherwise be offered in both #2 and #3. Unfortunately _IdentitiesOnly_ doesn't change the order that keys are offered in; keys in _ssh-agent_ are still offered first (in #1) and in the order they were loaded into _ssh-agent_, not the order that they would be offered in if _ssh-agent_ wasn't running. Where the '_IdentitiesOnly yes_' directive comes from makes no difference, as you'd pretty much expect. The only difference between having it in eg '_Hosts *_' versus only (some) specific '_Host _' entries is how many connections it applies to. This leads to an important observation: > ~~The main effect of a universal _IdentitiesOnly_ directive > is to make it harmless to load a ton of keys into your > _ssh-agent_.~~ OpenSSH servers have a relatively low limit on how many public keys they will let you offer to them; usually it's six or less (technically it's a limit on total authentication 'attempts', which can wind up including eg a regular password). Since OpenSSH normally offers all keys from your _ssh-agent_, loading too many keys into it can cause authentication problems (how many problems you have depends on how many places you can authenticate to with the first five or six keys loaded). Setting a universal '_IdentitiesOnly yes_' means that you can safely load even host-specific keys into _ssh-agent_ and still have everything usable. (This is the _sshd_ configuration directive _MaxAuthTries_.) Note that specifying _-i_ does not help if you're offering too many keys through _ssh-agent_, because the _ssh-agent_ keys are offered first. You must enable _IdentitiesOnly_ as well, either in _.ssh/config_ or as a command line option. Even this may not be a complete cure if your _.ssh/config_ enables too many _IdentityFile_ directives and those keys are loaded into _ssh-agent_ so that they get offered first. If the key for _-i_ is loaded into your _ssh-agent_, OpenSSH will use the _ssh-agent_ version for authentication. This will cause a confirmation check if the key was loaded with '_ssh-add -c_' (and yes, this still happens even if the _-i_ key is unencrypted). (_ssh-agent_ confirmation checks only happen when the key is about to be used to authenticate you, not when it is initially offered to the server.) PS: you can see what keys you're going to be offering in what order with '_ssh -v -v ..._'. Look for the 'debug2: key: ...' lines, and also 'debug1: Offering ...' lines. Note that keys with paths and marked '_explicit_' may still come from _ssh-agent_; that explicit path just means that they're known through an _IdentityFile_ directive. === Sidebar: the drawback of a universal _IdentitiesOnly_ The short version is 'agent forwarding from elsewhere'. Suppose that you are on machine A, with a _ssh-agent_ collection of keys, and you log into machine B with agent forwarding ([[for whatever reason EncryptedSshKeysAndScreen]]). If machine B is set up with up with universal _IdentitiesOnly_, you will be totally unable to use any _ssh-agent_ keys that machine B doesn't know about. This can sort of defeat the purpose of agent forwarding. There is a potential half way around this, which is that _IdentityFile_ can be used without the private key file. Given a stanza: .pn prewrap on > Host * > IdentitiesOnly yes > IdentityFile /u/cks/.ssh/ids/key-ed2 If you have a _key-ed2.pub_ file but no _key-ed2_ private key file, this key will still be offered to servers. If you have _key-ed2_ loaded into your _ssh-agent_ through some alternate path, SSH can authenticate you to the remote server; otherwise _ssh_ will offer the key, have it accepted by the server, and then discover that it can't authenticate with it because there is no private key. SSH will continue to try any remaining authentication methods, including more identities. (This is the inverse of [[how SSH only needs you to decrypt private keys when it's about to use them SSHWhenKeysDecrypted]].) However, this causes SSH to offer the key all the time, using up some of your _MaxAuthTries_ even in situations where the key is not usable. Unfortunately, as far as I can tell there is no way to tell SSH 'offer this key only if _ssh-agent_ supports it', which is what we really want here.