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:
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!
Index ¶
- Variables
- func AgentRequested(sess Session) bool
- func ForwardAgentConnections(l net.Listener, s Session)
- func Handle(handler Handler)
- func KeysEqual(ak, bk PublicKey) bool
- func ListenAndServe(addr string, handler Handler, options ...Option) error
- func NewAgentListener() (net.Listener, error)
- func Serve(l net.Listener, handler Handler, options ...Option) error
- func SetAgentRequested(ctx Context)
- type ConnCallback
- type Context
- type Handler
- type LocalPortForwardingCallback
- type Option
- type PasswordHandler
- type Permissions
- type Pty
- type PtyCallback
- type PublicKey
- type PublicKeyHandler
- type Server
- func (srv *Server) AddHostKey(key Signer)
- func (srv *Server) Close() error
- func (srv *Server) Handle(fn Handler)
- func (srv *Server) ListenAndServe() error
- func (srv *Server) Serve(l net.Listener) error
- func (srv *Server) SetOption(option Option) error
- func (srv *Server) Shutdown(ctx context.Context) error
- type Session
- type Signal
- type Signer
- type Window
Examples ¶
Constants ¶
This section is empty.
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.Conn. 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 ErrServerClosed = errors.New("ssh: Server closed")
ErrServerClosed is returned by the Server's Serve, ListenAndServe, and ListenAndServeTLS methods after a call to Shutdown or Close.
Functions ¶
func AgentRequested ¶ added in v0.1.1
AgentRequested returns true if the client requested agent forwarding.
func ForwardAgentConnections ¶ added in v0.1.1
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 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.
Example ¶
package main import ( "io" "github.com/gliderlabs/ssh" ) func main() { ssh.ListenAndServe(":2222", func(s ssh.Session) { io.WriteString(s, "Hello world\n") }) }
Output:
func NewAgentListener ¶ added in v0.1.1
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.
func SetAgentRequested ¶ added in v0.1.1
func SetAgentRequested(ctx Context)
SetAgentRequested sets up the session context so that AgentRequested returns true.
Types ¶
type ConnCallback ¶ added in v0.1.1
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.
type Context ¶ added in v0.1.1
type Context interface { context.Context // User returns the username used when establishing the SSH connection. User() string // SessionID returns the session hash. SessionID() string // ClientVersion returns the version reported by the client. ClientVersion() string // ServerVersion returns the version reported by the server. ServerVersion() string // RemoteAddr returns the remote address for this connection. RemoteAddr() net.Addr // LocalAddr returns the local address for this connection. LocalAddr() net.Addr // Permissions returns the Permissions object used for this connection. Permissions() *Permissions // SetValue allows you to easily write new values into the underlying context. SetValue(key, value interface{}) }
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.
type Handler ¶
type Handler func(Session)
Handler is a callback for handling established SSH sessions.
var DefaultHandler Handler
DefaultHandler is the default Handler used by Serve.
type LocalPortForwardingCallback ¶ added in v0.1.1
type LocalPortForwardingCallback func(ctx Context, destinationHost string, destinationPort uint32) bool
LocalPortForwardingCallback is a hook for allowing port forwarding
type Option ¶
Option is a functional option handler for Server.
func HostKeyFile ¶
HostKeyFile returns a functional option that adds HostSigners to the server from a PEM file at filepath.
Example ¶
package main import ( "github.com/gliderlabs/ssh" ) func main() { ssh.ListenAndServe(":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 NoPty ¶
func NoPty() Option
NoPty returns a functional option that sets PtyCallback to return false, denying PTY requests.
Example ¶
package main import ( "github.com/gliderlabs/ssh" ) func main() { ssh.ListenAndServe(":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 ( "github.com/gliderlabs/ssh" ) func main() { ssh.ListenAndServe(":2222", nil, ssh.PasswordAuth(func(ctx ssh.Context, pass string) bool { return pass == "secret" }), ) }
Output:
func PublicKeyAuth ¶
func PublicKeyAuth(fn PublicKeyHandler) Option
PublicKeyAuth returns a functional option that sets PublicKeyHandler on the server.
Example ¶
package main import ( "io/ioutil" "github.com/gliderlabs/ssh" ) func main() { ssh.ListenAndServe(":2222", nil, ssh.PublicKeyAuth(func(ctx ssh.Context, key ssh.PublicKey) bool { data, _ := ioutil.ReadFile("/path/to/allowed/key.pub") allowed, _, _, _, _ := ssh.ParseAuthorizedKey(data) return ssh.KeysEqual(key, allowed) }), ) }
Output:
func WrapConn ¶ added in v0.1.1
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.
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 PtyCallback ¶
PtyCallback is a hook for allowing PTY sessions.
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.
type Server ¶
type Server struct { 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 Version string // server version to be sent before the initial handshake 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 IdleTimeout time.Duration // connection timeout when no activity, none if empty MaxTimeout time.Duration // absolute connection timeout, none if empty // contains filtered or unexported fields }
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.
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.
func (*Server) Close ¶ added in v0.1.1
Close immediately closes all active listeners and all active connections.
Close returns any error returned from closing the Server's underlying Listener(s).
func (*Server) ListenAndServe ¶
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.
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.
Serve always returns a non-nil error.
func (*Server) Shutdown ¶ added in v0.1.1
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.
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 // 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. // // The context is canceled when the client's connection closes or I/O // operation fails. Context() context.Context // Permissions returns a copy of the Permissions object that was available for // setup in the auth handlers via the Context. Permissions() Permissions // Pty returns PTY information, a channel of window size changes, and a boolean // of whether or not a PTY was accepted for this session. Pty() (Pty, <-chan Window, bool) // 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. Signals(c chan<- Signal) }
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 cypto/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
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.