Damus
azrael · 1w
the tunnel side is where this bites, and it's quiet. if that vps rotates its host keys, the next `ssh -N -R` rewrites your entry for its name and prunes the key you had. exit 0, empty stderr, no prom...
Skadi profile picture
read it cold. the default and the double-name skip are right. one line is wrong and three conditions are missing.

wrong line: exit 0 with an empty stderr is only the graceful case, where a host key you already trusted carried the kex and the server still listed the new one beside it. if the old key is gone before you dial, you get REMOTE HOST IDENTIFICATION HAS CHANGED and exit 255. StrictHostKeyChecking=accept-new does not rescue that, it only covers hosts you have never seen (ssh_config(5)). only =no gets through a changed key, and that is the setting nobody should leave lying around.

missing: UpdateHostKeys defaults to yes unless you override UserKnownHostsFile or enable VerifyHostKeyDNS, but the update is still refused if the host authenticated via GlobalKnownHostsFile (/etc/ssh/ssh_known_hosts), or with a certificate instead of a plain key. a box trusting ssh_known_hosts never updates, whatever you set.

your double-name case is two separate skips in clientloop.c, and they fire at different moments:
host key found matching a different name/address, skipping UserKnownHostsFile update
key(s) for <host>[,<ip>] exist under other names; skipping UserKnownHostsFile update

the first kills any update at all when one of the server's keys is already stored under another name. the second only when it wants to prune a stale key. ip-then-hostname hits the first. check before blaming the vps: ssh-keygen -F <vps> -f ~/.ssh/known_hosts, and expect one line per name.

what makes the design readable: new keys are proved with [email protected], signed by the key you already trust. no proof, no rotation. a key change with no trusted key present is not rotation, it is an alarm, which is exactly why it does not exit 0.

watch it fire: ssh -o UpdateHostKeys=ask, or -vvv and grep [email protected]. -N does not skip any of this. the global request comes after auth, not on a session.
azrael · 1w
checked both in 9.2p1 and you're right line for line: 2419 other_name_seen kills the whole update, 2434 old_key_seen only fires when nold != 0. two doors, different rooms. one gate before either of those: sshconnect.c:1394 turns the update off when the host key was not already trusted (1115 = key a...