Documentation
¶
Overview ¶
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:
ctx := context.Background()
ssh.Handle(func(s ssh.Session) error {
_, err := io.WriteString(s, "Hello world\n")
return err
})
log.Fatal(ssh.ListenAndServe(ctx, ":2222", nil))
If you don't specify a host key, the Server generates one on first use and reuses it for its lifetime. This development convenience does not provide a stable identity across processes. Production servers should configure a persistent signer and set Server.RequireHostSigners. It's a better idea to generate or point to an existing key on your system:
log.Fatal(ssh.ListenAndServe(ctx, ":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(ctx))
See Server for lifecycle rules, ErrorHandler for operational errors, and SessionExitError for controlled session failures.
This package handles basic SSH requests such as environment variables, PTYs, window changes, signals, and breaks. Relevant state and delivery hooks are exposed through Session.
The module requires the Go version declared in go.mod. The core package supports the operating systems supported by its dependencies; examples that launch Unix programs or use Unix sockets have additional platform requirements.
Index ¶
- Constants
- Variables
- func AgentRequested(sess Session) bool
- func DefaultSessionHandler(srv *Server, conn *gossh.ServerConn, newChan gossh.NewChannel, ctx Context) error
- func DirectStreamLocalHandler(srv *Server, sshConn *gossh.ServerConn, newChan gossh.NewChannel, ctx Context) error
- func DirectTCPIPHandler(srv *Server, sshConn *gossh.ServerConn, newChan gossh.NewChannel, ctx Context) error
- func ForwardAgentConnections(ln net.Listener, logger log.Logger, sess Session)
- func FullDuplexCopy(ctx context.Context, left io.ReadWriteCloser, right io.ReadWriteCloser, ...) (rErr error)
- func Handle(handler Handler)
- func KeysEqual(ak, bk PublicKey) bool
- func ListenAndServe(ctx context.Context, addr string, handler Handler, options ...Option) error
- func NewAgentListener() (net.Listener, error)
- func Serve(ctx context.Context, l net.Listener, handler Handler, options ...Option) error
- func SetAgentRequested(ctx Context)
- type AgentForwardingCallback
- type BannerHandler
- type ChannelHandler
- type Cipher
- type Ciphers
- func (c Ciphers) Contains(v Cipher) bool
- func (c Ciphers) IsCumulative() bool
- func (c Ciphers) IsEmpty() bool
- func (c Ciphers) IsEqualTo(other any) bool
- func (c Ciphers) IsZero() bool
- func (c Ciphers) MarshalText() (text []byte, err error)
- func (c Ciphers) MarshalTexts() (texts [][]byte, err error)
- func (c *Ciphers) Set(text string) error
- func (c Ciphers) String() string
- func (c *Ciphers) UnmarshalText(text []byte) error
- func (c Ciphers) Validate() error
- type ConnCallback
- type ConnectionFailedCallback
- type Context
- type DisconnectCallback
- type ErrorHandler
- type ErrorOperation
- type ErrorResponder
- type ErrorScope
- type ForwardedTCPHandler
- type ForwardedUnixHandler
- type FullDuplexCopyOpts
- type GracefulShutdownHandler
- type Handler
- type KeyExchange
- func (ke KeyExchange) IsEqualTo(other any) bool
- func (ke KeyExchange) IsZero() bool
- func (ke KeyExchange) MarshalText() (text []byte, err error)
- func (ke *KeyExchange) Set(text string) error
- func (ke KeyExchange) String() string
- func (ke *KeyExchange) UnmarshalText(text []byte) error
- func (ke KeyExchange) Validate() error
- type KeyExchanges
- func (ke KeyExchanges) Contains(v KeyExchange) bool
- func (ke KeyExchanges) IsCumulative() bool
- func (ke KeyExchanges) IsEmpty() bool
- func (ke KeyExchanges) IsEqualTo(other any) bool
- func (ke KeyExchanges) IsZero() bool
- func (ke KeyExchanges) MarshalText() (text []byte, err error)
- func (ke KeyExchanges) MarshalTexts() (texts [][]byte, err error)
- func (ke *KeyExchanges) Set(text string) error
- func (ke KeyExchanges) String() string
- func (ke *KeyExchanges) UnmarshalText(text []byte) error
- func (ke KeyExchanges) Validate() error
- type KeyboardInteractiveHandler
- type LocalPortForwardingCallback
- type LocalUnixForwardingCallback
- type MaxStartupsConfig
- type MessageAuthentication
- func (ma MessageAuthentication) IsEqualTo(other any) bool
- func (ma MessageAuthentication) IsZero() bool
- func (ma MessageAuthentication) MarshalText() (text []byte, err error)
- func (ma *MessageAuthentication) Set(text string) error
- func (ma MessageAuthentication) String() string
- func (ma *MessageAuthentication) UnmarshalText(text []byte) error
- func (ma MessageAuthentication) Validate() error
- type MessageAuthentications
- func (me MessageAuthentications) Contains(v MessageAuthentication) bool
- func (me MessageAuthentications) IsCumulative() bool
- func (me MessageAuthentications) IsEmpty() bool
- func (me MessageAuthentications) IsEqualTo(other any) bool
- func (me MessageAuthentications) IsZero() bool
- func (me MessageAuthentications) MarshalText() (text []byte, err error)
- func (me MessageAuthentications) MarshalTexts() (texts [][]byte, err error)
- func (me *MessageAuthentications) Set(text string) error
- func (me MessageAuthentications) String() string
- func (me *MessageAuthentications) UnmarshalText(text []byte) error
- func (me MessageAuthentications) Validate() error
- type Option
- func EnableProxyProtocol(config ...ProxyProtocolConfig) Option
- 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 WithErrorHandler(handler ErrorHandler) Option
- func WithGracefulShutdownHandler(handler GracefulShutdownHandler) Option
- func WithGracefulShutdownTimeout(timeout time.Duration) Option
- func WrapConn(fn ConnCallback) Option
- type PasswordHandler
- type Permissions
- type ProxyProtocolConfig
- type Pty
- type PtyCallback
- type PublicKey
- type PublicKeyHandler
- type Request
- type RequestHandler
- type RequestResponseWriter
- type ReversePortForwardingCallback
- type ReverseUnixForwardingCallback
- type Server
- func (srv *Server) AddHostKey(key Signer)
- func (srv *Server) Handle(fn Handler)
- func (srv *Server) HandleConn(ctx context.Context, newConn net.Conn) error
- func (srv *Server) ListenAndServe(ctx context.Context) error
- func (srv *Server) Serve(ctx context.Context, l net.Listener) error
- func (srv *Server) SetOption(option Option) error
- type ServerConfigCallback
- type Session
- type SessionExitError
- type SessionRequestCallback
- type Signal
- type Signer
- type SubsystemHandler
- type Window
Examples ¶
Constants ¶
const ( DefaultHandshakeTimeout = 2 * time.Minute DefaultIdleTimeout = time.Duration(0) DefaultMaxTimeout = time.Duration(0) DefaultSessionRequestTimeout = 30 * time.Second DefaultMaxStartupsStart = 10 DefaultMaxStartupsRate = 30 DefaultMaxStartupsFull = 100 DefaultMaxSessionsPerConnection = 10 DefaultMaxChannelsPerConnection = 64 DefaultMaxReverseForwardsPerConnection = 16 DefaultMaxConnections = 256 DefaultMaxChannels = 64 DefaultMaxReverseForwards = 256 )
Variables ¶
var ( // ContextKeyUser is a context key for use with Contexts in this package. // The associated value will be of type string. ContextKeyUser = &contextKey{"user"} // ContextKeySessionID is a context key for use with Contexts in this package. // The associated value will be of type string. ContextKeySessionID = &contextKey{"session-id"} // ContextKeyPermissions is a context key for use with Contexts in this package. // The associated value will be of type *Permissions. ContextKeyPermissions = &contextKey{"permissions"} // ContextKeyClientVersion is a context key for use with Contexts in this package. // The associated value will be of type string. ContextKeyClientVersion = &contextKey{"client-version"} // ContextKeyServerVersion is a context key for use with Contexts in this package. // The associated value will be of type string. ContextKeyServerVersion = &contextKey{"server-version"} // ContextKeyLocalAddr is a context key for use with Contexts in this package. // The associated value will be of type net.Addr. ContextKeyLocalAddr = &contextKey{"local-addr"} // ContextKeyRemoteAddr is a context key for use with Contexts in this package. // The associated value will be of type net.Addr. ContextKeyRemoteAddr = &contextKey{"remote-addr"} // ContextKeyServer is a context key for use with Contexts in this package. // The associated value will be of type *Server. ContextKeyServer = &contextKey{"ssh-server"} // ContextKeyConn is a context key for use with Contexts in this package. // The associated value will be of type *gossh.ServerConn after the SSH // handshake has completed. ContextKeyConn = &contextKey{"ssh-conn"} // ContextKeyPublicKey is a context key for use with Contexts in this package. // The associated value will be of type PublicKey. ContextKeyPublicKey = &contextKey{"public-key"} )
var ( // ErrErrorResponseUnsupported is returned when an error cannot be reported // to the client at the point where it occurred. ErrErrorResponseUnsupported = errors.New("ssh: error response is not supported") // ErrErrorResponseAlreadySent is returned when an ErrorResponder is called // again after a response attempt. The first response may already have changed // the SSH protocol state even if it returned an error. ErrErrorResponseAlreadySent = errors.New("ssh: error response was already sent") // ErrErrorResponseExpired is returned when an ErrorResponder is called after // its ErrorHandler has returned. ErrErrorResponseExpired = errors.New("ssh: error responder has expired") // ErrNextErrorHandlerAlreadyCalled is returned when next is called more than // once by the same ErrorHandler invocation. ErrNextErrorHandlerAlreadyCalled = errors.New("ssh: next error handler was already called") // ErrNextErrorHandlerExpired is returned when next is called after its // ErrorHandler has returned. ErrNextErrorHandlerExpired = errors.New("ssh: next error handler has expired") // ErrNextErrorHandlerIncomplete indicates that next did not complete before // its ErrorHandler returned. ErrNextErrorHandlerIncomplete = errors.New("ssh: next error handler did not complete synchronously") )
var ( ErrRequestResponseAlreadySent = errors.New("ssh: request response was already sent") ErrRequestResponseExpired = errors.New("ssh: request response is no longer valid") ErrRequestResponseIncomplete = errors.New("ssh: request response did not complete synchronously") ErrRequestResponseNotSent = errors.New("ssh: request handler returned without a response") )
var ( // ErrGracefulShutdownTimeout is joined into the returned error when a // context-triggered graceful shutdown exceeds its configured period. ErrGracefulShutdownTimeout = errors.New("ssh: graceful shutdown timeout") ErrServerPermissionDenied = errors.New("permission denied") ErrServerHostSignerRequired = errors.New("ssh: at least one persistent host signer is required") ErrServerClientAuthRequired = errors.New("ssh: at least one client authentication method is required") ErrServerAuthCallbackConflict = errors.New("ssh: conflicting authentication callbacks") ErrChannelResponseAlreadySent = errors.New("ssh: channel response was already sent") ErrChannelResponseNotSent = errors.New("ssh: channel handler returned without accepting or rejecting the channel") )
var DefaultChannelHandlers = map[string]ChannelHandler{ "session": DefaultSessionHandler, }
DefaultChannelHandlers is used by servers with nil ChannelHandlers. It must not be mutated while any such server is serving connections.
var ( DefaultCiphers = Ciphers{ CipherAes256Gcm, CipherAes256Ctr, CipherAes192Ctr, } )
var ( DefaultKeyExchanges = KeyExchanges{ KeyExchangeCurve25519Sha256LibSsh, KeyExchangeCurve25519Sha256, KeyExchangeDh16Sha512, KeyExchangeMlkem768x25519xSha256, } )
var ( DefaultMessageAuthentications = MessageAuthentications{ MessageAuthenticationHmacSha2B512Etm, MessageAuthenticationHmacSha2B256Etm, } )
var DefaultRequestHandlers = map[string]RequestHandler{}
DefaultRequestHandlers is used by servers with nil RequestHandlers. It must not be mutated while any such server is serving connections.
var DefaultSubsystemHandlers = map[string]SubsystemHandler{}
DefaultSubsystemHandlers is used by servers with nil SubsystemHandlers. It must not be mutated while any such server is serving connections.
Functions ¶
func AgentRequested ¶
AgentRequested returns true if the client requested agent forwarding.
func DefaultSessionHandler ¶
func DefaultSessionHandler(srv *Server, conn *gossh.ServerConn, newChan gossh.NewChannel, ctx Context) error
func DirectStreamLocalHandler ¶ added in v0.2.0
func DirectStreamLocalHandler(srv *Server, sshConn *gossh.ServerConn, newChan gossh.NewChannel, ctx Context) error
DirectStreamLocalHandler handles client-to-server Unix socket forwarding. It can be enabled under the direct-streamlocal@openssh.com channel type. The configured LocalUnixForwardingCallback owns path authorization and dialing.
func DirectTCPIPHandler ¶
func DirectTCPIPHandler(srv *Server, sshConn *gossh.ServerConn, newChan gossh.NewChannel, ctx Context) error
DirectTCPIPHandler can be enabled by adding it to the server's ChannelHandlers under direct-tcpip.
func ForwardAgentConnections ¶
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.
func FullDuplexCopy ¶
func FullDuplexCopy(ctx context.Context, left io.ReadWriteCloser, right io.ReadWriteCloser, opts *FullDuplexCopyOpts) (rErr error)
FullDuplexCopy copies data in both directions until both streams finish. It half-closes completed streams and closes both sides on cancellation or error. To guarantee cancellation, Close on each side must unblock concurrent Read and Write calls; implementations that do not honor that contract can prevent this function from returning. A nil context is treated as context.Background.
func ListenAndServe ¶
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. Canceling ctx stops the server. The returned error contains the context cause and may contain cleanup errors or ErrGracefulShutdownTimeout; callers should inspect it with errors.Is.
Example ¶
package main
import (
"context"
"io"
"log"
"github.com/engity-com/ssh-server-go"
)
func main() {
log.Fatal(ssh.ListenAndServe(context.Background(), ":2222", func(s ssh.Session) error {
_, err := io.WriteString(s, "Hello world\n")
return err
}))
}
Output:
func NewAgentListener ¶
NewAgentListener sets up a temporary Unix socket that can be communicated to the session environment and used for forwarding connections.
func Serve ¶
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. Canceling ctx stops this Serve scope. The returned error contains the context cause and may contain cleanup errors or ErrGracefulShutdownTimeout; callers should inspect it with errors.Is.
func SetAgentRequested ¶
func SetAgentRequested(ctx Context)
SetAgentRequested sets up the session context so that AgentRequested returns true.
Types ¶
type AgentForwardingCallback ¶
AgentForwardingCallback is a hook for allowing agent forwarding per session. A nil callback or false, nil denies agent forwarding. A non-nil error is passed to ErrorHandler and ends the session by default.
type BannerHandler ¶
type BannerHandler func(ctx Context, conn gossh.ConnMetadata) (string, error)
BannerHandler resolves the server banner for a connection. A returned error aborts the SSH handshake.
type ChannelHandler ¶
type ChannelHandler func(srv *Server, conn *gossh.ServerConn, newChan gossh.NewChannel, ctx Context) error
ChannelHandler handles one channel synchronously. It should not return until ownership of the channel and its associated resources has ended. Returning an error reports it to ErrorHandler.
type Ciphers ¶
type Ciphers []Cipher
func (Ciphers) IsCumulative ¶
func (Ciphers) MarshalText ¶
func (Ciphers) MarshalTexts ¶
func (*Ciphers) UnmarshalText ¶
type ConnCallback ¶
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. Implementations must return promptly and honor Context cancellation; network deadlines cannot forcibly stop callback code that blocks without doing I/O. Returning nil, nil drops the connection without reporting an operational error. A non-nil error aborts the SSH handshake. A returned connection must own the input connection and close it when the returned connection is closed.
type ConnectionFailedCallback ¶
ConnectionFailedCallback is a hook for reporting failed connections. The net.Conn is likely to be closed at this point. A returned error is joined with the connection failure before it is passed to ErrorHandler.
type Context ¶
type Context interface {
context.Context
sync.Locker
// User returns the current username, or "" before metadata is available.
User() string
// SessionID returns the hex-encoded session hash, or "" before it is available.
SessionID() string
// ClientVersion returns the version reported by the client, or "" before it is available.
ClientVersion() string
// ServerVersion returns the version reported by the server, or "" before it is available.
ServerVersion() string
// RemoteAddr returns the remote address, or nil before metadata is available.
RemoteAddr() net.Addr
// LocalAddr returns the local address, or nil before metadata is available.
LocalAddr() net.Addr
// Permissions returns the current authentication permissions. Server-created
// contexts initialize an empty value before authentication starts.
Permissions() *Permissions
// SetValue allows you to easily write new values into the underlying context.
SetValue(key, value any)
}
Context is a package-specific context interface. It exposes connection metadata and allows new values to be written to it. Metadata getters return zero values until metadata is available during the SSH handshake. Context is used in authentication handlers and callbacks and exposed by Session.Context. A connection-scoped lock is embedded for coordinating application state.
type DisconnectCallback ¶ added in v0.2.0
DisconnectCallback is called exactly once after a successfully established SSH connection ends. The Context is canceled, the connection is closed, and connection workers have stopped before the callback runs. Implementations must return promptly. A returned error is passed to ErrorHandler. Panics from the callback are not recovered.
type ErrorHandler ¶ added in v0.2.0
type ErrorHandler func( ctx context.Context, scope ErrorScope, operation ErrorOperation, err error, respond ErrorResponder, next ErrorHandler, ) (canContinue bool, filteredErr error)
ErrorHandler handles operational errors. scope and operation identify their source, respond sends a client-safe response, and next applies the default handling.
respond and next are valid only during the call and may each be used once. A non-nil filteredErr stops processing; otherwise canContinue permits, but does not guarantee, continued processing. Calls may run concurrently and must return promptly.
type ErrorOperation ¶ added in v0.2.0
type ErrorOperation uint8
ErrorOperation identifies the operation which failed within an ErrorScope.
const ( ErrorOperationAccept ErrorOperation = iota ErrorOperationParse ErrorOperationHandle ErrorOperationReply ErrorOperationHandshake ErrorOperationDial ErrorOperationListen ErrorOperationOpenChannel ErrorOperationForward )
func (ErrorOperation) MarshalText ¶ added in v0.2.0
func (v ErrorOperation) MarshalText() ([]byte, error)
func (*ErrorOperation) Set ¶ added in v0.2.0
func (v *ErrorOperation) Set(text string) error
func (ErrorOperation) String ¶ added in v0.2.0
func (v ErrorOperation) String() string
func (*ErrorOperation) UnmarshalText ¶ added in v0.2.0
func (v *ErrorOperation) UnmarshalText(text []byte) error
func (ErrorOperation) Validate ¶ added in v0.2.0
func (v ErrorOperation) Validate() error
type ErrorResponder ¶ added in v0.2.0
ErrorResponder sends a scope-appropriate response to the client. It is valid only during its ErrorHandler call and may be used once. closeAfterResponse closes the associated SSH connection after the response attempt.
type ErrorScope ¶ added in v0.2.0
type ErrorScope uint8
ErrorScope identifies the protocol resource in which an error occurred.
const ( ErrorScopeServer ErrorScope = iota ErrorScopeConnection ErrorScopeRequest ErrorScopeChannel ErrorScopeSession ErrorScopeForwarding )
func (ErrorScope) MarshalText ¶ added in v0.2.0
func (v ErrorScope) MarshalText() ([]byte, error)
func (*ErrorScope) Set ¶ added in v0.2.0
func (v *ErrorScope) Set(text string) error
func (ErrorScope) String ¶ added in v0.2.0
func (v ErrorScope) String() string
func (*ErrorScope) UnmarshalText ¶ added in v0.2.0
func (v *ErrorScope) UnmarshalText(text []byte) error
func (ErrorScope) Validate ¶ added in v0.2.0
func (v ErrorScope) Validate() error
type ForwardedTCPHandler ¶
type ForwardedTCPHandler struct {
Logger log.Logger
sync.Mutex
// contains filtered or unexported fields
}
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.
func (*ForwardedTCPHandler) HandleSSHRequest ¶
func (h *ForwardedTCPHandler) HandleSSHRequest(response RequestResponseWriter, request *Request) error
type ForwardedUnixHandler ¶ added in v0.2.0
type ForwardedUnixHandler struct {
Logger log.Logger
sync.Mutex
// contains filtered or unexported fields
}
ForwardedUnixHandler handles server-to-client Unix socket forwarding. Add HandleSSHRequest under streamlocal-forward@openssh.com and cancel-streamlocal-forward@openssh.com. Forwarding remains disabled unless a ReverseUnixForwardingCallback is configured.
func (*ForwardedUnixHandler) HandleSSHRequest ¶ added in v0.2.0
func (h *ForwardedUnixHandler) HandleSSHRequest(response RequestResponseWriter, request *Request) error
type FullDuplexCopyOpts ¶
type FullDuplexCopyOpts struct {
OnStart func()
OnEnd func(l2r, r2l int64, duration time.Duration, err error, wasInL2r *bool)
OnStreamStart func(isL2r bool)
OnStreamEnd func(isL2r bool, err error)
}
FullDuplexCopyOpts defines optional callbacks for observing a bidirectional copy. Callbacks are invoked asynchronously in event order on one observer goroutine and cannot delay FullDuplexCopy. They must still return promptly to avoid retaining that observer goroutine.
type GracefulShutdownHandler ¶ added in v0.2.0
GracefulShutdownHandler determines how long a context-triggered shutdown waits for connections to drain before closing them. A returned error forces immediate shutdown.
func NewGracefulShutdownTimeoutHandler ¶ added in v0.2.0
func NewGracefulShutdownTimeoutHandler(timeout time.Duration) GracefulShutdownHandler
NewGracefulShutdownTimeoutHandler returns a graceful shutdown handler that always uses timeout.
type Handler ¶
Handler handles an established SSH session. Returned errors are passed to ErrorHandler and end the session by default. Return SessionExitError for a controlled client message and exit status.
var DefaultHandler Handler
DefaultHandler is the default Handler used by Serve.
type KeyExchange ¶
type KeyExchange uint8
const ( KeyExchangeDh1Sha1 KeyExchange = iota KeyExchangeDh14Sha1 KeyExchangeDh14Sha256 KeyExchangeDh16Sha512 KeyExchangeEcdh256 KeyExchangeEcdh384 KeyExchangeEcdh521 KeyExchangeCurve25519Sha256LibSsh KeyExchangeCurve25519Sha256 KeyExchangeDhgexSha1 KeyExchangeDhgexSha256 KeyExchangeMlkem768x25519xSha256 )
func (KeyExchange) IsEqualTo ¶
func (ke KeyExchange) IsEqualTo(other any) bool
func (KeyExchange) IsZero ¶
func (ke KeyExchange) IsZero() bool
func (KeyExchange) MarshalText ¶
func (ke KeyExchange) MarshalText() (text []byte, err error)
func (*KeyExchange) Set ¶
func (ke *KeyExchange) Set(text string) error
func (KeyExchange) String ¶
func (ke KeyExchange) String() string
func (*KeyExchange) UnmarshalText ¶
func (ke *KeyExchange) UnmarshalText(text []byte) error
func (KeyExchange) Validate ¶
func (ke KeyExchange) Validate() error
type KeyExchanges ¶
type KeyExchanges []KeyExchange
func (KeyExchanges) Contains ¶
func (ke KeyExchanges) Contains(v KeyExchange) bool
func (KeyExchanges) IsCumulative ¶
func (ke KeyExchanges) IsCumulative() bool
func (KeyExchanges) IsEmpty ¶
func (ke KeyExchanges) IsEmpty() bool
func (KeyExchanges) IsEqualTo ¶
func (ke KeyExchanges) IsEqualTo(other any) bool
func (KeyExchanges) IsZero ¶
func (ke KeyExchanges) IsZero() bool
func (KeyExchanges) MarshalText ¶
func (ke KeyExchanges) MarshalText() (text []byte, err error)
func (KeyExchanges) MarshalTexts ¶
func (ke KeyExchanges) MarshalTexts() (texts [][]byte, err error)
func (*KeyExchanges) Set ¶
func (ke *KeyExchanges) Set(text string) error
func (KeyExchanges) String ¶
func (ke KeyExchanges) String() string
func (*KeyExchanges) UnmarshalText ¶
func (ke *KeyExchanges) UnmarshalText(text []byte) error
func (KeyExchanges) Validate ¶
func (ke KeyExchanges) Validate() error
type KeyboardInteractiveHandler ¶
type KeyboardInteractiveHandler func(ctx Context, conn gossh.ConnMetadata, challenger gossh.KeyboardInteractiveChallenge) (bool, error)
KeyboardInteractiveHandler is a callback for performing keyboard-interactive authentication. Returning false, nil denies the authentication attempt. A non-nil error aborts the SSH handshake.
type LocalPortForwardingCallback ¶
type LocalPortForwardingCallback func(ctx Context, conn gossh.ConnMetadata, destinationHost string, destinationPort uint32) (bool, error)
LocalPortForwardingCallback is a hook for allowing port forwarding. Returning false, nil denies the request; a non-nil error is passed to ErrorHandler.
type LocalUnixForwardingCallback ¶ added in v0.2.0
type LocalUnixForwardingCallback func(ctx Context, conn gossh.ConnMetadata, socketPath string) (net.Conn, error)
LocalUnixForwardingCallback handles a direct-streamlocal@openssh.com request. A successful callback transfers ownership of the returned connection to the server. Return ErrServerPermissionDenied to reject the request without exposing an operational error to the client. Implementations must honor context cancellation.
type MaxStartupsConfig ¶
type MaxStartupsConfig struct {
Start int // number of unauthenticated connections before random early drop begins
Rate int // initial drop probability in percent, clamped to 0..100
Full int // hard limit for unauthenticated connections; nonpositive disables the limit
}
MaxStartupsConfig limits concurrent unauthenticated connections using the OpenSSH start:rate:full random early-drop model.
type MessageAuthentication ¶
type MessageAuthentication uint8
const ( MessageAuthenticationHmacSha1 MessageAuthentication = iota MessageAuthenticationHmacSha1B96 MessageAuthenticationHmacSha2B256 MessageAuthenticationHmacSha2B512 MessageAuthenticationHmacSha2B256Etm MessageAuthenticationHmacSha2B512Etm )
func (MessageAuthentication) IsEqualTo ¶
func (ma MessageAuthentication) IsEqualTo(other any) bool
func (MessageAuthentication) IsZero ¶
func (ma MessageAuthentication) IsZero() bool
func (MessageAuthentication) MarshalText ¶
func (ma MessageAuthentication) MarshalText() (text []byte, err error)
func (*MessageAuthentication) Set ¶
func (ma *MessageAuthentication) Set(text string) error
func (MessageAuthentication) String ¶
func (ma MessageAuthentication) String() string
func (*MessageAuthentication) UnmarshalText ¶
func (ma *MessageAuthentication) UnmarshalText(text []byte) error
func (MessageAuthentication) Validate ¶
func (ma MessageAuthentication) Validate() error
type MessageAuthentications ¶
type MessageAuthentications []MessageAuthentication
func (MessageAuthentications) Contains ¶
func (me MessageAuthentications) Contains(v MessageAuthentication) bool
func (MessageAuthentications) IsCumulative ¶
func (me MessageAuthentications) IsCumulative() bool
func (MessageAuthentications) IsEmpty ¶
func (me MessageAuthentications) IsEmpty() bool
func (MessageAuthentications) IsEqualTo ¶
func (me MessageAuthentications) IsEqualTo(other any) bool
func (MessageAuthentications) IsZero ¶
func (me MessageAuthentications) IsZero() bool
func (MessageAuthentications) MarshalText ¶
func (me MessageAuthentications) MarshalText() (text []byte, err error)
func (MessageAuthentications) MarshalTexts ¶
func (me MessageAuthentications) MarshalTexts() (texts [][]byte, err error)
func (*MessageAuthentications) Set ¶
func (me *MessageAuthentications) Set(text string) error
func (MessageAuthentications) String ¶
func (me MessageAuthentications) String() string
func (*MessageAuthentications) UnmarshalText ¶
func (me *MessageAuthentications) UnmarshalText(text []byte) error
func (MessageAuthentications) Validate ¶
func (me MessageAuthentications) Validate() error
type Option ¶
Option is a functional option handler for Server.
func EnableProxyProtocol ¶ added in v0.2.0
func EnableProxyProtocol(config ...ProxyProtocolConfig) Option
EnableProxyProtocol returns a functional option that enables PROXY protocol processing. With no configuration, every connection must supply a PROXY header and the header is trusted from any peer. At most one configuration may be supplied.
func HostKeyFile ¶
HostKeyFile returns a functional option that adds HostSigners to the server from a PEM file at filepath.
Example ¶
package main
import (
"context"
"log"
"github.com/engity-com/ssh-server-go"
)
func main() {
log.Fatal(ssh.ListenAndServe(context.Background(), ":2222", nil, ssh.HostKeyFile("/path/to/host/key")))
}
Output:
func HostKeyPEM ¶
HostKeyPEM returns a functional option that adds HostSigners to the server from a PEM file as bytes.
func KeyboardInteractiveAuth ¶
func KeyboardInteractiveAuth(fn KeyboardInteractiveHandler) Option
func NoPty ¶
func NoPty() Option
NoPty returns a functional option that sets PtyCallback to return false, denying PTY requests.
Example ¶
package main
import (
"context"
"log"
"github.com/engity-com/ssh-server-go"
)
func main() {
log.Fatal(ssh.ListenAndServe(context.Background(), ":2222", nil, ssh.NoPty()))
}
Output:
func PasswordAuth ¶
func PasswordAuth(fn PasswordHandler) Option
PasswordAuth returns a functional option that sets PasswordHandler on the server.
Example ¶
package main
import (
"context"
"log"
"github.com/engity-com/ssh-server-go"
gossh "golang.org/x/crypto/ssh"
)
func main() {
log.Fatal(ssh.ListenAndServe(context.Background(), ":2222", nil,
ssh.PasswordAuth(func(ctx ssh.Context, conn gossh.ConnMetadata, pass string) (bool, error) {
return pass == "secret", nil
}),
))
}
Output:
func PublicKeyAuth ¶
func PublicKeyAuth(fn PublicKeyHandler) Option
PublicKeyAuth returns a functional option that sets PublicKeyHandler on the server.
Example ¶
package main
import (
"context"
"log"
"os"
"github.com/engity-com/ssh-server-go"
gossh "golang.org/x/crypto/ssh"
)
func main() {
log.Fatal(ssh.ListenAndServe(context.Background(), ":2222", nil,
ssh.PublicKeyAuth(func(ctx ssh.Context, conn gossh.ConnMetadata, key ssh.PublicKey) (bool, error) {
data, _ := os.ReadFile("/path/to/allowed/key.pub")
allowed, _, _, _, _ := ssh.ParseAuthorizedKey(data)
return ssh.KeysEqual(key, allowed), nil
}),
))
}
Output:
func WithErrorHandler ¶ added in v0.2.0
func WithErrorHandler(handler ErrorHandler) Option
WithErrorHandler returns a functional option that sets the central handler for operational server and handler errors.
func WithGracefulShutdownHandler ¶ added in v0.2.0
func WithGracefulShutdownHandler(handler GracefulShutdownHandler) Option
WithGracefulShutdownHandler returns a functional option that sets the graceful shutdown handler on the server.
func WithGracefulShutdownTimeout ¶ added in v0.2.0
WithGracefulShutdownTimeout returns a functional option that configures a fixed graceful shutdown timeout on the server.
func WrapConn ¶
func WrapConn(fn ConnCallback) Option
WrapConn returns a functional option that sets ConnCallback on the server.
type PasswordHandler ¶
PasswordHandler is a callback for performing password authentication. Returning false, nil denies the authentication attempt. A non-nil error aborts the SSH handshake.
type Permissions ¶
type Permissions struct {
*gossh.Permissions
}
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.
type ProxyProtocolConfig ¶ added in v0.2.0
type ProxyProtocolConfig struct {
// ConnPolicy decides whether a connection may supply a PROXY header and how
// that header is handled. It must return promptly.
ConnPolicy proxyproto.ConnPolicyFunc
// ValidateHeader performs application-specific validation after parsing. It
// must return promptly.
ValidateHeader proxyproto.Validator
// ReadHeaderTimeout bounds PROXY header processing. Zero uses the
// go-proxyproto default; a negative value disables its header timeout.
ReadHeaderTimeout time.Duration
// ReadBufferSize controls the per-connection header buffer. A nonpositive
// value uses the go-proxyproto default. Values below 107 bytes break maximum
// length version 1 headers.
ReadBufferSize int
}
ProxyProtocolConfig configures PROXY protocol processing for accepted connections. A nil ConnPolicy requires a PROXY header but trusts the source information supplied by every peer. Listeners reachable by untrusted peers should configure a policy such as proxyproto.TrustProxyHeaderFrom or proxyproto.TrustProxyHeaderFromRanges. Connections are wrapped before ConnCallback, while the header is processed lazily on first I/O or address access. A callback can type-assert the connection to *proxyproto.Conn and use Raw to inspect the transport peer instead of the address supplied by the header. It must retain or wrap the supplied connection for PROXY processing to remain effective.
type Pty ¶
type Pty struct {
Term string
Window Window
// TerminalModes contains the initial RFC 4254 terminal modes requested by
// the client. Callers may modify the map; each API boundary returns a copy.
TerminalModes gossh.TerminalModes
}
Pty represents the metadata in an accepted PTY request. This package exposes the requested values but does not allocate or configure an operating-system PTY and does not interpret or apply TerminalModes.
type PtyCallback ¶
PtyCallback is a hook for allowing PTY sessions. The Pty contains the client's requested metadata; this package does not allocate or configure an operating-system PTY. Returning false, nil denies the request. A non-nil error is passed to ErrorHandler and ends the session by default.
type PublicKey ¶
PublicKey is an abstraction of different types of public keys.
func ParseAuthorizedKey ¶
func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error)
ParseAuthorizedKey parses a public key from an authorized_keys file used in OpenSSH according to the sshd(8) manual page.
func ParsePublicKey ¶
ParsePublicKey parses an SSH public key formatted for use in the SSH wire protocol according to RFC 4253, section 6.6.
type PublicKeyHandler ¶
PublicKeyHandler is a callback for performing public key authentication. Returning false, nil denies the authentication attempt. A non-nil error aborts the SSH handshake.
type Request ¶ added in v0.2.0
type Request struct {
Type string
Payload []byte
WantReply bool
// contains filtered or unexported fields
}
Request contains one connection-level SSH request. Payload remains valid for the duration of the RequestHandler call and must not be retained or modified.
type RequestHandler ¶
type RequestHandler func(response RequestResponseWriter, request *Request) error
RequestHandler handles one connection-level SSH request. A returned error is passed to ErrorHandler. A request that wants a reply must be completed through response before the handler returns.
type RequestResponseWriter ¶ added in v0.2.0
RequestResponseWriter completes a request with either acceptance or rejection. Each writer is valid only during its RequestHandler call and may be completed at most once. When Request.WantReply is false, the decision is recorded without writing a protocol reply.
type ReversePortForwardingCallback ¶
type ReversePortForwardingCallback func(ctx Context, conn gossh.ConnMetadata, bindHost string, bindPort uint32) (bool, error)
ReversePortForwardingCallback is a hook for allowing reverse port forwarding. Returning false, nil denies the request; a non-nil error is passed to ErrorHandler.
type ReverseUnixForwardingCallback ¶ added in v0.2.0
type ReverseUnixForwardingCallback func(ctx Context, conn gossh.ConnMetadata, socketPath string) (net.Listener, error)
ReverseUnixForwardingCallback handles a streamlocal-forward@openssh.com request. A successful callback transfers ownership of the returned listener to the server. Close must unblock Accept. Return ErrServerPermissionDenied to reject the request without exposing an operational error to the client. Path validation, socket creation, permissions, and stale-file handling are application policy. Callbacks returning a *net.UnixListener must also choose appropriate unlink-on-close behavior. Implementations must honor context cancellation.
type Server ¶
type Server struct {
Logger log.Logger
Addr string // TCP address to listen on, ":22" if empty
Handler Handler // handler to invoke, ssh.DefaultHandler if nil
HostSigners []Signer // private keys for the host key, must have at least one
RequireHostSigners bool // reject startup without an explicitly configured host signer
RequireClientAuth bool // reject connections without an effective, non-anonymous client authentication method
Version string // server version to be sent before the initial handshake
Ciphers Ciphers // allowed ciphers, DefaultCiphers if empty
KeyExchanges KeyExchanges // allowed key exchanges, DefaultKeyExchanges if empty
MessageAuthentications MessageAuthentications // allowed MACs, DefaultMessageAuthentications if empty
BannerHandler BannerHandler // server banner handler
KeyboardInteractiveHandler KeyboardInteractiveHandler // keyboard-interactive authentication handler
PasswordHandler PasswordHandler // password authentication handler
PublicKeyHandler PublicKeyHandler // public key authentication handler
PtyCallback PtyCallback // callback for allowing PTY sessions, allows all if nil
ConnCallback ConnCallback // optional callback for wrapping net.Conn before handling
LocalPortForwardingCallback LocalPortForwardingCallback // callback for allowing local port forwarding, denies all if nil
ReversePortForwardingCallback ReversePortForwardingCallback // callback for allowing reverse port forwarding, denies all if nil
LocalUnixForwardingCallback LocalUnixForwardingCallback // callback for local Unix forwarding, denies all if nil
ReverseUnixForwardingCallback ReverseUnixForwardingCallback // callback for reverse Unix forwarding, denies all if nil
ServerConfigCallback ServerConfigCallback // callback for detailed SSH options; same-method auth conflicts are rejected
SessionRequestCallback SessionRequestCallback // callback for allowing or denying SSH sessions
AgentForwardingCallback AgentForwardingCallback // callback for allowing agent forwarding, denies all if nil
ConnectionFailedCallback ConnectionFailedCallback // callback to report connection failures
DisconnectCallback DisconnectCallback // callback after an established SSH connection ends
ErrorHandler ErrorHandler // central callback for operational server and handler errors
// GracefulShutdownHandler determines how long a context-triggered shutdown
// waits for connections to drain before closing them. It is called once with
// the original canceled context after the listener has been closed and must
// return promptly. Nil or a nonpositive result disables graceful shutdown.
GracefulShutdownHandler GracefulShutdownHandler
// ProxyProtocol enables PROXY protocol processing when non-nil. Connection
// wrapping occurs before ConnCallback and the SSH handshake. Do not pass
// connections already wrapped by go-proxyproto when this is configured.
ProxyProtocol *ProxyProtocolConfig
// Timeout fields use their Default* value when nil. A configured duration
// less than or equal to zero disables that timeout.
HandshakeTimeout *time.Duration // timeout until successful authentication, default 2 minutes
IdleTimeout *time.Duration // timeout when no activity, disabled by default
MaxTimeout *time.Duration // absolute connection timeout, disabled by default
// SessionRequestTimeout limits how long an accepted session channel may wait
// for shell, exec, or subsystem. The default is 30 seconds.
SessionRequestTimeout *time.Duration
// Limit fields use their Default* value when nil. A configured value less
// than or equal to zero disables that limit, meaning no limit is enforced.
// MaxStartups is disabled when Full is less than or equal to zero.
MaxStartups *MaxStartupsConfig
MaxSessionsPerConnection *int
MaxChannelsPerConnection *int
MaxReverseForwardsPerConnection *int
MaxConnections *int // authenticated connections per Serve or HandleConn call
MaxChannels *int // active channels per Serve or HandleConn call
MaxReverseForwards *int // active reverse-forward listeners per Serve or HandleConn call
// 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.
ChannelHandlers map[string]ChannelHandler
// RequestHandlers allow overriding the server-level request handlers or
// provide extensions to the protocol, such as tcpip forwarding. By default,
// no handlers are enabled.
RequestHandlers map[string]RequestHandler
// SubsystemHandlers are handlers which are similar to the usual SSH command
// handlers, but handle named subsystems.
SubsystemHandlers map[string]SubsystemHandler
// contains filtered or unexported fields
}
Server configures an SSH server. Its zero value is valid and does not require client authentication.
Configure Server and its referenced values before the first Server.Serve or Server.HandleConn call. It must not be copied or modified after first use, but may be reused concurrently. Each call owns independent runtime state and limits.
func (*Server) AddHostKey ¶
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. It must only be called before the server's first Serve or HandleConn call.
func (*Server) Handle ¶
Handle sets the Handler for the server. It must only be called before the server's first Serve or HandleConn call.
func (*Server) HandleConn ¶
HandleConn handles one connection until it finishes or ctx is canceled. It does not invoke ConnectionFailedCallback. Unhandled connection failures are returned directly; ErrorHandler can handle or transform them. On cancellation, the returned error contains the context cause and may contain cleanup errors or ErrGracefulShutdownTimeout. Limits and ErrorHandler concurrency belong to this HandleConn call and are not shared with Serve calls on the same Server.
func (*Server) ListenAndServe ¶
ListenAndServe listens on the TCP network address srv.Addr and then calls Serve with ctx to handle incoming connections. If srv.Addr is blank, ":22" is used. Its return value has the same error semantics as Serve.
func (*Server) Serve ¶
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. Canceling ctx closes the listener and stops this Serve scope; other concurrent Serve calls on srv are unaffected. Serve returns the context cause after draining or forcibly closing the scope's connections. Limits and ErrorHandler concurrency are independent for each Serve call. A forced shutdown after a positive graceful period also returns ErrGracefulShutdownTimeout.
type ServerConfigCallback ¶
ServerConfigCallback customizes a fresh per-connection server config. A returned error aborts the SSH handshake. Public key multi-factor authentication must return PartialSuccessError from VerifiedPublicKeyCallback, after key ownership has been proven. Configuring a PasswordCallback, PublicKeyCallback, or KeyboardInteractiveCallback together with the corresponding high-level Server handler rejects that auth method with ErrServerAuthCallbackConflict rather than silently replacing either policy.
type Session ¶
type Session interface {
gossh.Channel
// User returns the username used when establishing the SSH connection.
User() string
// RemoteAddr returns the net.Addr of the client side of the connection.
RemoteAddr() net.Addr
// LocalAddr returns the net.Addr of the server side of the connection.
LocalAddr() net.Addr
// Environ returns a copy of strings representing the environment set by the
// user for this session, in the form "key=value".
Environ() []string
// Exit sends an exit status and then closes the session.
Exit(code int) error
// 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.
Command() []string
// RawCommand returns the exact command that was provided by the user.
RawCommand() string
// Subsystem returns the subsystem requested by the user.
Subsystem() string
// PublicKey returns the PublicKey used to authenticate. If a public key was not
// used it will return nil.
PublicKey() PublicKey
// 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.
//
// Values are inherited from the context passed to Serve or HandleConn. Its
// cancellation and deadline are intentionally detached during graceful
// shutdown. The connection context is canceled when the connection closes,
// an I/O operation fails, or a hard shutdown begins.
Context() Context
// Permissions returns a copy of the Permissions object that was available for
// setup in the auth handlers via the Context. Its map containers are copied;
// arbitrary values stored in ExtraData are not recursively cloned.
Permissions() Permissions
// Pty returns the client's PTY request, a channel of effective window sizes,
// and whether a PTY was accepted for this session. The channel initially
// contains the size from the PTY request. If the receiver falls behind,
// intermediate changes are coalesced and the latest size is retained. The
// returned Pty and its TerminalModes map are snapshots and can be modified by
// the caller.
Pty() (Pty, <-chan Window, bool)
// Signals registers a channel to receive signals sent from the client. The
// channel must handle signal sends promptly. Blocked sends are canceled when
// the channel is unregistered, the session exits, or its context is canceled.
// 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. The receiver
// must unregister the channel before closing it.
Signals(c chan<- Signal)
// Break registers 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.
// The receiver must unregister the channel before closing it.
Break(c chan<- bool)
}
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.
type SessionExitError ¶ added in v0.2.0
SessionExitError requests a public message and exit status from a Handler or SubsystemHandler. It bypasses ErrorHandler unless sending the response fails. Wrapping preserves this behavior; joining another error routes the result through ErrorHandler.
func NewSessionExitError ¶ added in v0.2.0
func NewSessionExitError(code int, message string) *SessionExitError
NewSessionExitError creates a controlled session exit.
func (*SessionExitError) Error ¶ added in v0.2.0
func (e *SessionExitError) Error() string
type SessionRequestCallback ¶
SessionRequestCallback is a callback for allowing or denying SSH sessions. Returning false, nil denies the request. A non-nil error is passed to ErrorHandler and ends the session by default.
type Signal ¶
type Signal string
const ( SIGABRT Signal = "ABRT" SIGALRM Signal = "ALRM" SIGFPE Signal = "FPE" SIGHUP Signal = "HUP" SIGILL Signal = "ILL" SIGINT Signal = "INT" SIGKILL Signal = "KILL" SIGPIPE Signal = "PIPE" SIGQUIT Signal = "QUIT" SIGSEGV Signal = "SEGV" SIGTERM Signal = "TERM" SIGUSR1 Signal = "USR1" SIGUSR2 Signal = "USR2" )
POSIX signals as listed in RFC 4254 Section 6.10.
type SubsystemHandler ¶
SubsystemHandler handles a named SSH subsystem. Returned errors have the same ErrorHandler and exit-status semantics as Handler errors.
type Window ¶
Window represents the informational dimensions of a PTY window. Width and Height are measured in characters; WidthPixels and HeightPixels describe the drawable area. A zero value in an initial PTY request means unspecified. A zero value in a later window change leaves that dimension unchanged.