README

easyssh

GoDoc

easyssh provides a simple wrapper around the standard SSH library. Designed to be like net/http but for ssh.

Install

go get dev.justinjudd.org/justin/easyssh

Usage

Server Example
package main

import (
	"fmt"
	"io/ioutil"
	"log"

	"dev.justinjudd.org/justin/easyssh"

	"golang.org/x/crypto/ssh"
)

func main() {

	privateBytes, err := ioutil.ReadFile("id_rsa")
	if err != nil {
		log.Fatal("Failed to load private key (./id_rsa)")
	}

	private, err := ssh.ParsePrivateKey(privateBytes)
	if err != nil {
		log.Fatal("Failed to parse private key")
	}

	config := &ssh.ServerConfig{
		PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
			if c.User() == "test" && string(pass) == "test" {
				log.Printf("User logged in: %s", c.User())
				return nil, nil
			}
			return nil, fmt.Errorf("password rejected for %s", c.User())
		},
	}
	config.AddHostKey(private)


	easyssh.HandleChannel(easyssh.SessionRequest, easyssh.SessionHandler())
	easyssh.HandleChannel(easyssh.DirectForwardRequest, easyssh.DirectPortForwardHandler())
	easyssh.HandleRequestFunc(easyssh.RemoteForwardRequest, easyssh.TCPIPForwardRequest)

	easyssh.ListenAndServe(":2022", config, nil)
}

Client Example
package main

import (
	"log"

	"dev.justinjudd.org/justin/easyssh"
	"golang.org/x/crypto/ssh"
)

func main() {
	config := &ssh.ClientConfig{
		User: "test",
		Auth: []ssh.AuthMethod{
			ssh.Password("test"),
		},
	}


  conn, err := easyssh.Dial("tcp", "localhost:2022", config)
  if err != nil {
  	log.Fatalf("unable to connect: %s", err)
  }
  defer conn.Close()

  err = conn.LocalForward("localhost:8000", "localhost:6060")
  if err != nil {
  	log.Fatalf("unable to forward local port: %s", err)
  }

}

Documentation

Overview

Package easyssh provides a simple wrapper around the standard SSH library. Designed to be like net/http but for ssh. Both server and client implementations are provided.

Creating a client is similar to creating a normal ssh client

client, err := easyssh.Dial("tcp", "localhost:2022", config)
if err != nil {
  // Handle error
}
defer client.Close()

Once a client is created, you can do a number of things with it: Local Port Forwarding

err = client.LocalForward("localhost:8000", "localhost:6060")
if err != nil {
  // Handle error
}

Remote Port Forwarding

err = client.RemoteForward("localhost:8000", "localhost:6060")
if err != nil {
  // Handle error
}

Create a session - used for executing remote commands or getting a remote shell

session, err := client.NewSession()
if err != nil {
  // Handle error
}
out, err := session.Output("whoami")
if err != nil {
  // Handle error
}

Getting started with an SSH server is easy with easyssh

easyssh.HandleChannel(easyssh.SessionRequest, easyssh.SessionHandler())
easyssh.HandleChannel(easyssh.DirectForwardRequest, easyssh.DirectPortForwardHandler())
easyssh.HandleRequestFunc(easyssh.RemoteForwardRequest, easyssh.TCPIPForwardRequest)

easyssh.ListenAndServe(":2022", sshServerConfig, nil)

There are a lot of layers of ssh communication, and easyssh makes it easy to control at the level desired.

Index

Examples

Constants

View Source
const (
	SessionRequest               = "session"       // RFC 4254 6.1
	PTYRequest                   = "pty-req"       // RFC 4254 6.2
	X11Request                   = "x11-req"       // RFC 4254 6.3.1
	X11ChannelRequest            = "x11"           // RFC 4254 6.3.2
	EnvironmentRequest           = "env"           // RFC 4254 6.4
	ShellRequest                 = "shell"         // RFC 4254 6.5
	ExecRequest                  = "exec"          // RFC 4254 6.5
	SubsystemRequest             = "subsystem"     // RFC 4254 6.5
	WindowDimensionChangeRequest = "window-change" // RFC 4254 6.7
	FlowControlRequest           = "xon-off"       // RFC 4254 6.8
	SignalRequest                = "signal"        // RFC 4254 6.9
	ExitStatusRequest            = "exit-status"   // RFC 4254 6.10
	ExitSignalRequest            = "exit-signal"   // RFC 4254 6.10
)

Request types used in sessions - RFC 4254 6.X

View Source
const (
	DirectForwardRequest       = "direct-tcpip"         // RFC 4254 7.2
	RemoteForwardRequest       = "tcpip-forward"        // RFC 4254 7.1
	ForwardedTCPReturnRequest  = "forwarded-tcpip"      // RFC 4254 7.2
	CancelRemoteForwardRequest = "cancel-tcpip-forward" // RFC 4254 7.1
)

Applicaple SSH Request types for Port Forwarding - RFC 4254 7.X

Variables

View Source
var DefaultGlobalMultipleRequestsHandler = NewGlobalMultipleRequestsMux()

DefaultGlobalMultipleRequestsHandler is a GlobalMultipleRequestsHandler that by default discards all incoming global requests

View Source
var DefaultMultipleChannelsHandler = NewChannelsMux()

DefaultMultipleChannelsHandler is the ChannelMux and is used to handle all incoming channel requests

View Source
var DefaultSSHConnHandler = &SSHConnHandler{}

DefaultSSHConnHandler is an SSH Server Handler

Functions

func CopyReadWriters

func CopyReadWriters(a, b io.ReadWriter, close func())

CopyReadWriters copies biderectionally - output from a to b, and output of b into a. Calls the close function when unable to copy in either direction

func CreateKeyPair

func CreateKeyPair(publicKey, privateKey io.Writer) (err error)

CreateKeyPair creates a new SSH Key Pair writing the formatted keys to the corresponding io.Writers

func CreateKeyPairFiles

func CreateKeyPairFiles(publicKeyPath, privateKeyPath string) error

CreateKeyPairFiles is the equivalent of running 'ssh-keygen -t rsa"'

func DirectPortForwardChannel

func DirectPortForwardChannel(newChannel ssh.NewChannel, channel ssh.Channel, reqs <-chan *ssh.Request, sshConn ssh.Conn)

DirectPortForwardChannel acts as an SSH Direct Port Forwarder - ssh -L

Should be to channel type - "direct-tcpip" - RFC 4254 7.2

Example
package main

import (
	"fmt"
	"io/ioutil"

	"dev.justinjudd.org/justin/easyssh"
	"golang.org/x/crypto/ssh"
)

func main() {
	s := easyssh.Server{Addr: ":2022"}

	privateBytes, err := ioutil.ReadFile("id_rsa")
	if err != nil {
		// Failed to load private key (./id_rsa)
	}

	private, err := ssh.ParsePrivateKey(privateBytes)
	if err != nil {
		// Failed to parse private key
	}

	config := &ssh.ServerConfig{
		PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
			if c.User() == "test" && string(pass) == "test" {
				return nil, nil
			}
			return nil, fmt.Errorf("password rejected for %s", c.User())
		},
	}
	config.AddHostKey(private)

	s.Config = config

	handler := easyssh.NewStandardSSHServerHandler()
	channelHandler := easyssh.NewChannelsMux()

	channelHandler.HandleChannel(easyssh.DirectForwardRequest, easyssh.DirectPortForwardHandler())
	handler.MultipleChannelsHandler = channelHandler

	s.Handler = handler

	s.ListenAndServe()
}
Output:

func DiscardChannelMultipleRequests

func DiscardChannelMultipleRequests(reqs <-chan *ssh.Request, sshConn ssh.Conn, channelType string, channel ssh.Channel)

DiscardChannelMultipleRequests is a wrapper around ssh.DiscardRequests. Ignores ssh ServerConn

func DiscardGlobalMultipleRequests

func DiscardGlobalMultipleRequests(reqs <-chan *ssh.Request, sshConn ssh.Conn)

DiscardGlobalMultipleRequests is a wrapper around ssh.DiscardRequests. Ignores ssh ServerConn

func DiscardRequest

func DiscardRequest(req *ssh.Request)

DiscardRequest appropriately discards SSH Requests, returning responses to those that expect it

func EnableLogging

func EnableLogging(output io.Writer)

EnableLogging enables logging for the easyssh library

func HandleChannel

func HandleChannel(channelType string, handler ChannelHandler)

HandleChannel registers the given handler under the channelType with the DefaultMultipleChannelsHandler

func HandleChannelFunc

func HandleChannelFunc(channelType string, handler func(newChannel ssh.NewChannel, channel ssh.Channel, reqs <-chan *ssh.Request, sshConn ssh.Conn))

HandleChannelFunc registers the given handler function under the channelType with the DefaultMultipleChannelsHandler

func HandleRequest

func HandleRequest(requestType string, handler GlobalRequestHandler)

HandleRequest registers the given handler with the DefaultGlobalMultipleRequestsHandler

func HandleRequestFunc

func HandleRequestFunc(requestType string, handler func(*ssh.Request, ssh.Conn))

HandleRequestFunc registers the given handler function with the DefaultGlobalMultipleRequestsHandler

func ListenAndServe

func ListenAndServe(addr string, conf *ssh.ServerConfig, handler ConnHandler) error

ListenAndServe listens on the given tcp address addr and then calls Serve with handler. If handler is nil, the DefaultServerHandler is used.

Example
package main

import (
	"dev.justinjudd.org/justin/easyssh"
	"golang.org/x/crypto/ssh"
)

func main() {
	config := &ssh.ServerConfig{}
	easyssh.HandleChannel(easyssh.SessionRequest, easyssh.SessionHandler())
	easyssh.HandleChannel(easyssh.DirectForwardRequest, easyssh.DirectPortForwardHandler())
	easyssh.HandleRequestFunc(easyssh.RemoteForwardRequest, easyssh.TCPIPForwardRequest)

	easyssh.ListenAndServe(":2022", config, nil)
}
Output:

func LoadPrivateKey

func LoadPrivateKey(filePath string) (ssh.Signer, error)

LoadPrivateKey loads a file at the provided path and attempts to load it into an ssh.Signer that can be used for SSH servers

func Serve

func Serve(l net.Listener, conf *ssh.ServerConfig, handler ConnHandler) error

Serve accepts incoming SSH connections on the listener l. If handler is nil, the DefaultServerHandler is used.

func SessionChannel

func SessionChannel(newChannel ssh.NewChannel, channel ssh.Channel, reqs <-chan *ssh.Request, sshConn ssh.Conn)

SessionChannel acts as an SSH Session ChannelHandler

func TCPIPForwardRequest

func TCPIPForwardRequest(req *ssh.Request, sshConn ssh.Conn)

TCPIPForwardRequest fulfills RFC 4254 7.1 "tcpip-forward" request

TODO: Need to add state to handle "cancel-tcpip-forward"

Types

type ChannelHandler

type ChannelHandler interface {
	HandleChannel(newChannel ssh.NewChannel, channel ssh.Channel, reqs <-chan *ssh.Request, sshConn ssh.Conn)
}

ChannelHandler handles channel requests for a given channel type

func DirectPortForwardHandler

func DirectPortForwardHandler() ChannelHandler

DirectPortForwardHandler returns a ChannelHandler that implements standard SSH direct portforwarding

func SessionHandler

func SessionHandler() ChannelHandler

SessionHandler returns a ChannelHandler that implements standard SSH Sessions for PTY, shell, and exec capabilities

type ChannelHandlerFunc

type ChannelHandlerFunc func(newChannel ssh.NewChannel, channel ssh.Channel, reqs <-chan *ssh.Request, sshConn ssh.Conn)

ChannelHandlerFunc is an adapter that allows regular functions to act as SSH Channel Handlers

func (ChannelHandlerFunc) HandleChannel

func (f ChannelHandlerFunc) HandleChannel(newChannel ssh.NewChannel, channel ssh.Channel, reqs <-chan *ssh.Request, sshConn ssh.Conn)

HandleChannel calls f(channelType, channel, reqs, sshConn)

type ChannelMultipleRequestsHandler

type ChannelMultipleRequestsHandler interface {
	HandleMultipleRequests(reqs <-chan *ssh.Request, sshConn ssh.Conn, channelType string, channel ssh.Channel)
}

ChannelMultipleRequestsHandler handles tied to a channel out-of-band SSH Requests

type ChannelMultipleRequestsHandlerFunc

type ChannelMultipleRequestsHandlerFunc func(reqs <-chan *ssh.Request, sshConn ssh.Conn, channelType string, channel ssh.Channel)

ChannelMultipleRequestsHandlerFunc is an adaper to allow regular functions to act as a Channel Requests Handler

func (ChannelMultipleRequestsHandlerFunc) HandleMultipleRequests

func (f ChannelMultipleRequestsHandlerFunc) HandleMultipleRequests(reqs <-chan *ssh.Request, sshConn ssh.Conn, channelType string, channel ssh.Channel)

HandleMultipleRequests calls f(reqs, sshConn, channelType, channel)

type ChannelRequestHandler

type ChannelRequestHandler interface {
	HandleRequest(req *ssh.Request, sshConn ssh.Conn, channelType string, channel ssh.Channel)
}

ChannelRequestHandler handles tied to a channel out-of-band SSH Requests

type ChannelRequestHandlerFunc

type ChannelRequestHandlerFunc func(req *ssh.Request, sshConn ssh.Conn, channelType string, channel ssh.Channel)

ChannelRequestHandlerFunc is an adaper to allow regular functions to act as a Global Request Handler

func (ChannelRequestHandlerFunc) HandleRequest

func (f ChannelRequestHandlerFunc) HandleRequest(req *ssh.Request, sshConn ssh.Conn, channelType string, channel ssh.Channel)

HandleRequest calls f(reqs, sshConn, channelType, channel)

type ChannelsMux

type ChannelsMux struct {
	// contains filtered or unexported fields
}

ChannelsMux is an SSH Channel multiplexer. It matches Channel types and calls the handler for the corresponding type - Can be used as ChannelsHandler

func NewChannelsMux

func NewChannelsMux() *ChannelsMux

NewChannelsMux creates and returns a MultipleChannelsHandler that performs multiplexing of request types with dispatching to ChannelHandlers

func (*ChannelsMux) HandleChannel

func (s *ChannelsMux) HandleChannel(channelType string, handler ChannelHandler)

HandleChannel registers the ChannelHandler for the given Channel Type. If a ChannelHandler was already registered for the type, HandleChannel panics

Example
package main

import (
	"dev.justinjudd.org/justin/easyssh"

	"golang.org/x/crypto/ssh"
)

type testHandler struct{}

func (testHandler) HandleChannel(nCh ssh.NewChannel, ch ssh.Channel, reqs <-chan *ssh.Request, conn ssh.Conn) {
	defer ch.Close()
	// Do something
}

func main() {
	handler := easyssh.NewChannelsMux()

	handler.HandleChannel("test", testHandler{})

	test2Handler := func(newChannel ssh.NewChannel, channel ssh.Channel, reqs <-chan *ssh.Request, sshConn ssh.Conn) {
		defer channel.Close()
		ssh.DiscardRequests(reqs)
	}

	handler.HandleChannelFunc("test2", test2Handler)

	handler.HandleChannel("anotherTest2", easyssh.ChannelHandlerFunc(test2Handler))
}
Output:

func (*ChannelsMux) HandleChannelFunc

func (s *ChannelsMux) HandleChannelFunc(channelType string, f func(newChannel ssh.NewChannel, channel ssh.Channel, reqs <-chan *ssh.Request, sshConn ssh.Conn))

HandleChannelFunc registers the Channel Handler function for the provided Channel Type

Example
package main

import (
	"dev.justinjudd.org/justin/easyssh"
	"golang.org/x/crypto/ssh"
)

func main() {
	handler := easyssh.NewChannelsMux()

	testHandler := func(newChannel ssh.NewChannel, channel ssh.Channel, reqs <-chan *ssh.Request, sshConn ssh.Conn) {
		defer channel.Close()
		ssh.DiscardRequests(reqs)
	}

	handler.HandleChannelFunc("test", testHandler)

}
Output:

func (*ChannelsMux) HandleChannels

func (s *ChannelsMux) HandleChannels(chans <-chan ssh.NewChannel, sshConn ssh.Conn)

HandleChannels acts a a mux for incoming channel requests

type Client

type Client struct {
	*ssh.Client
}

Client wraps an SSH Client

func Dial

func Dial(network, addr string, config *ssh.ClientConfig) (*Client, error)

Dial starts an ssh connection to the provided server

Example
package main

import (
	"log"

	"dev.justinjudd.org/justin/easyssh"
	"golang.org/x/crypto/ssh"
)

func main() {
	config := &ssh.ClientConfig{
		User: "test",
		Auth: []ssh.AuthMethod{
			ssh.Password("test"),
		},
	}
	conn, err := easyssh.Dial("tcp", "localhost:2022", config)
	if err != nil {
		log.Fatalf("unable to connect: %s", err)
	}
	defer conn.Close()
}
Output:

func NewClient

func NewClient(c ssh.Conn, chans <-chan ssh.NewChannel, reqs <-chan *ssh.Request) *Client

NewClient returns a new SSH Client.

func (*Client) HandleOpenChannel

func (c *Client) HandleOpenChannel(channelName string, handler ChannelMultipleRequestsHandler, data ...byte) error

HandleOpenChannel requests that the remote end accept a channel request and if accepted, passes the newly opened channel and requests to the provided handler

func (*Client) HandleOpenChannelFunc

func (c *Client) HandleOpenChannelFunc(channelName string, handler ChannelMultipleRequestsHandlerFunc, data ...byte) error

HandleOpenChannelFunc requests that the remote end accept a channel request and if accepted, passes the newly opened channel and requests to the provided handler function

func (*Client) LocalForward

func (c *Client) LocalForward(laddr, raddr *net.TCPAddr) error

LocalForward performs a port forwarding over the ssh connection - ssh -L. Client will bind to the local address, and will tunnel those requests to host addr

Example
package main

import (
	"log"
	"net"

	"dev.justinjudd.org/justin/easyssh"
	"golang.org/x/crypto/ssh"
)

func main() {
	config := &ssh.ClientConfig{
		User: "test",
		Auth: []ssh.AuthMethod{
			ssh.Password("test"),
		},
	}
	conn, err := easyssh.Dial("tcp", "localhost:2022", config)
	if err != nil {
		log.Fatalf("unable to connect: %s", err)
	}
	defer conn.Close()

	laddr, _ := net.ResolveTCPAddr("tcp", "localhost:8000")
	raddr, _ := net.ResolveTCPAddr("tcp", "localhost:6060")
	err = conn.LocalForward(laddr, raddr)
	if err != nil {
		log.Fatalf("unable to forward local port: %s", err)
	}

}
Output:

func (*Client) RemoteForward

func (c *Client) RemoteForward(remote, local string) error

RemoteForward forwards a remote port - ssh -R

Example
package main

import (
	"log"

	"dev.justinjudd.org/justin/easyssh"
	"golang.org/x/crypto/ssh"
)

func main() {
	config := &ssh.ClientConfig{
		User: "test",
		Auth: []ssh.AuthMethod{
			ssh.Password("test"),
		},
	}
	conn, err := easyssh.Dial("tcp", "localhost:2022", config)
	if err != nil {
		log.Fatalf("unable to connect: %s", err)
	}
	defer conn.Close()

	err = conn.RemoteForward("localhost:8000", "localhost:6060")
	if err != nil {
		log.Fatalf("unable to forward local port: %s", err)
	}

}
Output:

type ConnHandler

type ConnHandler interface {
	HandleSSHConn(ssh.Conn, <-chan ssh.NewChannel, <-chan *ssh.Request)
}

A ConnHandler is a top level SSH Manager. Objects implementing the ConnHandler are responsible for managing incoming Channels and Global Requests

type ConnHandlerFunc

type ConnHandlerFunc func(ssh.Conn, <-chan ssh.NewChannel, <-chan *ssh.Request)

ConnHandlerFunc is an adapter that allows regular functions to act as SSH Connection Handlers

func (ConnHandlerFunc) HandleSSHConn

func (f ConnHandlerFunc) HandleSSHConn(sshConn ssh.Conn, chans <-chan ssh.NewChannel, reqs <-chan *ssh.Request)

HandleSSHConn calls f(sshConn, chans, reqs)

type GlobalMultipleRequestsHandler

type GlobalMultipleRequestsHandler interface {
	HandleRequests(<-chan *ssh.Request, ssh.Conn)
}

GlobalMultipleRequestsHandler handles global (not tied to a channel) out-of-band SSH Requests

type GlobalMultipleRequestsHandlerFunc

type GlobalMultipleRequestsHandlerFunc func(<-chan *ssh.Request, ssh.Conn)

GlobalMultipleRequestsHandlerFunc is an adaper to allow regular functions to act as a Global Requests Handler

func (GlobalMultipleRequestsHandlerFunc) HandleRequests

func (f GlobalMultipleRequestsHandlerFunc) HandleRequests(reqs <-chan *ssh.Request, sshConn ssh.Conn)

HandleRequests calls f(reqs, sshConn)

type GlobalMultipleRequestsMux

type GlobalMultipleRequestsMux struct {
	// contains filtered or unexported fields
}

GlobalMultipleRequestsMux is an SSH Global Requests multiplexer. It matches Channel types and calls the handler for the corresponding type - can be used as GlobalMultipleRequestsHandler

func NewGlobalMultipleRequestsMux

func NewGlobalMultipleRequestsMux() *GlobalMultipleRequestsMux

NewGlobalMultipleRequestsMux creates and returns a GlobalMultipleRequestsHandler that performs multiplexing of request types with dispatching to GlobalRequestHandlers

func (*GlobalMultipleRequestsMux) HandleRequest

func (s *GlobalMultipleRequestsMux) HandleRequest(requestType string, handler GlobalRequestHandler)

HandleRequest registers the GlobalRequestHandler for the given Channel Type. If a GlobalRequestHandler was already registered for the type, HandleRequest panics

func (*GlobalMultipleRequestsMux) HandleRequestFunc

func (s *GlobalMultipleRequestsMux) HandleRequestFunc(requestType string, f func(*ssh.Request, ssh.Conn))

HandleRequestFunc registers the Channel Handler function for the provided Request Type

func (*GlobalMultipleRequestsMux) HandleRequests

func (s *GlobalMultipleRequestsMux) HandleRequests(reqs <-chan *ssh.Request, sshConn ssh.Conn)

HandleRequests handles global out-of-band SSH Requests -

type GlobalRequestHandler

type GlobalRequestHandler interface {
	HandleRequest(*ssh.Request, ssh.Conn)
}

GlobalRequestHandler handles global (not tied to a channel) out-of-band SSH Requests

func TCPIPForwardRequestHandler

func TCPIPForwardRequestHandler() GlobalRequestHandler

TCPIPForwardRequestHandler returns a GlobalRequestHandler that implements remote port forwarding - ssh -R

type GlobalRequestHandlerFunc

type GlobalRequestHandlerFunc func(*ssh.Request, ssh.Conn)

GlobalRequestHandlerFunc is an adaper to allow regular functions to act as a Global Request Handler

func (GlobalRequestHandlerFunc) HandleRequest

func (f GlobalRequestHandlerFunc) HandleRequest(req *ssh.Request, sshConn ssh.Conn)

HandleRequest calls f(reqs, sshConn)

type MultipleChannelsHandler

type MultipleChannelsHandler interface {
	HandleChannels(chans <-chan ssh.NewChannel, sshConn ssh.Conn)
}

MultipleChannelsHandler handles a chan of all SSH channel requests for a connection

type MultipleChannelsHandlerFunc

type MultipleChannelsHandlerFunc func(chans <-chan ssh.NewChannel, sshConn ssh.Conn)

MultipleChannelsHandlerFunc is an adapter that allows regular functions to act as SSH Multiple Channels Handlers

func (MultipleChannelsHandlerFunc) HandleChannels

func (f MultipleChannelsHandlerFunc) HandleChannels(chans <-chan ssh.NewChannel, sshConn ssh.Conn)

HandleChannels calls f(chans, sshConn)

type SSHConnHandler

SSHConnHandler is an SSH Channel multiplexer. It matches Channel types and calls the handler for the corresponding type

func NewSSHConnHandler

func NewSSHConnHandler() *SSHConnHandler

NewSSHConnHandler creates and returns a basic working ConnHandler to provide a minimal "working" SSH server

func NewSessionServerHandler

func NewSessionServerHandler() *SSHConnHandler

NewSessionServerHandler creates a ConnHandler to provide a more standard SSH server providing sessions

func NewStandardSSHServerHandler

func NewStandardSSHServerHandler() *SSHConnHandler

NewStandardSSHServerHandler returns a server handler that can deal with ssh sessions and both local and remote port forwarding

func (*SSHConnHandler) HandleSSHConn

func (s *SSHConnHandler) HandleSSHConn(sshConn ssh.Conn, chans <-chan ssh.NewChannel, reqs <-chan *ssh.Request)

HandleSSHConn manages incoming channel and out-of-band requests. It discards out-of-band requests and dispatches channel requests if a ChannelHandler is registered for a given Channel Type

type Server

type Server struct {
	Addr    string
	Config  *ssh.ServerConfig
	Handler ConnHandler
	*ssh.ServerConn
}

Server represents an SSH Server. The SSH ServerConfig must be provided

func (*Server) HandleOpenChannel

func (s *Server) HandleOpenChannel(channelName string, handler ChannelMultipleRequestsHandler, data ...byte) error

HandleOpenChannel requests that the remote end accept a channel request and if accepted, passes the newly opened channel and requests to the provided handler

func (*Server) HandleOpenChannelFunc

func (s *Server) HandleOpenChannelFunc(channelName string, handler func(reqs <-chan *ssh.Request, sshConn ssh.Conn, channelType string, channel ssh.Channel), data ...byte) error

HandleOpenChannelFunc requests that the remote end accept a channel request and if accepted, passes the newly opened channel and requests to the provided handler function

func (*Server) ListenAndServe

func (s *Server) ListenAndServe() error

ListenAndServe listens on the TCP address s.Addr and then calls Serve to handle requests on incoming connections. If s.Addr is blank, ":ssh" is used

Example
package main

import (
	"fmt"
	"io/ioutil"

	"dev.justinjudd.org/justin/easyssh"
	"golang.org/x/crypto/ssh"
)

func main() {
	s := easyssh.Server{Addr: ":2022"}

	privateBytes, err := ioutil.ReadFile("id_rsa")
	if err != nil {
		// Failed to load private key (./id_rsa)
	}

	private, err := ssh.ParsePrivateKey(privateBytes)
	if err != nil {
		// Failed to parse private key
	}

	config := &ssh.ServerConfig{
		PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
			if c.User() == "test" && string(pass) == "test" {
				return nil, nil
			}
			return nil, fmt.Errorf("password rejected for %s", c.User())
		},
	}
	config.AddHostKey(private)

	s.Config = config

	handler := easyssh.NewStandardSSHServerHandler()
	channelHandler := easyssh.NewChannelsMux()

	channelHandler.HandleChannel(easyssh.SessionRequest, easyssh.SessionHandler())
	handler.MultipleChannelsHandler = channelHandler

	s.Handler = handler

	s.ListenAndServe()
}
Output:

func (*Server) Serve

func (s *Server) Serve(l net.Listener) error

Serve accepts incoming connections on the provided listener.and reads global SSH Channel and Out-of-band requests and calls s,ConnHandler to handle them