package ssh

Import Path
	github.com/gliderlabs/ssh (on go.dev)

Dependency Relation
	imports 19 packages, and imported by one package

Involved Source Files agent.go conn.go context.go Package ssh wraps the crypto/ssh package with a higher-level API for building SSH servers. The goal of the API was to make it as simple as using net/http, so the API is very similar. You should be able to build any SSH server using only this package, which wraps relevant types and some functions from crypto/ssh. However, you still need to use crypto/ssh for building SSH clients. ListenAndServe starts an SSH server with a given address, handler, and options. The handler is usually nil, which means to use DefaultHandler. Handle sets DefaultHandler: ssh.Handle(func(s ssh.Session) { io.WriteString(s, "Hello world\n") }) log.Fatal(ssh.ListenAndServe(":2222", nil)) If you don't specify a host key, it will generate one every time. This is convenient except you'll have to deal with clients being confused that the host key is different. It's a better idea to generate or point to an existing key on your system: log.Fatal(ssh.ListenAndServe(":2222", nil, ssh.HostKeyFile("/Users/progrium/.ssh/id_rsa"))) Although all options have functional option helpers, another way to control the server's behavior is by creating a custom Server: s := &ssh.Server{ Addr: ":2222", Handler: sessionHandler, PublicKeyHandler: authHandler, } s.AddHostKey(hostKeySigner) log.Fatal(s.ListenAndServe()) This package automatically handles basic SSH requests like setting environment variables, requesting PTY, and changing window size. These requests are processed, responded to, and any relevant state is updated. This state is then exposed to you via the Session interface. The one big feature missing from the Session abstraction is signals. This was started, but not completed. Pull Requests welcome! options.go server.go session.go ssh.go tcpip.go util.go wrap.go
Code Examples package main import ( "github.com/gliderlabs/ssh" ) func main() { ssh.ListenAndServe(":2222", nil, ssh.HostKeyFile("/path/to/host/key")) } package main import ( "io" "github.com/gliderlabs/ssh" ) func main() { ssh.ListenAndServe(":2222", func(s ssh.Session) { io.WriteString(s, "Hello world\n") }) } package main import ( "github.com/gliderlabs/ssh" ) func main() { ssh.ListenAndServe(":2222", nil, ssh.NoPty()) } package main import ( "github.com/gliderlabs/ssh" ) func main() { ssh.ListenAndServe(":2222", nil, ssh.PasswordAuth(func(ctx ssh.Context, pass string) bool { return pass == "secret" }), ) } package main import ( "os" "github.com/gliderlabs/ssh" ) func main() { ssh.ListenAndServe(":2222", nil, ssh.PublicKeyAuth(func(ctx ssh.Context, key ssh.PublicKey) bool { data, _ := os.ReadFile("/path/to/allowed/key.pub") allowed, _, _, _, _ := ssh.ParseAuthorizedKey(data) return ssh.KeysEqual(key, allowed) }), ) }
Package-Level Type Names (total 26)
/* sort by: | */
BannerHandler is a callback for displaying the server banner.
type ChannelHandler (func)
ConnCallback is a hook for new connections before handling. It allows wrapping for timeouts and limiting by returning the net.Conn that will be used as the underlying connection. func WrapConn(fn ConnCallback) Option
ConnectionFailedCallback is a hook for reporting failed connections Please note: the net.Conn is likely to be closed at this point
Context is a package specific context interface. It exposes connection metadata and allows new values to be easily written to it. It's used in authentication handlers and callbacks, and its underlying context.Context is exposed on Session in the session Handler. A connection-scoped lock is also embedded in the context to make it easier to limit operations per-connection. ClientVersion returns the version reported by the client. Deadline returns the time when work done on behalf of this context should be canceled. Deadline returns ok==false when no deadline is set. Successive calls to Deadline return the same results. Done returns a channel that's closed when work done on behalf of this context should be canceled. Done may return nil if this context can never be canceled. Successive calls to Done return the same value. The close of the Done channel may happen asynchronously, after the cancel function returns. WithCancel arranges for Done to be closed when cancel is called; WithDeadline arranges for Done to be closed when the deadline expires; WithTimeout arranges for Done to be closed when the timeout elapses. Done is provided for use in select statements: // Stream generates values with DoSomething and sends them to out // until DoSomething returns an error or ctx.Done is closed. func Stream(ctx context.Context, out chan<- Value) error { for { v, err := DoSomething(ctx) if err != nil { return err } select { case <-ctx.Done(): return ctx.Err() case out <- v: } } } See https://blog.golang.org/pipelines for more examples of how to use a Done channel for cancellation. If Done is not yet closed, Err returns nil. If Done is closed, Err returns a non-nil error explaining why: DeadlineExceeded if the context's deadline passed, or Canceled if the context was canceled for some other reason. After Err returns a non-nil error, successive calls to Err return the same error. LocalAddr returns the local address for this connection. ( Context) Lock() Permissions returns the Permissions object used for this connection. RemoteAddr returns the remote address for this connection. ServerVersion returns the version reported by the server. SessionID returns the session hash. SetValue allows you to easily write new values into the underlying context. ( Context) Unlock() User returns the username used when establishing the SSH connection. Value returns the value associated with this context for key, or nil if no value is associated with key. Successive calls to Value with the same key returns the same result. Use context values only for request-scoped data that transits processes and API boundaries, not for passing optional parameters to functions. A key identifies a specific value in a Context. Functions that wish to store values in Context typically allocate a key in a global variable then use that key as the argument to context.WithValue and Context.Value. A key can be any type that supports equality; packages should define keys as an unexported type to avoid collisions. Packages that define a Context key should provide type-safe accessors for the values stored using that key: // Package user defines a User type that's stored in Contexts. package user import "context" // User is the type of value stored in the Contexts. type User struct {...} // key is an unexported type for keys defined in this package. // This prevents collisions with keys defined in other packages. type key int // userKey is the key for user.User values in Contexts. It is // unexported; clients use user.NewContext and user.FromContext // instead of using this key directly. var userKey key // NewContext returns a new Context that carries value u. func NewContext(ctx context.Context, u *User) context.Context { return context.WithValue(ctx, userKey, u) } // FromContext returns the User value stored in ctx, if any. func FromContext(ctx context.Context) (*User, bool) { u, ok := ctx.Value(userKey).(*User) return u, ok } Context : context.Context Context : sync.Locker func Session.Context() Context func DefaultSessionHandler(srv *Server, conn *gossh.ServerConn, newChan gossh.NewChannel, ctx Context) func DirectTCPIPHandler(srv *Server, conn *gossh.ServerConn, newChan gossh.NewChannel, ctx Context) func SetAgentRequested(ctx Context) func (*ForwardedTCPHandler).HandleSSHRequest(ctx Context, srv *Server, req *gossh.Request) (bool, []byte)
ForwardedTCPHandler can be enabled by creating a ForwardedTCPHandler and adding the HandleSSHRequest callback to the server's RequestHandlers under tcpip-forward and cancel-tcpip-forward. Mutex sync.Mutex (*ForwardedTCPHandler) HandleSSHRequest(ctx Context, srv *Server, req *gossh.Request) (bool, []byte) Lock locks m. If the lock is already in use, the calling goroutine blocks until the mutex is available. TryLock tries to lock m and reports whether it succeeded. Note that while correct uses of TryLock do exist, they are rare, and use of TryLock is often a sign of a deeper problem in a particular use of mutexes. Unlock unlocks m. It is a run-time error if m is not locked on entry to Unlock. A locked [Mutex] is not associated with a particular goroutine. It is allowed for one goroutine to lock a Mutex and then arrange for another goroutine to unlock it. *ForwardedTCPHandler : sync.Locker
Handler is a callback for handling established SSH sessions. func Handle(handler Handler) func ListenAndServe(addr string, handler Handler, options ...Option) error func Serve(l net.Listener, handler Handler, options ...Option) error func (*Server).Handle(fn Handler) var DefaultHandler
KeyboardInteractiveHandler is a callback for performing keyboard-interactive authentication. func KeyboardInteractiveAuth(fn KeyboardInteractiveHandler) Option
LocalPortForwardingCallback is a hook for allowing port forwarding
Option is a functional option handler for Server. func HostKeyFile(filepath string) Option func HostKeyPEM(bytes []byte) Option func KeyboardInteractiveAuth(fn KeyboardInteractiveHandler) Option func NoPty() Option func PasswordAuth(fn PasswordHandler) Option func PublicKeyAuth(fn PublicKeyHandler) Option func WrapConn(fn ConnCallback) Option func ListenAndServe(addr string, handler Handler, options ...Option) error func Serve(l net.Listener, handler Handler, options ...Option) error func (*Server).SetOption(option Option) error
PasswordHandler is a callback for performing password authentication. func PasswordAuth(fn PasswordHandler) Option
The Permissions type holds fine-grained permissions that are specific to a user or a specific authentication method for a user. Permissions, except for "source-address", must be enforced in the server application layer, after successful authentication. Permissions *gossh.Permissions CriticalOptions indicate restrictions to the default permissions, and are typically used in conjunction with user certificates. The standard for SSH certificates defines "force-command" (only allow the given command to execute) and "source-address" (only allow connections from the given address). The SSH package currently only enforces the "source-address" critical option. It is up to server implementations to enforce other critical options, such as "force-command", by checking them after the SSH handshake is successful. In general, SSH servers should reject connections that specify critical options that are unknown or not supported. Extensions are extra functionality that the server may offer on authenticated connections. Lack of support for an extension does not preclude authenticating a user. Common extensions are "permit-agent-forwarding", "permit-X11-forwarding". The Go SSH library currently does not act on any extension, and it is up to server implementations to honor them. Extensions can be used to pass data from the authentication callbacks to the server application layer. ExtraData allows to store user defined data. func Context.Permissions() *Permissions func Session.Permissions() Permissions
Pty represents a PTY request and configuration. Term string Window Window func Session.Pty() (Pty, <-chan Window, bool)
PtyCallback is a hook for allowing PTY sessions.
PublicKey is an abstraction of different types of public keys. Marshal returns the serialized key data in SSH wire format, with the name prefix. To unmarshal the returned data, use the ParsePublicKey function. Type returns the key format name, e.g. "ssh-rsa". Verify that sig is a signature on the given data using this key. This method will hash the data appropriately first. sig.Format is allowed to be any signature algorithm compatible with the key type, the caller should check if it has more stringent requirements. *golang.org/x/crypto/ssh.Certificate golang.org/x/crypto/ssh.PublicKey (interface) PublicKey : golang.org/x/crypto/ssh.PublicKey func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) func ParsePublicKey(in []byte) (out PublicKey, err error) func Session.PublicKey() PublicKey func KeysEqual(ak, bk PublicKey) bool
PublicKeyHandler is a callback for performing public key authentication. func PublicKeyAuth(fn PublicKeyHandler) Option
type RequestHandler (func)
ReversePortForwardingCallback is a hook for allowing reverse port forwarding
Server defines parameters for running an SSH server. The zero value for Server is a valid configuration. When both PasswordHandler and PublicKeyHandler are nil, no client authentication is performed. // TCP address to listen on, ":22" if empty // server banner // server banner handler, overrides Banner ChannelHandlers allow overriding the built-in session handlers or provide extensions to the protocol, such as tcpip forwarding. By default only the "session" handler is enabled. // optional callback for wrapping net.Conn before handling // callback to report connection failures // handler to invoke, ssh.DefaultHandler if nil // private keys for the host key, must have at least one // connection timeout when no activity, none if empty // keyboard-interactive authentication handler // callback for allowing local port forwarding, denies all if nil // absolute connection timeout, none if empty // password authentication handler // callback for allowing PTY sessions, allows all if nil // public key authentication handler RequestHandlers allow overriding the server-level request handlers or provide extensions to the protocol, such as tcpip forwarding. By default no handlers are enabled. // callback for allowing reverse port forwarding, denies all if nil // callback for configuring detailed SSH options // callback for allowing or denying SSH sessions SubsystemHandlers are handlers which are similar to the usual SSH command handlers, but handle named subsystems. // server version to be sent before the initial handshake AddHostKey adds a private key as a host key. If an existing host key exists with the same algorithm, it is overwritten. Each server config must have at least one host key. Close immediately closes all active listeners and all active connections. Close returns any error returned from closing the Server's underlying Listener(s). Handle sets the Handler for the server. (*Server) HandleConn(newConn net.Conn) ListenAndServe listens on the TCP network address srv.Addr and then calls Serve to handle incoming connections. If srv.Addr is blank, ":22" is used. ListenAndServe always returns a non-nil error. Serve accepts incoming connections on the Listener l, creating a new connection goroutine for each. The connection goroutines read requests and then calls srv.Handler to handle sessions. Serve always returns a non-nil error. SetOption runs a functional option against the server. Shutdown gracefully shuts down the server without interrupting any active connections. Shutdown works by first closing all open listeners, and then waiting indefinitely for connections to close. If the provided context expires before the shutdown is complete, then the context's error is returned. *Server : github.com/prometheus/common/expfmt.Closer *Server : io.Closer func DefaultSessionHandler(srv *Server, conn *gossh.ServerConn, newChan gossh.NewChannel, ctx Context) func DirectTCPIPHandler(srv *Server, conn *gossh.ServerConn, newChan gossh.NewChannel, ctx Context) func (*ForwardedTCPHandler).HandleSSHRequest(ctx Context, srv *Server, req *gossh.Request) (bool, []byte)
ServerConfigCallback is a hook for creating custom default server configs
Session provides access to information about an SSH session and methods to read and write to the SSH channel with an embedded Channel interface from crypto/ssh. When Command() returns an empty slice, the user requested a shell. Otherwise the user is performing an exec with those command arguments. TODO: Signals Break regisers a channel to receive notifications of break requests sent from the client. The channel must handle break requests, or it will block the request handling loop. Registering nil will unregister the channel. During the time that no channel is registered, breaks are ignored. Close signals end of channel use. No data may be sent after this call. CloseWrite signals the end of sending in-band data. Requests may still be sent, and the other side may still send data Command returns a shell parsed slice of arguments that were provided by the user. Shell parsing splits the command string according to POSIX shell rules, which considers quoting not just whitespace. Context returns the connection's context. The returned context is always non-nil and holds the same data as the Context passed into auth handlers and callbacks. The context is canceled when the client's connection closes or I/O operation fails. Environ returns a copy of strings representing the environment set by the user for this session, in the form "key=value". Exit sends an exit status and then closes the session. LocalAddr returns the net.Addr of the server side of the connection. Permissions returns a copy of the Permissions object that was available for setup in the auth handlers via the Context. Pty returns PTY information, a channel of window size changes, and a boolean of whether or not a PTY was accepted for this session. PublicKey returns the PublicKey used to authenticate. If a public key was not used it will return nil. RawCommand returns the exact command that was provided by the user. Read reads up to len(data) bytes from the channel. RemoteAddr returns the net.Addr of the client side of the connection. SendRequest sends a channel request. If wantReply is true, it will wait for a reply and return the result as a boolean, otherwise the return value will be false. Channel requests are out-of-band messages so they may be sent even if the data stream is closed or blocked by flow control. If the channel is closed before a reply is returned, io.EOF is returned. Signals registers a channel to receive signals sent from the client. The channel must handle signal sends or it will block the SSH request loop. Registering nil will unregister the channel from signal sends. During the time no channel is registered signals are buffered up to a reasonable amount. If there are buffered signals when a channel is registered, they will be sent in order on the channel immediately after registering. Stderr returns an io.ReadWriter that writes to this channel with the extended data type set to stderr. Stderr may safely be read and written from a different goroutine than Read and Write respectively. Subsystem returns the subsystem requested by the user. User returns the username used when establishing the SSH connection. Write writes len(data) bytes to the channel. Session : github.com/miekg/dns.Writer Session : github.com/pion/stun.Connection Session : github.com/pion/stun/v3.Connection Session : github.com/prometheus/common/expfmt.Closer Session : golang.org/x/crypto/ssh.Channel Session : internal/bisect.Writer Session : io.Closer Session : io.ReadCloser Session : io.Reader Session : io.ReadWriteCloser Session : io.ReadWriter Session : io.WriteCloser Session : io.Writer func AgentRequested(sess Session) bool func ForwardAgentConnections(l net.Listener, s Session) func github.com/pancsta/asyncmachine-go/tools/cmd/am-dbg-ssh.NewSessionScreen(s Session) (tcell.Screen, error)
SessionRequestCallback is a callback for allowing or denying SSH sessions.
func Session.Signals(c chan<- Signal) const SIGABRT const SIGALRM const SIGFPE const SIGHUP const SIGILL const SIGINT const SIGKILL const SIGPIPE const SIGQUIT const SIGSEGV const SIGTERM const SIGUSR1 const SIGUSR2
A Signer can create signatures that verify against a public key. PublicKey returns the associated PublicKey. Sign returns a signature for the given data. This method will hash the data appropriately first. The signature algorithm is expected to match the key format returned by the PublicKey.Type method (and not to be any alternative algorithm supported by the key format). golang.org/x/crypto/ssh.AlgorithmSigner (interface) golang.org/x/crypto/ssh.MultiAlgorithmSigner (interface) golang.org/x/crypto/ssh.Signer (interface) Signer : golang.org/x/crypto/ssh.Signer func (*Server).AddHostKey(key Signer)
type SubsystemHandler (func)
Window represents the size of a PTY window. Height int Width int func Session.Pty() (Pty, <-chan Window, bool)
Package-Level Functions (total 19)
AgentRequested returns true if the client requested agent forwarding.
DirectTCPIPHandler can be enabled by adding it to the server's ChannelHandlers under direct-tcpip.
ForwardAgentConnections takes connections from a listener to proxy into the session on the OpenSSH channel for agent connections. It blocks and services connections until the listener stop accepting.
Handle registers the handler as the DefaultHandler.
HostKeyFile returns a functional option that adds HostSigners to the server from a PEM file at filepath.
HostKeyPEM returns a functional option that adds HostSigners to the server from a PEM file as bytes.
KeysEqual is constant time compare of the keys to avoid timing attacks.
ListenAndServe listens on the TCP network address addr and then calls Serve with handler to handle sessions on incoming connections. Handler is typically nil, in which case the DefaultHandler is used.
NewAgentListener sets up a temporary Unix socket that can be communicated to the session environment and used for forwarding connections.
NoPty returns a functional option that sets PtyCallback to return false, denying PTY requests.
ParseAuthorizedKey parses a public key from an authorized_keys file used in OpenSSH according to the sshd(8) manual page.
ParsePublicKey parses an SSH public key formatted for use in the SSH wire protocol according to RFC 4253, section 6.6.
PasswordAuth returns a functional option that sets PasswordHandler on the server.
PublicKeyAuth returns a functional option that sets PublicKeyHandler on the server.
Serve accepts incoming SSH connections on the listener l, creating a new connection goroutine for each. The connection goroutines read requests and then calls handler to handle sessions. Handler is typically nil, in which case the DefaultHandler is used.
SetAgentRequested sets up the session context so that AgentRequested returns true.
WrapConn returns a functional option that sets ConnCallback on the server.
Package-Level Variables (total 15)
ContextKeyClientVersion is a context key for use with Contexts in this package. The associated value will be of type string.
ContextKeyConn is a context key for use with Contexts in this package. The associated value will be of type gossh.ServerConn.
ContextKeyLocalAddr is a context key for use with Contexts in this package. The associated value will be of type net.Addr.
ContextKeyPermissions is a context key for use with Contexts in this package. The associated value will be of type *Permissions.
ContextKeyPublicKey is a context key for use with Contexts in this package. The associated value will be of type PublicKey.
ContextKeyRemoteAddr is a context key for use with Contexts in this package. The associated value will be of type net.Addr.
ContextKeyServer is a context key for use with Contexts in this package. The associated value will be of type *Server.
ContextKeyServerVersion is a context key for use with Contexts in this package. The associated value will be of type string.
ContextKeySessionID is a context key for use with Contexts in this package. The associated value will be of type string.
ContextKeyUser is a context key for use with Contexts in this package. The associated value will be of type string.
DefaultHandler is the default Handler used by Serve.
ErrServerClosed is returned by the Server's Serve, ListenAndServe, and ListenAndServeTLS methods after a call to Shutdown or Close.
Package-Level Constants (total 13)
POSIX signals as listed in RFC 4254 Section 6.10.
POSIX signals as listed in RFC 4254 Section 6.10.
POSIX signals as listed in RFC 4254 Section 6.10.
POSIX signals as listed in RFC 4254 Section 6.10.
POSIX signals as listed in RFC 4254 Section 6.10.
POSIX signals as listed in RFC 4254 Section 6.10.
POSIX signals as listed in RFC 4254 Section 6.10.
POSIX signals as listed in RFC 4254 Section 6.10.
POSIX signals as listed in RFC 4254 Section 6.10.
POSIX signals as listed in RFC 4254 Section 6.10.
POSIX signals as listed in RFC 4254 Section 6.10.
POSIX signals as listed in RFC 4254 Section 6.10.
POSIX signals as listed in RFC 4254 Section 6.10.