sshserver

package module
v0.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 8, 2020 License: MIT Imports: 17 Imported by: 15

README

ContainerSSH - Launch Containers on Demand

ContainerSSH SSH Server Library

Go Report Card LGTM Alerts

This library provides an overlay for the built-in go SSH server library that makes it easier to handle.

Note: This is a developer documentation.
The user documentation for ContainerSSH is located at containerssh.github.io.

Using this library

This library provides a friendlier way to handle SSH requests than with the built-in SSH library. As a primary entry point you will need to create and run the SSH server:

// Create the server. See the description below for parameters.
server, err := sshserver.New(
    cfg,
    handler,
    logger,
)
if err != nil {
    // Handle configuration errors
    log.Fatalf("%v", err)
}

defer func() {
    // The Run method will run the server and return when the server is shut down.
    // We are running this in a goroutine so the shutdown below can proceed after a minute.
    if err := server.Run(); err != nil {
        // Handle errors while running the server
    }
}()

time.Sleep(60 * time.Second)

// Shut down the server. Pass a context to indicate how long the server should wait
// for existing connections to finish. This function will return when the server
// has stopped. 
server.Shutdown(
    context.WithTimeout(
        context.Background(),
        30 * time.Second,
    ),
)

The cfg variable will be a Config structure as described in config.go.

The handler variable must be an implementation of the Handler interface described in handler.go.

The logger variable needs to be an instance of the Logger interface from github.com/containerssh/log.

Implementing a handler

The handler interface consists of multiple parts:

  • The Handler is the main handler for the application providing several hooks for events. On new connections the OnNetworkConnection method is called, which must return a NetworkConnectionHandler
  • The NetworkConnectionHandler is a handler for network connections before the SSH handshake is complete. It is called to perform authentication and return an SSHConnectionHandler when the authentication is successful.
  • The SSHConnectionHandler is responsible for handling an individual SSH connection. Most importantly, it is responsible for providing a SessionChannelHandler when a new session channel is requested by the client.
  • The SessionChannelHandler is responsible for an individual session channel (single program execution). It provides several hooks for setting up and running the program. Once the program execution is complete the channel is closed. You must, however, keep handling requests (e.g. window size change) during program execution.

A sample implementation can be found in the test code at the bottom of the file.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AuthResponse

type AuthResponse uint8

AuthResponse indicates the various response states for the authentication process.

const (
	// AuthResponseSuccess indicates that the authentication was successful.
	AuthResponseSuccess AuthResponse = 1

	// AuthResponseFailure indicates that the authentication failed for invalid credentials.
	AuthResponseFailure AuthResponse = 2

	// AuthResponseUnavailable indicates that the authentication could not be performed because a backend system failed
	//                         to respond.
	AuthResponseUnavailable AuthResponse = 3
)

type ChannelRejection

type ChannelRejection interface {
	error

	// Message contains a message intended for the user.
	Message() string
	// Reason contains the SSH-specific reason for the rejection.
	Reason() ssh.RejectionReason
}

ChannelRejection is an error type that also contains a Message and a Reason

type Cipher

type Cipher string

Cipher is the SSH cipher

const (
	CipherChaCha20Poly1305 Cipher = "chacha20-poly1305@openssh.com"
	CipherAES256GCM        Cipher = "aes256-gcm@openssh.com"
	CipherAES128GCM        Cipher = "aes128-gcm@openssh.com"
	CipherAES256CTE        Cipher = "aes256-ctr"
	CipherAES192CTR        Cipher = "aes192-ctr"
	CipherAES128CTR        Cipher = "aes128-ctr"
	CipherAES128CBC        Cipher = "aes128-cbc"
	CipherArcFour256       Cipher = "arcfour256"
	CipherArcFour128       Cipher = "arcfour128"
	CipherArcFour          Cipher = "arcfour"
	CipherTripleDESCBCID   Cipher = "tripledescbcID"
)

Cipher is the SSH cipher

func (Cipher) String

func (c Cipher) String() string

String creates a string representation.

type Config

type Config struct {
	// Listen is the listen address for the SSH server
	Listen string `json:"listen" yaml:"listen" default:"0.0.0.0:2222"`
	// ServerVersion is the version sent to the client.
	//               Must be in the format of "SSH-protoversion-softwareversion SPACE comments".
	//               See https://tools.ietf.org/html/rfc4253#page-4 section 4.2. Protocol Version Exchange
	//               The trailing CR and LF characters should NOT be added to this string.
	ServerVersion string `json:"serverVersion" yaml:"serverVersion" default:"SSH-2.0-ContainerSSH"`
	// Ciphers are the ciphers offered to the client.
	Ciphers []Cipher `` /* 205-byte string literal not displayed */
	// KexAlgorithms are the key exchange algorithms offered to the client.
	KexAlgorithms []Kex `` /* 176-byte string literal not displayed */
	// MACs are the MAC algorithms offered to the client.
	MACs []MAC `` /* 150-byte string literal not displayed */
	// Banner is the banner sent to the client on connecting.
	Banner string `json:"banner" yaml:"banner" comment:"Host banner to show after the username" default:""`
	// HostKeys are the host keys either in PEM format, or filenames to load.
	HostKeys []ssh.Signer `json:"hostkeys" yaml:"hostkeys" comment:"Host keys in PEM format or files to load PEM host keys from."`
}

Config is the base configuration structure of the SSH server.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns the config structure with the default settings. Only the HostKeys option will need to be

filled.

func (*Config) GenerateHostKey

func (cfg *Config) GenerateHostKey() error

GenerateHostKey generates a random host key and adds it to Config

func (Config) UnmarshalJSON

func (cfg Config) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes a JSON data structure into the configuration.

func (Config) Validate

func (cfg Config) Validate() error

Validate validates the configuration and returns an error if invalid.

type Handler

type Handler interface {
	// OnReady is called when the server is ready to receive connections. It has an opportunity to return an error to
	//         abort the startup.
	OnReady() error

	// OnShutdown is called when a shutdown of the SSH server is desired. The shutdownContext is passed as a deadline
	//            for the shutdown, after which the server should abort all running connections and return as fast as
	//            possible.
	OnShutdown(shutdownContext context.Context)

	// Connection is called when a new network connection is opened. It must either return a NetworkConnectionHandler object or
	//            an error. In case of an error the network connection is closed.
	OnNetworkConnection(ip net.Addr) (NetworkConnectionHandler, error)
}

Handler is the basic handler for SSH connections. It contains several methods to handle startup and operations of the

server

type HostKeyAlgo

type HostKeyAlgo string

HostKeyAlgo are supported host key algorithms.

const (
	HostKeyAlgoSSHRSACertv01            HostKeyAlgo = "ssh-rsa-cert-v01@openssh.com"
	HostKeyAlgoSSHDSSCertv01            HostKeyAlgo = "ssh-dss-cert-v01@openssh.com"
	HostKeyAlgoECDSASHA2NISTp256Certv01 HostKeyAlgo = "ecdsa-sha2-nistp256-cert-v01@openssh.com"
	HostKeyAlgoECDSASHA2NISTp384Certv01 HostKeyAlgo = "ecdsa-sha2-nistp384-cert-v01@openssh.com"
	HostKeyAlgoECDSASHA2NISTp521Certv01 HostKeyAlgo = "ecdsa-sha2-nistp521-cert-v01@openssh.com"
	HostKeyAlgoSSHED25519Certv01        HostKeyAlgo = "ssh-ed25519-cert-v01@openssh.com"
	HostKeyAlgoSSHRSA                   HostKeyAlgo = "ssh-rsa"
	HostKeyAlgoSSHDSS                   HostKeyAlgo = "ssh-dss"
	HostKeyAlgoSSHED25519               HostKeyAlgo = "ssh-ed25519"
)

HostKeyAlgo are supported host key algorithms.

func (HostKeyAlgo) String

func (h HostKeyAlgo) String() string

String creates a string representation.

type Kex

type Kex string

Kex are the SSH key exchange algorithms

const (
	KexCurve25519SHA256 Kex = "curve25519-sha256@libssh.org"
	KexECDHSHA2NISTp521 Kex = "ecdh-sha2-nistp521"
	KexECDHSHA2Nistp384 Kex = "ecdh-sha2-nistp384"
	KexECDHSHA2Nistp256 Kex = "ecdh-sha2-nistp256"
	KexDHGroup14SHA1    Kex = "diffie-hellman-group14-sha1"
	KexDHGroup1SHA1     Kex = "diffie-hellman-group1-sha1"
)

Kex are the SSH key exchange algorithms

func (Kex) String

func (k Kex) String() string

String creates a string representation.

type MAC

type MAC string

MAC are the SSH mac algorithms.

const (
	MACHMACSHA2256ETM MAC = "hmac-sha2-256-etm@openssh.com"
	MACHMACSHA2256    MAC = "hmac-sha2-256"
	MACHMACSHA1       MAC = "hmac-sha1"
	MACHMACSHA196     MAC = "hmac-sha1-96"
)

MAC are the SSH mac algorithms.

func (MAC) String

func (m MAC) String() string

String creates a string representation.

type NetworkConnectionHandler

type NetworkConnectionHandler interface {
	// OnAuthPassword is called when a user attempts a password authentication. The implementation must always supply
	//                AuthResponse and may supply error as a reason description.
	OnAuthPassword(username string, password []byte) (response AuthResponse, reason error)

	// OnAuthPassword is called when a user attempts a pubkey authentication. The implementation must always supply
	//                AuthResponse and may supply error as a reason description.
	OnAuthPubKey(username string, pubKey []byte) (response AuthResponse, reason error)

	// OnHandshakeFailed is called when the SSH handshake failed. This method is also called after an authentication
	//                   failure. After this method is the connection will be closed and the OnDisconnect method will be
	//                   called.
	OnHandshakeFailed(reason error)

	// OnHandshakeSuccess is called when the SSH handshake was successful. It returns connection to process
	//                    requests, or failureReason to indicate that a backend error has happened. In this case, the
	//                    connection will be closed and OnDisconnect will be called.
	OnHandshakeSuccess() (connection SSHConnectionHandler, failureReason error)

	// OnDisconnect is called when the network connection is closed.
	OnDisconnect()
}

NetworkConnectionHandler is an object that is used to represent the underlying network connection and the SSH handshake.

type SSHConnectionHandler

type SSHConnectionHandler interface {
	// OnUnsupportedGlobalRequest captures all global SSH requests and gives the implementation an opportunity to log
	//                            the request.
	OnUnsupportedGlobalRequest(requestType string, payload []byte)

	// OnUnsupportedChannel is called when a new channel is requested of an unsupported type. This gives the implementer
	//                      the ability to log unsupported channel requests.
	OnUnsupportedChannel(channelType string, extraData []byte)

	// OnSessionChannel is called when a channel of the session type is requested. The implementer must either return
	//                  the channel result if the channel was successful, or failureReason to state why the channel
	//                  should be rejected.
	OnSessionChannel(extraData []byte) (channel SessionChannelHandler, failureReason ChannelRejection)
}

SSHConnectionHandler represents an established SSH connection that is ready to receive requests.

type Server

type Server interface {
	// Run runs the server synchronously. This function returns when the server has stopped.
	Run() error

	// Shutdown signals the server to not accept any more connections and shut down. When shutdownContext
	// expires the server aborts active connections and shuts down the server.
	// The method waits for the server to shut down.
	Shutdown(shutdownContext context.Context)
}

Server is the main server for running a server

func New

func New(cfg Config, handler Handler, logger log.Logger) (Server, error)

New creates a new SSH server ready to be run. It may return an error if the configuration is invalid.

type SessionChannelHandler

type SessionChannelHandler interface {
	// OnUnsupportedChannelRequest captures channel requests of unsupported types.
	OnUnsupportedChannelRequest(
		requestType string,
		payload []byte,
	)

	// OnFailedDecodeChannelRequest is called when a supported channel request was received, but the payload could not
	//                              be decoded.
	OnFailedDecodeChannelRequest(
		requestType string,
		payload []byte,
		reason error,
	)

	// OnEnvRequest is called when the client requests an environment variable to be set. The implementation can return
	//              an error to reject the request.
	OnEnvRequest(
		name string,
		value string,
	) error

	// OnExecRequest is called when the client request a program to be executed. The implementation can return an error
	//               to reject the request.
	//
	// program is the name of the program to be executed.
	// stdin is a reader for the shell or program to read the stdin.
	// stdout is a writer for the shell or program standard output.
	// stderr is a writer for the shell or program standard error.
	// onExit is a callback to send the exit status back to the client.
	OnExecRequest(
		program string,
		stdin io.Reader,
		stdout io.Writer,
		stderr io.Writer,
		onExit func(exitStatus uint32),
	) error

	// OnPtyRequest is called when the client requests an interactive terminal to be allocated. The implementation can
	//              return an error to reject the request.
	//
	// term is the terminal name. This is usually set in the TERM environment variable.
	// columns is the number of columns in the terminal.
	// rows is the number of rows in the terminal.
	// width is the width of the terminal in pixels.
	// height is the height of a terminal in pixels.
	// modelist are the encoded terminal modes the client desires. See RFC4254 section 8 and RFC8160 for details.
	OnPtyRequest(
		term string,
		columns uint32,
		rows uint32,
		width uint32,
		height uint32,
		modeList []byte,
	) error

	// OnShell is called when the client requests a shell to be started. The implementation can return an error to
	//         reject the request. The implementation should send the IO handling into background. It should also
	//         respect the shutdown context on the Handler.
	//
	// stdin is a reader for the shell or program to read the stdin.
	// stdout is a writer for the shell or program standard output.
	// stderr is a writer for the shell or program standard error.
	// onExit is a callback to send the exit status back to the client.
	OnShell(
		stdin io.Reader,
		stdout io.Writer,
		stderr io.Writer,
		onExit func(exitStatus uint32),
	) error

	// OnSignal is called when the client requests a signal to be sent to the running process. The implementation can
	//          return an error to reject the request.
	OnSignal(signal string) error

	// OnSubsystem is called when the client calls a well-known subsystem (e.g. sftp). The implementation can return an
	//             error to reject the request. The implementation should send the IO handling into background. It
	//             should also respect the shutdown context on the Handler.
	//
	// stdin is a reader for the shell or program to read the stdin.
	// stdout is a writer for the shell or program standard output.
	// stderr is a writer for the shell or program standard error.
	// onExit is a callback to send the exit status back to the client.
	OnSubsystem(
		subsystem string,
		stdin io.Reader,
		stdout io.Writer,
		stderr io.Writer,
		onExit func(exitStatus uint32),
	) error

	// OnWindow is called when the client requests requests the window size to be changed. The implementation can
	//              return an error to reject the request.
	//
	// columns is the number of columns in the terminal.
	// rows is the number of rows in the terminal.
	// width is the width of the terminal in pixels.
	// height is the height of a terminal in pixels.
	OnWindow(
		columns uint32,
		rows uint32,
		width uint32,
		height uint32,
	) error
}

SessionChannelHandler is a channel of the "session" type used for interactive and non-interactive sessions

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL