Skip to content
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

git-ssh: try multiple algorithms for known_hosts #411

Closed
franklouwers opened this issue Nov 17, 2021 · 8 comments · Fixed by #655 or 610lyn/go-git#1
Closed

git-ssh: try multiple algorithms for known_hosts #411

franklouwers opened this issue Nov 17, 2021 · 8 comments · Fixed by #655 or 610lyn/go-git#1

Comments

@franklouwers
Copy link

Hi,

When using git over ssh, it seems that if a host (eg: GitHub.com) has multiple keys (eg: an rsa and an ed25519 ones), but only one of those keys is listed in the $HOME/.ssh/known_hosts, and the one that's not listed has a higher preference (e.g. ed25519 over rsa), then the git clone operation will fail.

I feel it should try to be more intelligent and try to use the rsa one.

@steffakasid
Copy link

I experienced the same. As workaround you could do the following: ssh-keyscan github.com >> known_hosts

@mojotx
Copy link

mojotx commented Dec 16, 2021

I've been struggling for several days, trying to get go-git to work, and I kept thinking it had something to do with ssh-agent, or that I had missed some minor thing in my code.

THIS was the problem, and running ssh-keyscan github.com >> ~/.ssh/known_hosts fixed it for me. Thank you, both @franklouwers and @steffakasid, for helping me fix this issue! 🙂

@mojotx
Copy link

mojotx commented Dec 16, 2021

I did some digging, to see how easy this would be to fix, and I don't think this is an issue in go-git's code

In plumbing/transport/ssh/common.go, in the dial() func, the code is calling ssh.NewClientConn().

	c, chans, reqs, err := ssh.NewClientConn(conn, addr, config)

That function is actually defined in golang/x/crypto/ssh. I didn't follow the rabbit trail all the way down into the crypto code, but I suspect that's where it needs to be fixed.

If I had the time, I would try writing a trivial Go program that makes a SSH connection to Github,, disabling the pseudo-tty allocation, which would be the equivalent of ssh -T git@github.com.

Currently if you do that, and you have your SSH keys set up correctly, it prints something like this:

$ ssh -T git@github.com
Hi mojotx! You've successfully authenticated, but GitHub does not provide shell access.

If a trivial Go implementation of ssh -T git@github.com also gives you the same host-key error, then we know for sure that the problem is in the golang/x/crypto/ssh code.

For what it's worth, I tried forking the go-git repo, and then updating the crypto module, to see if it's been fixed already, and it hasn't.

$ go get -v -u golang.org/x/crypto
go get: upgraded golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 => v0.0.0-20211215153901-e495a2d5b3d3
go get: upgraded golang.org/x/net v0.0.0-20210326060303-6b1517762897 => v0.0.0-20211112202133-69e39bad7dc2
go get: upgraded golang.org/x/text v0.3.3 => v0.3.6

@jaredallard
Copy link

Here's a workaround for ~/.ssh/known_hosts for those running into this:

ssh-keyscan -t rsa github.com > ~/.ssh/known_hosts
ssh-keyscan -t ecdsa github.com >> ~/.ssh/known_hosts

This seems to 100% of the time ensure this works. It's kinda confusing.

@rgalanakis
Copy link

@jaredallard and others, thank you for the workarounds!

rm3l added a commit to rm3l/gh-org-repo-sync that referenced this issue Feb 16, 2022
Leverage the standard Git command for such operations,
which should anyways be available for using the GitHub CLI.
There are few issues like [1] with SSH known hosts when using go-git.

[1] go-git/go-git#411
@smveloso
Copy link

smveloso commented Apr 8, 2022

From #411 (comment):

I did some digging, to see how easy this would be to fix, and I don't think this is an issue in go-git's code

It seems that the root cause is indeed in golang's ssh library: golang/go#29286

However, it's possible to work around it in code by explicitly setting the HostKeyAlgorithms field of https://pkg.go.dev/golang.org/x/crypto/ssh#ClientConfig. This was suggested here.

I did try and it works, by hardcoding the ssh key type I actually had in my known_hosts.

I don't know what would be the appropriate way of doing this kind of configuration on go-git. 🤔

NOTE: I'm working on a pull request. You can see the work so far here.

smveloso added a commit to smveloso-lab/go-git that referenced this issue Apr 13, 2022
evanelias added a commit to evanelias/go-git that referenced this issue Jun 20, 2022
…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.
@evanelias
Copy link
Contributor

I've just submitted a new pull request #548 which adds auto-population of ssh.ClientConfig.HostKeyAlgorithms, based on the known_hosts entries for the git remote host. Seems to work properly and solve this issue in my testing :)

@shaftoe
Copy link

shaftoe commented Jun 21, 2022

@evanelias looks great! thanks a lot

rohankmr414 pushed a commit to rohankmr414/go-git that referenced this issue Oct 12, 2022
…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.
gibchikafa pushed a commit to gibchikafa/go-git that referenced this issue Nov 23, 2022
…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.
aymanbagabas added a commit to aymanbagabas/go-git that referenced this issue Jan 9, 2023
Don't overwrite HostKeyCallback if one is provided.

Fixes: c35b808 ("plumbing: transport/ssh, auto-populate ClientConfig.HostKeyAlgorithms. Fixes go-git#411")
Fixes: go-git#654
Signed-off-by: Ayman Bagabas <ayman.bagabas@gmail.com>
aymanbagabas added a commit to aymanbagabas/go-git that referenced this issue Mar 5, 2023
Don't overwrite HostKeyCallback if one is provided.

Fixes: c35b808 ("plumbing: transport/ssh, auto-populate ClientConfig.HostKeyAlgorithms. Fixes go-git#411")
Fixes: go-git#654
Signed-off-by: Ayman Bagabas <ayman.bagabas@gmail.com>
durandj pushed a commit to durandj/go-git that referenced this issue Jul 1, 2023
…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.
durandj pushed a commit to durandj/go-git that referenced this issue Jul 1, 2023
Don't overwrite HostKeyCallback if one is provided.

Fixes: c35b808 ("plumbing: transport/ssh, auto-populate ClientConfig.HostKeyAlgorithms. Fixes go-git#411")
Fixes: go-git#654
Signed-off-by: Ayman Bagabas <ayman.bagabas@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
8 participants