Handle unknown host keys #17
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
keyop-go/nfq_forwarder#17
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
When connecting to an unknown host, we currently error that the host key is unknown:
This is reasonable behaviour, but it would be convenient to add unknown host keys automatically (although incorrect keys should still prevent connection).
assigned to @danny
mentioned in issue #3
To be clear, only keys which are unknown should be accepted and automatically added to the
known_hostsconfiguration, and this behaviour should be a configurable option, on by default.Plan
golang.org/x/crypto/ssh/knownhosts(already used bysshtunnel.Dial) returns a*knownhosts.KeyErrorwhen a host key doesn't check out, and that error type alreadydistinguishes the two cases this ticket needs treated differently:
KeyError.Wantempty -> the host has no existing entry at all - genuinely unknown.KeyError.Wantnon-empty -> the host has an entry, but with a different key - amismatch, and exactly the signal of a possible MITM attack.
So the fix wraps the existing
knownhosts.New(...)callback: on an empty-WantKeyError(genuinely unknown host), auto-add the new key to
known_hostsand accept the connection: onanything else (a real mismatch, or any other failure) it's rejected exactly as today - never
silently overwritten.
ssh_strict_host_key_checking(Configuration.SSHStrictHostKeyChecking),a global setting matching
ssh_key_path/known_hosts_path. Named after OpenSSH's ownwell-known
StrictHostKeyCheckingoption for the same behavior. Defaults tofalse(i.e.auto-add is on by default, per your comment) - deliberately phrased as the "strict" opt-in
rather than an "auto-add" opt-out, so Go's normal zero-value (
false) already matches thewanted default without needing any special defaulting logic in
config.LoadFromFile. Appliesto both
--configYAML and the legacy CLI-flags path uniformly (the latter never sets iteither, so it inherits the same default).
sshtunnel.Dial: gains anautoAddUnknownHostKeys boolparameter (inverse ofSSHStrictHostKeyChecking, wired up ininternal/nfq_forwarder). When true, itsHostKeyCallbackwrapsknownhosts.New's callback: on an empty-WantKeyError, it appendsa new line to the known_hosts file (
knownhosts.Line(...), same helper the file's own formatis built from) and accepts the key; any other error (mismatch, revoked key, unreadable file,
etc.) is returned unchanged - the connection is refused.
silent.
Known limitation, out of scope for this MR: this only affects the "host key doesn't match an
existing known_hosts entry" case. If the
known_hostsfile itself doesn't exist yet at all,knownhosts.Newalready fails before any of this runs (unchanged, pre-existing behavior) - thefile still needs to exist (even empty) for auto-add to kick in. Happy to also handle
create-if-missing in a follow-up if that'd be useful, but wanted to flag it rather than silently
expand scope.
Testing
Since this is pure file I/O + the
knownhostspackage's own logic (no live SSH handshakeneeded), tests build real
ssh.PublicKeyvalues (ed25519) and a tempknown_hostsfiledirectly:
against the now-updated file also passes (round-trip proof, not just "a line got written");
unmodified (the critical security case - proves auto-add never overwrites a changed key);
ssh_strict_host_key_checking: true, an unknown host is still rejected exactly astoday, and the file is left unmodified.
Work is happening on branch
issue17_unknown_host_keys; an MR will follow referencing thisissue.
mentioned in commit
e7b8178413mentioned in merge request !66
Added a follow-up commit to MR !66: when auto-add is enabled (the default),
known_hosts_pathis now created automatically (empty) if it doesn't already exist, so a brand new setup that's never manuallyssh'd anywhere works out of the box - no manualtouch known_hostsneeded first. Withssh_strict_host_key_checking: true, a missing file remains a hard error, matching that setting's explicit intent. The MR description and tests have been updated accordingly.mentioned in commit 79f9e6ba9e02eca23090f98a3aad381875fafbf1
Fixed via MR !66 and released in v1.0.5 (https://gitlab.keyop.co.uk/keyop/go/nfq_forwarder/-/releases/v1.0.5). Unknown jump host keys are now automatically accepted and recorded on first connection (Trust On First Use), on by default, controlled by
ssh_strict_host_key_checking; a key that's already known but has changed is still always rejected.known_hosts_pathis also now created automatically if missing. Closing.