https://github.com/cmoog/sshproxy
An authentication termination SSH proxy.
https://github.com/cmoog/sshproxy
golang reverse-proxy ssh ssh-proxy
Last synced: 6 months ago
JSON representation
An authentication termination SSH proxy.
- Host: GitHub
- URL: https://github.com/cmoog/sshproxy
- Owner: cmoog
- License: mit
- Created: 2021-02-08T00:35:24.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2023-09-08T19:11:07.000Z (over 2 years ago)
- Last Synced: 2025-03-23T04:25:15.336Z (9 months ago)
- Topics: golang, reverse-proxy, ssh, ssh-proxy
- Language: Go
- Homepage:
- Size: 42 KB
- Stars: 13
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# sshproxy
[](https://pkg.go.dev/github.com/cmoog/sshproxy)
[](https://goreportcard.com/report/github.com/cmoog/sshproxy)
[](https://codecov.io/gh/cmoog/sshproxy)
Package sshproxy provides a slim SSH reverse proxy built
atop the `golang.org/x/crypto/ssh` package.
```text
go get github.com/cmoog/sshproxy
```
## Authorization termination proxy
`sshproxy.ReverseProxy` implements a single host reverse proxy
for SSH servers and clients. Its API is modeled after the ergonomics
of the [HTTP reverse proxy](https://pkg.go.dev/net/http/httputil#ReverseProxy) implementation
from the standard library.
It enables the proxy to perform authorization termination,
whereby custom authorization logic of the single entrypoint can protect
a set of SSH hosts hidden in a private network.
For example, one could conceivably use OAuth as a basis for verifying
identity and ownership of public keys.
## Example usage
Consider the following bare-bones example with error handling omitted for brevity.
```go
package main
import (
"net"
"golang.org/x/crypto/ssh"
"github.com/cmoog/sshproxy"
)
func main() {
serverConfig := ssh.ServerConfig{
// TODO: add your custom public key authentication logic
PublicKeyCallback: customPublicKeyAuthenticationLogic
}
serverConfig.AddHostKey(reverseProxyHostKey)
listener, _ := net.Listen("tcp", reverseProxyEntrypoint)
for {
clientConnection, _ := listener.Accept()
go func() {
defer clientConnection.Close()
sshConn, sshChannels, sshRequests, _ := ssh.NewServerConn(clientConnection, &serverConfig)
// TODO: add your custom routing logic based the SSH `user` string, and/or the public key
targetServer, targetServerConnectionConfig := customRoutingLogic(sshConn.User())
proxy := sshproxy.New(targetServer, targetServerConnectionConfig)
_ = proxy.Serve(ctx, sshConn, sshChannels, sshRequests)
}()
}
}
```