-
Notifications
You must be signed in to change notification settings - Fork 17.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
x/crypto/ssh: client requires first hostkey to match, knownhosts doesn't expose available key types #29286
Comments
If you are proposing to add new API, then this should be a proposal, rather than a bug report. /cc @hanwen |
you can have only one hostkey algorithm per connection attempt, so it doesn't make sense to automate this, I think. We could look at exposing the DB in knownhosts. I think that should just make the existing types public, rather than introducing an interface. |
db is a local inside the New() method currently, are you suggesting making it create a global, or having a different method which returns a db, which you call instead of .New()? |
different method. |
So it sounds like the only thing you don't like about my solution is that it provides the interface. I guess the wonderful thing about Go is that you don't have to know that you respond to an interface, so as long as we call the methods something sane, people who need to be able to access file based knownhosts and eg. registry based knownhosts can create their own interface. |
interfaces should be defined where they are consumed, and functions should return concrete types if possible. See https://github.com/golang/go/wiki/CodeReviewComments#interfaces I know that the SSH package violates this guidelines in some places, but unfortunately, we can't fix it without breaking callers. However, I don't want to introduce more instances of this pattern. |
I've run into this issue recently, where
Current workaround: manually get the host key with
|
This seems like intended behavior? If For @TheoBrigitte, is this fixed by setting |
Yes this fixes it, but ideally I would not have to set this manually, and it should be auto-discovered as in |
It does look like there should be an easy way to set or better yet sort ClientConfig.HostKeyAlgorithms based on the available known keys (which is how OpenSSH handles this), but it's not immediately clear what it would be, especially when using FixedHostKey. At the very least, we should document the need to match them. (Relatedly, OpenSSH has a discovery mechanism for new host key algorithms, |
Actually, we can make this almost automagic. We can type-assert the HostKeyCallback returned by knownhosts.New and by FixedHostKey in the ssh client and prioritize those key types automatically. Then document you need to do it yourself for custom callbacks. (We can't actually type-assert across packages, but an interface upgrade might work even if the named type is a function. If not, we can add knownhosts.KeyFormatForCallback.) |
…Fixes go-git#411 This commit adjusts the transport/ssh logic in command.connect(), so that it now auto-populates ssh.ClientConfig.HostKeyAlgorithms. The algorithms are chosen based on the known host keys for the target host, as obtained from the known_hosts file. In order to look-up the algorithms from the known_hosts file, external module github.com/skeema/knownhosts is used. This package is just a thin wrapper around golang.org/x/crypto/ssh/knownhosts, adding an extra mechanism to query the known_hosts keys, implemented in a way which avoids duplication of any golang.org/x/crypto/ssh/knownhosts logic. Because HostKeyAlgorithms vary by target host, some related logic for setting HostKeyCallback has been moved out of the various AuthMethod implementations. This was necessary because the old HostKeyCallbackHelper is not host-specific. Since known_hosts handling isn't really tied to AuthMethod anyway, it seems reasonable to separate these. Previously-exported types/methods remain in place for backwards compat, but some of them are now unused. For testing approach, see pull request. Issue go-git#411 can only be reproduced via end-to-end / integration testing, since it requires actually launching an SSH connection, in order to see the key mismatch error triggered from golang/go#29286 as the root cause.
For anyone else stuck on this: it's actually possible to populate I've just open-sourced a new package github.com/skeema/knownhosts which is a thin wrapper around x/crypto/ssh/knownhosts making it easier to use this technique, as well as adding a few other niceties. In my testing it consistently solves this problem, at least when using known_hosts for host key callbacks. (My package does not handle FixedHostKey, as I suspect that would require x/crypto/ssh changes to be possible.) |
…Fixes #411 This commit adjusts the transport/ssh logic in command.connect(), so that it now auto-populates ssh.ClientConfig.HostKeyAlgorithms. The algorithms are chosen based on the known host keys for the target host, as obtained from the known_hosts file. In order to look-up the algorithms from the known_hosts file, external module github.com/skeema/knownhosts is used. This package is just a thin wrapper around golang.org/x/crypto/ssh/knownhosts, adding an extra mechanism to query the known_hosts keys, implemented in a way which avoids duplication of any golang.org/x/crypto/ssh/knownhosts logic. Because HostKeyAlgorithms vary by target host, some related logic for setting HostKeyCallback has been moved out of the various AuthMethod implementations. This was necessary because the old HostKeyCallbackHelper is not host-specific. Since known_hosts handling isn't really tied to AuthMethod anyway, it seems reasonable to separate these. Previously-exported types/methods remain in place for backwards compat, but some of them are now unused. For testing approach, see pull request. Issue #411 can only be reproduced via end-to-end / integration testing, since it requires actually launching an SSH connection, in order to see the key mismatch error triggered from golang/go#29286 as the root cause.
…Fixes go-git#411 This commit adjusts the transport/ssh logic in command.connect(), so that it now auto-populates ssh.ClientConfig.HostKeyAlgorithms. The algorithms are chosen based on the known host keys for the target host, as obtained from the known_hosts file. In order to look-up the algorithms from the known_hosts file, external module github.com/skeema/knownhosts is used. This package is just a thin wrapper around golang.org/x/crypto/ssh/knownhosts, adding an extra mechanism to query the known_hosts keys, implemented in a way which avoids duplication of any golang.org/x/crypto/ssh/knownhosts logic. Because HostKeyAlgorithms vary by target host, some related logic for setting HostKeyCallback has been moved out of the various AuthMethod implementations. This was necessary because the old HostKeyCallbackHelper is not host-specific. Since known_hosts handling isn't really tied to AuthMethod anyway, it seems reasonable to separate these. Previously-exported types/methods remain in place for backwards compat, but some of them are now unused. For testing approach, see pull request. Issue go-git#411 can only be reproduced via end-to-end / integration testing, since it requires actually launching an SSH connection, in order to see the key mismatch error triggered from golang/go#29286 as the root cause.
…Fixes go-git#411 This commit adjusts the transport/ssh logic in command.connect(), so that it now auto-populates ssh.ClientConfig.HostKeyAlgorithms. The algorithms are chosen based on the known host keys for the target host, as obtained from the known_hosts file. In order to look-up the algorithms from the known_hosts file, external module github.com/skeema/knownhosts is used. This package is just a thin wrapper around golang.org/x/crypto/ssh/knownhosts, adding an extra mechanism to query the known_hosts keys, implemented in a way which avoids duplication of any golang.org/x/crypto/ssh/knownhosts logic. Because HostKeyAlgorithms vary by target host, some related logic for setting HostKeyCallback has been moved out of the various AuthMethod implementations. This was necessary because the old HostKeyCallbackHelper is not host-specific. Since known_hosts handling isn't really tied to AuthMethod anyway, it seems reasonable to separate these. Previously-exported types/methods remain in place for backwards compat, but some of them are now unused. For testing approach, see pull request. Issue go-git#411 can only be reproduced via end-to-end / integration testing, since it requires actually launching an SSH connection, in order to see the key mismatch error triggered from golang/go#29286 as the root cause.
…Fixes go-git#411 This commit adjusts the transport/ssh logic in command.connect(), so that it now auto-populates ssh.ClientConfig.HostKeyAlgorithms. The algorithms are chosen based on the known host keys for the target host, as obtained from the known_hosts file. In order to look-up the algorithms from the known_hosts file, external module github.com/skeema/knownhosts is used. This package is just a thin wrapper around golang.org/x/crypto/ssh/knownhosts, adding an extra mechanism to query the known_hosts keys, implemented in a way which avoids duplication of any golang.org/x/crypto/ssh/knownhosts logic. Because HostKeyAlgorithms vary by target host, some related logic for setting HostKeyCallback has been moved out of the various AuthMethod implementations. This was necessary because the old HostKeyCallbackHelper is not host-specific. Since known_hosts handling isn't really tied to AuthMethod anyway, it seems reasonable to separate these. Previously-exported types/methods remain in place for backwards compat, but some of them are now unused. For testing approach, see pull request. Issue go-git#411 can only be reproduced via end-to-end / integration testing, since it requires actually launching an SSH connection, in order to see the key mismatch error triggered from golang/go#29286 as the root cause.
golang.org/x/crypto/ssh/knownhosts has an issue when the SSH server key in the `known_hosts` file doesn't match the first key returned by the SSH server (but should be still considered valid because it matches one of the other keys of the SSH server). See golang/go#29286 and containers/podman#23575. Signed-off-by: Mario Loriedo <mario.loriedo@gmail.com>
Package [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts) has an issue when an SSH server has many public keys (i.e. supports multiple crypto algorithms). For instance, if the local `known_hosts` file entries don't match the first SSH server key but match other keys of the SSH server, the handshake fails with a key mismatch error. See golang/go#29286 and containers/podman#23575. Package [github.com/skeema/knownhosts](https://github.com/skeema/knownhosts) is a wrapper of `x/crypto/ssh/knownhosts` that addresses this issue. This commit replaces the usage of `x/crypto/ssh/knownhosts` in containers/common with `github.com/skeema/knownhosts`. Signed-off-by: Mario Loriedo <mario.loriedo@gmail.com>
Package [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts) has an issue when an SSH server has many public keys (i.e. supports multiple crypto algorithms). For instance, if the local `known_hosts` file entries don't match the first SSH server key but match other keys of the SSH server, the handshake fails with a key mismatch error. See golang/go#29286 and containers/podman#23575. Package [github.com/skeema/knownhosts](https://github.com/skeema/knownhosts) is a wrapper of `x/crypto/ssh/knownhosts` that addresses this issue. This commit replaces the usage of `x/crypto/ssh/knownhosts` in containers/common with `github.com/skeema/knownhosts`. Signed-off-by: Mario Loriedo <mario.loriedo@gmail.com>
Package [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts) has an issue when an SSH server has many public keys (i.e. supports multiple crypto algorithms). For instance, if the local `known_hosts` file entries don't match the first SSH server key but match other keys of the SSH server, the handshake fails with a key mismatch error. See golang/go#29286 and containers/podman#23575. Package [github.com/skeema/knownhosts](https://github.com/skeema/knownhosts) is a wrapper of `x/crypto/ssh/knownhosts` that addresses this issue. This commit replaces the usage of `x/crypto/ssh/knownhosts` in containers/common with `github.com/skeema/knownhosts`. Signed-off-by: Mario Loriedo <mario.loriedo@gmail.com>
Package [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts) has an issue when an SSH server has many public keys (i.e. supports multiple crypto algorithms). For instance, if the local `known_hosts` file entries don't match the first SSH server key but match other keys of the SSH server, the handshake fails with a key mismatch error. See golang/go#29286 and containers/podman#23575. Package [github.com/skeema/knownhosts](https://github.com/skeema/knownhosts) is a wrapper of `x/crypto/ssh/knownhosts` that addresses this issue. This commit replaces the usage of `x/crypto/ssh/knownhosts` in containers/common with `github.com/skeema/knownhosts`. Signed-off-by: Mario Loriedo <mario.loriedo@gmail.com>
…Fixes go-git#411 This commit adjusts the transport/ssh logic in command.connect(), so that it now auto-populates ssh.ClientConfig.HostKeyAlgorithms. The algorithms are chosen based on the known host keys for the target host, as obtained from the known_hosts file. In order to look-up the algorithms from the known_hosts file, external module github.com/skeema/knownhosts is used. This package is just a thin wrapper around golang.org/x/crypto/ssh/knownhosts, adding an extra mechanism to query the known_hosts keys, implemented in a way which avoids duplication of any golang.org/x/crypto/ssh/knownhosts logic. Because HostKeyAlgorithms vary by target host, some related logic for setting HostKeyCallback has been moved out of the various AuthMethod implementations. This was necessary because the old HostKeyCallbackHelper is not host-specific. Since known_hosts handling isn't really tied to AuthMethod anyway, it seems reasonable to separate these. Previously-exported types/methods remain in place for backwards compat, but some of them are now unused. For testing approach, see pull request. Issue go-git#411 can only be reproduced via end-to-end / integration testing, since it requires actually launching an SSH connection, in order to see the key mismatch error triggered from golang/go#29286 as the root cause.
Package [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts) has an issue when an SSH server has many public keys (i.e. supports multiple crypto algorithms). For instance, if the local `known_hosts` file entries don't match the first SSH server key but match other keys of the SSH server, the handshake fails with a key mismatch error. See golang/go#29286 and containers/podman#23575. Package [github.com/skeema/knownhosts](https://github.com/skeema/knownhosts) is a wrapper of `x/crypto/ssh/knownhosts` that addresses this issue. This commit replaces the usage of `x/crypto/ssh/knownhosts` in containers/common with `github.com/skeema/knownhosts`. Signed-off-by: Mario Loriedo <mario.loriedo@gmail.com>
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
This is the latest docker release (yes)
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
knownHostsCallback is an ssh.HostKeysCallback.
2 machines:
machine A has ecdsa-sha2-nistp256 key for remote host in known hosts file
machine B has ssh-ed25519 key for remote host in known hosts file
If machine A connects to the remote host, the remote host sends the ecdsa-sha2-nistp256 key and is allowed to continue the handshake
If machine B connects to the remote host, the remote host sends the ecdsa-sha2-nistp256 key and is rejected because the callback returns an error.
If I set the host key list to prefer ["ssh-ed25519","ecdsa-sha2-nistp256"...]
Machine A fails
Machine B succeeds
What did you expect to see?
Since there is no mechanism for discovering the available hostkeys for a host published in ssh/knownhosts , I expected it to try each hostkey in the preference list in turn, failing only if all the keys had been tried.
What did you see instead?
SSH Client ceases handshake after receiving the first error response from the HostKeysCallback.
Since only the method on the database is returned by knownhosts.New() it is not easy to add another method accessing the same hostKeyDB instance.
I propose adding an initializing function for the database from knownhosts which returns the database - NewDB to complement New which would return a hostkeys interface.
There would be published methods on the receiver:
That way you can just use:
Alternatively if the protocol allows for it, the host key algorithms could be tried in turn until you run out of algorithms (fail) or you have a match (success)
The text was updated successfully, but these errors were encountered: