-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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: add NewControlClientConn #32958
Comments
Change https://golang.org/cl/193117 mentions this issue: |
@FiloSottile, if you have some time to investigate this proposal it would be much appreciated. |
The change looks good to me, and I would appreciate this interface. |
Hello, just checking to see where this is at in the proposal process. I am still maintaining a fork of this library for an environment where openssh control master sockets are in use. |
This was accidentally left off the list when it was created, and now it is waiting to get onto the list of proposals under active consideration. Sorry for the delay. |
Any code on how this would look like? |
Example usage:
|
Hi @ianlancetaylor, do you know if this proposal was ever reviewed? A colleague just reached out to see if there was a resolution for this, and figured I would ask... |
/cc @FiloSottile |
This proposal has been added to the active column of the proposals project |
Thank you for the proposal. We'd like to support ControlMaster, but this might be too low level an interface, as it leaves a lot of implementation of the ControlMaster protocol to the application. Are there other use cases for a Transport-level interface? What if we added NewClientConnFromControl that takes a net.Conn dialed to the UNIX socket? (We can't put it in ClientConfig as the socket changes between remotes.) By the way, I haven't looked at the protocol in depth yet, the reason we can't use NewClientConn for ControlMaster is that transport encryption happens at the transport level, right? |
Thanks for looking at this!
I can imagine a few (custom transports / proxy protocols), and will also note that this seems like a logical boundary to unit test RFC 4254 in isolation of 4253. All that said; I don't have a strong opinion on the matter and my only planned usage is a ControlMaster transport.
Seems fine to me. This was actually my original proposal and patch, which i closed out in favor of this one: My reasoning for assuming y'all might prefer the generic transport approach was:
I believe so, see RFC 4253. |
The application/product I was working on is a host access management solution using ssh certificates. We implemented a custom server to handle looking up the correct CA cert from our DB based on info in the client cert. This all worked fine but requires lots of ssh_config and dns check host gymnastics on the client side. We wanted to do improve this experience with a custom ssh client for users who were interesting in adopting it. IIR idea was that our client and server would overlay some logic prior to the actual ssh authentication handshake, do happy path setup, and then proceed to traditional ssh auth. I don’t remember all the details but the use case is pretty similar to a proxy. Having a transport interface supported here would be very convenient as opposed to some heavier solution with a separate proxy. And it would allow transports to be manage and swapped out independently from the ssh protocol and application implementations as future requirements may or may not dictate. |
@FiloSottile and I discussed this and suggest to add NewSharedClientConn that takes as an argument the net.Conn already opened to the control socket. Then the package doesn't need to figure out how to find a control socket. It also avoids "master" in ControlMaster, and the docs for OpenSSH refer to these as shared sockets. Thoughts? |
Can you confirm the approach in golang/crypto@6af5693 is along the lines of what you are suggesting, and that the OpenSSH specific handshake bits should be included? I chose "NewControlProxyClientConn" because the protocol comes in two flavors; "passenger" and "proxy". I only planned on adding support for "proxy" in my change. I don't have a strong opinion on naming, and "NewSharedClientConn" seems fine. |
ping @FiloSottile |
1 similar comment
ping @FiloSottile |
cc @golang/security |
Yeah, that looks like it, an implementation of proxy mode from PROTOCOL.mux.
Agreed on only supporting proxy mode, but I wouldn't expose that name in the API, because nothing user-facing mentions "proxy" in relation to muxing. "Proxy" makes me think about ProxyJump which is a similarly shaped but very different mechanism. How about |
It sounds like the API being proposed is
Is that correct? Is the channel part right? Can we say more about what "serviced" means? |
|
I've fixed the name in my summary, added a link to the summary to the top post, and retitled. Any objections to this NewControlClientConn? |
Based on the discussion above, this proposal seems like a likely accept. |
No change in consensus, so accepted. 🎉 |
Hello, do you recommend any further action on my part to advance the review of https://go-review.googlesource.com/c/crypto/+/383374 ? Thanks. |
Hello, do you recommend any further action on my part to advance the review of https://go-review.googlesource.com/c/crypto/+/383374 ? Thanks. |
I've added myself as a reviewer to https://go.dev/cl/383374 and left some comments. |
Amazing work @y3llowcake, would love to see this merged! |
Is there a way to create a unix socket same as openssh? Without this, do we need to start openssh first? Then we connect to the unix socket created by openssh. |
what about introducing |
@y3llowcake Are there some comments need to be resolved? Love to see it merged! |
For anyone stuck on this, before merging https://go-review.googlesource.com/c/crypto/+/383374. You can try this. But it's unsafe, and you do it at your own risk. package main
import (
"log"
"net"
"github.com/trzsz/trzsz-ssh/tssh"
"golang.org/x/crypto/ssh"
)
func main() {
conn, err := net.Dial("unix", "/path/to/ssh_control_path")
if err != nil {
log.Fatal(err)
}
ncc, chans, reqs, err := tssh.NewControlClientConn(conn)
if err != nil {
log.Fatal(err)
}
client := ssh.NewClient(ncc, chans, reqs)
session, err := client.NewSession()
if err != nil {
log.Fatal(err)
}
output, err := session.CombinedOutput("hostname")
if err != nil {
log.Fatal(err)
}
log.Printf("hostname: %s", string(output))
} You can also do it without tssh. Feel free to copy the whole file into your project: |
Just a note in case people see this comment and think it's a solution instead of this PR, tssh is just calling out (via exec) to openssh , so it's not really a golang implementation. |
Update, 23 Feb 2022: The new API is #32958 (comment).
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputProposal: Feature Request
I propose a modification to the x/crypto/ssh library that would allow an application to use this library's implementation of the SSH Connection Protocol (RFC 4254), but provide a separate implementation of the SSH Transport Protocol (RFC 4253).
Concretely this would require adapting the existing
packetConn
interface and exporting it, and then adding a Client constructor that operated on this interface:My immediate use case for this is to implement an application that uses an OpenSSH ControlMaster socket as the transport. However, I can imagine other use cases for this. This proposal is an alternative to #31874.
The text was updated successfully, but these errors were encountered: