sshego

package module
v5.1.1+incompatible Latest Latest
Warning

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

Go to latest
Published: Sep 10, 2017 License: MIT Imports: 43 Imported by: 0

README

sshego, a usable ssh library for Go

executive summary

Google's "golang.org/x/crypto/ssh" library offers a fantastic full implementation of the ssh client and server protocols. However this library is minimalistic by design, cumbersome to figure out how to use with RSA keys, and needs additional code to support support tunneling and receiving connections as an sshd.

sshego bridges this usability gap, providing a drop-in Go library to secure your tcp connections. In places sshego can be used in preference to a virtual-private-network (VPN), for both convenience and speed. Moreover the SSH protocol's man-in-the-middle attack protection is better than a VPN in almost all cases.

usable three-factor auth in an embeddable sshd

For strong security, our embedded sshd offers three-factor auth (3FA). The three security factors are: a passphrase ("what you know"); a 6-digit Google authenticator code (TOTP/RFC 6238; "what you have": your phone); and the use of PKI in the form of 4096-bit RSA keys.

To promote strong passphrases, we follow the inspiration of https://xkcd.com/936/, and offer a user- friendly 3-word starting prompt (the user completes the sentence) to spark the user's imagination in creating a strong and memorizable passphrase. Passphrases of up to 100 characters are supported.

Although not for the super-security conscious, if desired and configured, passphrases can automatically be backed up to email (via the Mailgun email service).

On new account creation with gosshtun -adduser yourlogin, we will attempt to pop-up the QR-code on your local desktop for quick Google Authenticator setup on your phone.

introducing sshego: a gopher's do-it-yourself ssh tunneling library

sshego is a golang (Go) library for ssh tunneling (secure port forwarding). It also offers an embeddable 3-factor authentication sshd server, which can be useful for securing reverse forwards.

This means you can easily create an ssh-based vpn with 3-factor authentication requrirements: the embedded sshd requires passphrase, RSA keys, and a TOTP Google Authenticator one-time password.

In addition to the libary, gosshtun is also a command line utility (see the cmd/ subdir) that demonstrates use of the library and may prove useful on its own.

The intent of having a Go library is so that it can be used to secure (via SSH tunnel) any other traffic that your Go application would normally have to do over cleartext TCP.

While you could always run a tunnel as a separate process, by running the tunnel in process with your application, you know the tunnel is running when the process is running. It's just simpler to administer; only one thing to start instead of two.

Also this is much simpler, and much faster, than using a virtual private network (VPN). For a speed comparison, consider [1] where SSH is seen to be at least 2x faster than OpenVPN.

[1] http://serverfault.com/questions/653211/ssh-tunneling-is-faster-than-openvpn-could-it-be

In its principal use, sshego is the equivalent to using the ssh client and giving -L and/or -R. It acts like an ssh client without a remote shell; it simply tunnels other TCP connections securely. There are also options to run an embedded SSHD. This can be useful for securing reverse forwards, if allowed.

For example,

gosshtun -listen 127.0.0.1:89  -sshd jumpy:55  -remote 10.0.1.5:80 -user alice -key ~/.ssh/id_rsa_nopw

is equivalent to

ssh -N -L 89:10.0.1.5:80 alice@jumpy -port 55

with the addendum that gosshtun requires the use of passwordless private -key file, and will never prompt you for a password at the keyboard. This makes it ideal for embedding inside your application to secure your (e.g. mysql, postgres, other cleartext) traffic. As many connections as you need will be multiplexed over the same ssh tunnel.

grain of access

If you don't trust the other users on the host where your process is running, you can also use sshego to (a) secure a direct TCP connection (see DialConfig.Dial() and the example in cli_test.go; https://github.com/glycerine/sshego/blob/master/cli_test.go#L72); or (b) forward via a file-system secured unix-domain sockets.

The first option (a) would disallow any other process (even under the same user) from multiplexing your original connection, and the second (b) would disallow any other user from accessing your tunnel, so long as you use the file-system permissions to make the unix-domain socket path inaccessible to others.

In either case, note that keys are by default stored on disk under the user's $HOME/.ssh folder, so as usual that folder should not be readable by others. Using a direct connection as in (a) in no way prevents you from starting another process (from the same executable or another) that reads the same keys and starts its own direct tcp connection.

theory of operation

gosshtun and sshego will check the sshd server's host key. We prevent MITM attacks by only allowing new servers if -new (a.k.a. SshegoConfig.AddIfNotKnown == true) is given.

When running the standalone gosshtun to test a foward, you should give -new only once at setup time.

Then the lack of -new protects you on subsequent runs, because the server's host key must match what we were given the very first time.

flags accepted, see gosshtun -h for complete list

Usage of gosshtun:
  -cfg string
        path to our config file
  -esshd string
        (optional) start an in-process embedded sshd (server),
        binding this host:port, with both RSA key and 2FA
        checking; useful for securing -revfwd connections.
  -esshd-host-db string
        (only matters if -esshd is also given) path
        to database holding sshd persistent state
        such as our host key, registered 2FA secrets, etc.
        (default "$HOME/.ssh/.sshego.sshd.db")        
  -key string
        private key for sshd login (default "$HOME/.ssh/id_rsa_nopw")
  -known-hosts string
        path to gosshtun's own known-hosts file (default
        "$HOME/.ssh/.sshego.cli.known.hosts")
  -listen string
        (forward tunnel) We listen on this host:port locally,
        securely tunnel that traffic to sshd, then send it
        cleartext to -remote. The forward tunnel is active
        if and only if -listen is given.  If host starts with
        a '/' then we treat it as the path to a unix-domain
        socket to listen on, and the port can be omitted.
  -new
        allow connecting to a new sshd host key, and store it
        for future reference. Otherwise prevent MITM attacks by
        rejecting unknown hosts.
  -quiet
        if -quiet is given, we don't log to stdout as each
        connection is made. The default is false; we log
        each tunneled connection.        
  -remote string
        (forward tunnel) After traversing the secured forward
        tunnel, -listen traffic flows in cleartext from the
        sshd to this host:port. The foward tunnel is active
        only if -listen is given too.  If host starts with a
        '/' then we treat it as the path to a unix-domain
        socket to forward to, and the port can be omitted.
  -revfwd string
        (reverse tunnel) The gosshtun application will receive
        securely tunneled connections from -revlisten on the
        sshd side, and cleartext forward them to this host:port.
        For security, it is recommended that this be 127.0.0.1:22,
        so that the sshd service on your gosshtun host
        authenticates all remotely initiated traffic.
        See also the -esshd option which can be used to
        secure the -revfwd connection as well.
        The reverse tunnel is active only if -revlisten is given
        too. (default "127.0.0.1:22")
  -revlisten string
        (reverse tunnel) The sshd will listen on this host:port,
        securely tunnel those connections to the gosshtun application,
        whence they will cleartext connect to the -revfwd address.
        The reverse tunnel is active if and only if -revlisten is given.  
  -sshd string
        The remote sshd host:port that we establish a secure tunnel to;
        our public key must have been already deployed there.
  -user string
        username for sshd login (default is $USER)
  -v    verbose debug mode
  -write-config string
        (optional) write our config to this path before doing
        connections

installation

go get github.com/glycerine/sshego/...

example use of the command

$ gosshtun -listen localhost:8888 -sshd 10.0.1.68:22 -remote 127.0.0.1:80

means the following two network hops will happen, when a local browser connects to localhost:8888

                       `gosshtun`             `sshd`
local browser ----> localhost:8888 --(a)--> 10.0.1.68:22 --(b)--> 127.0.0.1:80
  `host A`             `host A`               `host B`              `host B`

where (a) takes place inside the previously established ssh tunnel.

Connection (b) takes place over basic, un-adorned, un-encrypted TCP/IP. Of course you could always run gosshtun again on the remote host to secure the additional hop as well, but typically -remote is aimed at the 127.0.0.1, which will be internal to the remote host itself and so needs no encryption.

specifying username to login to sshd host with

The -user flag should be used if your local $USER is different from that on the sshd host.

source code for gosshtun command

See github.com/glycerine/sshego/cmd/gosshtun/main.go for the source code. This also serves as an example of how to use the library.

host key storage location (default)

~/.ssh/.sshego.known.hosts.json.snappy

prep before running

a) install your passwordless ssh-private key in ~/.ssh/id_rsa_nopw or use -key to say where it is.

b) add the corresponding public key to the user's .ssh/authorized_keys file on the sshd host.

config file format

a) see demo.env for an example

b) run gosshtun -write-config - to generate a sample config file to stdout

c) comments are allowed; lines must start with #, comments continue until end-of-line

d) fields recognized (see gosshtun -write-config - for a full list)

#
# config file for sshego:
#
SSHD_ADDR="1.2.3.4:22"
FWD_LISTEN_ADDR="127.0.0.1:8888"
FWD_REMOTE_ADDR="127.0.0.1:22"
REV_LISTEN_ADDR=""
REV_REMOTE_ADDR=""
SSHD_LOGIN_USERNAME="$USER"
SSH_PRIVATE_KEY_PATH="$HOME/.ssh/id_rsa_nopw"
SSH_KNOWN_HOSTS_PATH="$HOME/.ssh/.sshego.known.hosts"
#
# optional in-process sshd
#
EMBEDDED_SSHD_HOST_DB_PATH="$HOME/.ssh/.sshego.sshd.db"
EMBEDDED_SSHD_LISTEN_ADDR="127.0.0.1:2022"

d) special environment reads

  • The SSHD_LOGIN_USERNAME will subsitute $USER from the environment, if present.

  • The *PATH keys will substitute $HOME from the environment, if present.

MIT license

See the LICENSE file.

Author

Jason E. Aten, Ph.D.

Documentation

Overview

Package sshego is a golang libary that does secure port forwarding over ssh.

Also `gosshtun` is a command line utility included here that demonstrates use of the library; and may be useful standalone.

The intent of having a Go library is so that it can be used to secure (via SSH tunnel) any other traffic that your Go application would normally have to do over cleartext TCP.

While you could always run a tunnel as a separate process, by running the tunnel in process with your application, you know the tunnel is running when the process is running. It's just simpler to administer; only one thing to start instead of two.

Also this is much simpler, and much faster, than using a virtual private network (VPN). For a speed comparison, consider [1] where SSH is seen to be at least 2x faster than OpenVPN.

[1] http://serverfault.com/questions/653211/ssh-tunneling-is-faster-than-openvpn-could-it-be

The sshego library typically acts as an ssh client, but also provides options to support running an embedded sshd server daemon. Port forwarding is the most typical use of the client, and this is the equivalent of using the standalone `ssh` client program and giving the `-L` and/or `-R` flags.

If you only trust the user running your application and not your entire host, you can further restrict access by using either DialConfig.Dial() for a direct-tcpip connection, or by using the unix-domain-socket support.

For example,

gosshtun -listen 127.0.0.1:89  -sshd jumpy:55  -remote 10.0.1.5:80 -user alice -key ~/.ssh/id_rsa_nopw

is equivalent to

ssh -N -L 89:10.0.1.5:80 alice@jumpy -port 55

with the addendum that `gosshtun` requires the use of passwordless private `-key` file, and will never prompt you for a password at the keyboard. This makes it ideal for embedding inside your application to secure your (e.g. mysql, postgres, other cleartext) traffic. As many connections as you need will be multiplexed over the same ssh tunnel.

theory of operation

We check the sshd server's host key. We prevent MITM attacks by only allowing new servers if `-new` is given.

You should give `-new` only once at setup time.

Then the lack of `-new` can protect you on subsequent runs, because the server's host key must match what we were given the first time.

options

$ gosshtun -h
Usage of gosshtun:
 -cfg string
       path to our config file
 -esshd string
       (optional) start an in-process embedded sshd (server),
       binding this host:port, with both RSA key and 2FA
       checking; useful for securing -revfwd connections.
 -esshd-host-db string
       (only matters if -esshd is also given) path
       to database holding sshd persistent state
       such as our host key, registered 2FA secrets, etc.
       (default "$HOME/.ssh/.sshego.sshd.db")
 -key string
       private key for sshd login (default "$HOME/.ssh/id_rsa_nopw")
 -known-hosts string
       path to gosshtun's own known-hosts file (default
       "$HOME/.ssh/.sshego.cli.known.hosts")
 -listen string
       (forward tunnel) We listen on this host:port locally,
       securely tunnel that traffic to sshd, then send it
       cleartext to -remote. The forward tunnel is active
       if and only if -listen is given.  If host starts with
       a '/' then we treat it as the path to a unix-domain
       socket to listen on, and the port can be omitted.
 -new
       allow connecting to a new sshd host key, and store it
       for future reference. Otherwise prevent MITM attacks by
       rejecting unknown hosts.
 -quiet
       if -quiet is given, we don't log to stdout as each
       connection is made. The default is false; we log
       each tunneled connection.
 -remote string
       (forward tunnel) After traversing the secured forward
       tunnel, -listen traffic flows in cleartext from the
       sshd to this host:port. The foward tunnel is active
       only if -listen is given too.  If host starts with
       a '/' then we treat it as the path to a unix-domain
       socket to forward to, and the port can be omitted.
 -revfwd string
       (reverse tunnel) The gosshtun application will receive
       securely tunneled connections from -revlisten on the
       sshd side, and cleartext forward them to this host:port.
       For security, it is recommended that this be 127.0.0.1:22,
       so that the sshd service on your gosshtun host
       authenticates all remotely initiated traffic.
       See also the -esshd option which can be used to
       secure the -revfwd connection as well.
       The reverse tunnel is active only if -revlisten is given
       too. (default "127.0.0.1:22")
 -revlisten string
       (reverse tunnel) The sshd will listen on this host:port,
       securely tunnel those connections to the gosshtun application,
       whence they will cleartext connect to the -revfwd address.
       The reverse tunnel is active if and only if -revlisten is given.
 -sshd string
       The remote sshd host:port that we establish a secure tunnel to;
       our public key must have been already deployed there.
 -user string
       username for sshd login (default is $USER)
 -v    verbose debug mode
 -write-config string
       (optional) write our config to this path before doing
       connections
$

example use of the command

$ gosshtun -listen localhost:8888 -sshd 10.0.1.68:22 -remote 127.0.0.1:80

means the following two network hops will happen, when a local browser connects to localhost:8888

                       `gosshtun`             `sshd`
local browser ----> localhost:8888 --(a)--> 10.0.1.68:22 --(b)--> 127.0.0.1:80
  `host A`             `host A`               `host B`              `host B`

where (a) takes place inside the previously established ssh tunnel.

Connection (b) takes place over basic, un-adorned, un-encrypted TCP/IP. Of course you could always run `gosshtun` again on the remote host to secure the additional hop as well, but typically -remote is aimed at the 127.0.0.1, which will be internal to the remote host itself and so needs no encryption.

Index

Constants

View Source
const CustomInprocStreamChanName = "direct-tcpip"

CustomInprocStreamChanName is how sshego/reptile specific channels are named. const CustomInprocStreamChanName = "custom-inproc-stream"

View Source
const MUX_C_OPEN_FWD = 0x10000006 // 268435462
View Source
const ProgramName = "sshego-library"
View Source
const Verbose bool = false

Verbose can be set to true for debug output. For production builds it should be set to false, the default.

Variables

View Source
var DelUserCmd = []byte("01DELUSER___")
View Source
var DelUserCmdStr = string(DelUserCmd)
View Source
var DelUserReplyFailed = []byte("01REPLY_FAIL")
View Source
var DelUserReplyOK = []byte("01REPLY_OK__")
View Source
var ErrClosed = fmt.Errorf("channel closed")
View Source
var ErrCouldNotAquirePort = fmt.Errorf("could not acquire " +
	"our -xport before the deadline")
View Source
var ErrShutdown = fmt.Errorf("shutting down")
View Source
var GIT_BRANCH string
View Source
var GO_VERSION string
View Source
var LAST_GIT_COMMIT_HASH string
View Source
var NEAREST_GIT_TAG string
View Source
var NewUserCmd = []byte("00NEWUSER___")
View Source
var NewUserCmdStr = string(NewUserCmd)
View Source
var NewUserReply = []byte("00REPLY_____")

Functions

func AddUserAndExit added in v1.5.7

func AddUserAndExit(cfg *SshegoConfig)

func Base64ofPublicKey added in v1.8.0

func Base64ofPublicKey(key ssh.PublicKey) string

func CryptoRandBytes

func CryptoRandBytes(n int) []byte

func CryptoRandInt64

func CryptoRandInt64() int64

Use crypto/rand to get an random int64

func CryptoRandNonNegInt

func CryptoRandNonNegInt(n int64) int64

func DelUserAndExit added in v1.5.7

func DelUserAndExit(cfg *SshegoConfig)

func DialRemoteUnixDomain added in v1.4.0

func DialRemoteUnixDomain(ctx context.Context, c *ssh.Client, udpath string) (net.Conn, error)

DialRemoteUnixDomain initiates a connection to udpath from the remote host using c as the ssh client. Here udpath is a unixDomain socket path in the remote filesystem. The resulting connection has a zero LocalAddr() and RemoteAddr().

func DiscardRequestsExceptKeepalives

func DiscardRequestsExceptKeepalives(ctx context.Context, in <-chan *ssh.Request, reqStop chan struct{})

DiscardRequestsExceptKeepalives accepts and responds to requests of type "keepalive@sshego.glycerine.github.com" that want reply; these are used as ping/pong messages to detect ssh connection failure.

func Fingerprint

func Fingerprint(k ssh.PublicKey) string

Fingerprint performs a SHA256 BASE64 fingerprint of the PublicKey, similar to OpenSSH. See: https://anongit.mindrot.org/openssh.git/commit/?id=56d1c83cdd1ac

func GenRSAKeyPair

func GenRSAKeyPair(rsaFile string, bits int, email string) (priv *rsa.PrivateKey, sshPriv ssh.Signer, err error)

GenRSAKeyPair generates an RSA keypair of length bits. If rsa_file != "", we write the private key to rsa_file and the public key to rsa_file + ".pub". If rsa_file == "" the keys are not written to disk.

func GenRSAKeyPairCrypt

func GenRSAKeyPairCrypt(rsaFile string, bits int, password string) (priv *rsa.PrivateKey, sshPriv ssh.Signer, err error)

TODO: Finish this-- specified but password based encryption not implemented. GenRSAKeyPairCrypt generates an RSA keypair of length bits. If rsa_file != "", we write the private key to rsa_file and the public key to rsa_file + ".pub". If rsa_file == "" the keys are not written to disk. The private key is encrypted with the password.

func GetAvailPort added in v1.5.7

func GetAvailPort() (net.Listener, int)

GetAvailPort asks the OS for an unused port, returning a bound net.Listener and the port number to which it is bound. The caller should Close() the listener when it is done with the port.

func GetExternalIP

func GetExternalIP() string

GetExternalIP tries to determine the external IP address used on this host.

func IsAlreadyBound added in v1.5.7

func IsAlreadyBound(addr string) bool

func IsRoutableIPv4

func IsRoutableIPv4(ip string) bool

IsRoutableIPv4 returns true if the string in ip represents an IPv4 address that is not private. See http://en.wikipedia.org/wiki/Private_network#Private_IPv4_address_spaces for the numeric ranges that are private. 127.0.0.1, 192.168.0.1, and 172.16.0.1 are examples of non-routables IP addresses.

func KnownHostsEqual

func KnownHostsEqual(a, b *KnownHosts) (bool, error)

KnownHostsEqual compares two instances of KnownHosts structures for equality.

func LoadRSAPrivateKey

func LoadRSAPrivateKey(path string) (privkey ssh.Signer, err error)

LoadRSAPrivateKey reads a private key from path on disk.

func LoadRSAPrivateKeyCrypt

func LoadRSAPrivateKeyCrypt(path string, password string) (privkey ssh.Signer, err error)

TODO: Finish this-- specified but password based encryption not implemented. LoadRSAPrivateKey reads a private key from path on disk.

func LoadRSAPublicKey

func LoadRSAPublicKey(path string) (pubkey ssh.PublicKey, err error)

LoadRSAPublicKey reads a public key from path on disk. By convention these keys end in '.pub', but that is not verified here.

func MakeAndMoveToTempDir added in v1.5.7

func MakeAndMoveToTempDir() (origdir string, tmpdir string)

func PromptForPassword

func PromptForPassword(username string) (pw string, err error)

PromptForPassword ask

func RSAToSSHPublicKey

func RSAToSSHPublicKey(pubkey *rsa.PublicKey) []byte

RSAToSSHPublicKey convert an RSA Public Key to the SSH authorized_keys format.

func RandomString added in v1.4.0

func RandomString(n int) string

func ScryptHash

func ScryptHash(password string) []byte

func SetWinsize

func SetWinsize(fd uintptr, w, h uint32)

SetWinsize sets the size of the given pty.

func SourceVersion added in v1.4.6

func SourceVersion() string

SourceVersion returns the git source code version this code was built from.

func StartBackgroundTestTcpServer added in v1.5.7

func StartBackgroundTestTcpServer(mgr *ssh.Halter, payloadByteCount int, confirmationPayload string, confirmationReply string, tcpSrvLsn net.Listener, pnc *net.Conn)

func TempDirCleanup added in v1.5.7

func TempDirCleanup(origdir string, tmpdir string)

func TestCreateNewAccount added in v1.5.7

func TestCreateNewAccount(srvCfg *SshegoConfig) (mylogin, toptPath, rsaPath, pw string, err error)

func UHPEqual

func UHPEqual(a, b *UHP) bool

UHPEqual returns true iff a and b are both not nil and they have equal fields.

func UnencPingPong added in v1.5.7

func UnencPingPong(dest, confirmationPayload, confirmationReply string, payloadByteCount int)

func VerifyClientServerExchangeAcrossSshd added in v1.5.7

func VerifyClientServerExchangeAcrossSshd(channelToTcpServer net.Conn, confirmationPayload, confirmationReply string, payloadByteCount int)

func WaitUntilAddrAvailable added in v1.5.7

func WaitUntilAddrAvailable(addr string, dur time.Duration, tries int) int

waitUntilAddrAvailable returns -1 if the addr was always unavailable after tries sleeps of dur time. Otherwise it returns the number of tries it took. Between attempts we wait 'dur' time before trying again.

Types

type AddrHostPort

type AddrHostPort struct {
	Title          string
	Addr           string
	Host           string
	Port           int64
	UnixDomainPath string
	Required       bool
}

AddrHostPort is used to specify tunnel endpoints.

func (*AddrHostPort) ParseAddr

func (a *AddrHostPort) ParseAddr() error

ParseAddr fills Host and Port from Addr, breaking Addr apart at the ':' using net.SplitHostPort()

type AtomicUserMap

type AtomicUserMap struct {
	U map[string]*User
	// contains filtered or unexported fields
}

func NewAtomicUserMap

func NewAtomicUserMap() *AtomicUserMap

func (*AtomicUserMap) DecodeMsg

func (z *AtomicUserMap) DecodeMsg(dc *msgp.Reader) (err error)

DecodeMsg implements msgp.Decodable We treat empty fields as if we read a Nil from the wire.

func (*AtomicUserMap) Del

func (m *AtomicUserMap) Del(key string)

func (*AtomicUserMap) EncodeMsg

func (z *AtomicUserMap) EncodeMsg(en *msgp.Writer) (err error)

EncodeMsg implements msgp.Encodable

func (*AtomicUserMap) Get

func (m *AtomicUserMap) Get(key string) *User

func (*AtomicUserMap) Get2

func (m *AtomicUserMap) Get2(key string) (*User, bool)

func (*AtomicUserMap) MarshalMsg

func (z *AtomicUserMap) MarshalMsg(b []byte) (o []byte, err error)

MarshalMsg implements msgp.Marshaler

func (*AtomicUserMap) Msgsize

func (z *AtomicUserMap) Msgsize() (s int)

Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message

func (*AtomicUserMap) Set

func (m *AtomicUserMap) Set(key string, val *User)

func (*AtomicUserMap) String added in v1.5.9

func (m *AtomicUserMap) String() string

func (*AtomicUserMap) UnmarshalMsg

func (z *AtomicUserMap) UnmarshalMsg(bts []byte) (o []byte, err error)

UnmarshalMsg implements msgp.Unmarshaler

func (*AtomicUserMap) UnmarshalMsgWithCfg added in v1.7.1

func (z *AtomicUserMap) UnmarshalMsgWithCfg(bts []byte, cfg *msgp.RuntimeConfig) (o []byte, err error)

type AuthState

type AuthState struct {
	HostKey ssh.Signer
	OneTime *TOTP

	AuthorizedKeysMap map[string]bool

	PrivateKeys map[string]interface{}
	Signers     map[string]ssh.Signer
	PublicKeys  map[string]ssh.PublicKey

	Cert *ssh.Certificate
}

AuthState holds the authorization information that doesn't change after startup; each fresh PerAttempt gets a pointer to one of these. Currently assumes only one user.

func NewAuthState

func NewAuthState(w *TOTP) *AuthState

func (*AuthState) LoadHostKey

func (a *AuthState) LoadHostKey(path string) error

func (*AuthState) LoadPublicKeys

func (a *AuthState) LoadPublicKeys(authorizedKeysPath string) error

type BasicAddress added in v1.5.5

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

Address satisfies the net.Addr interface, which BasicListener.Addr() returns.

func (*BasicAddress) Network added in v1.5.5

func (a *BasicAddress) Network() string

Network returns the name of the network, "sshego"

func (*BasicAddress) String added in v1.5.5

func (a *BasicAddress) String() string

String returns the string form of the address.

type BasicListener added in v1.5.5

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

BasicListener satifies the net.Listener interface

func (*BasicListener) Accept added in v1.5.5

func (b *BasicListener) Accept(ctx context.Context) (net.Conn, error)

Accept and Listen support BasicServer functionality. Accept waits for and returns the next connection to the listener.

func (*BasicListener) Addr added in v1.5.5

func (b *BasicListener) Addr() net.Addr

Addr returns the listener's network address.

func (*BasicListener) Close added in v1.5.5

func (b *BasicListener) Close() error

Close closes the listener. Any blocked Accept operations will be unblocked and return errors.

type BasicServer added in v1.5.5

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

BasicServer configures a simple embedded sshd server that only expects RSA key (or other) based authentication, and doesn't expect TOTP or passphase. This makes it suitable for using with unattended systems / to replace a TLS server.

func NewBasicServer added in v1.5.5

func NewBasicServer(cfg *SshegoConfig) *BasicServer

NewBasicServer in listen.go provides net.Listen() compatibility for running an embedded sshd. It refactors server.go's Start() into Listen() and Accept().

func (*BasicServer) Close added in v1.5.5

func (b *BasicServer) Close() error

Close releases all server port bindings.

func (*BasicServer) Listen added in v1.5.5

func (bs *BasicServer) Listen(laddr string) (*BasicListener, error)

Listen announces on the local network address laddr. The syntax of laddr is "host:port", like "127.0.0.1:2222". We listen on a TCP port.

type CommandRecv

type CommandRecv struct {
	Done chan bool
	// contains filtered or unexported fields
}

func (*CommandRecv) Start

func (cr *CommandRecv) Start(ctx context.Context) error

type ConnectionAlert added in v1.5.5

type ConnectionAlert struct {
	PortOne  chan ssh.Channel
	ShutDown chan struct{}
}

type CustomChannelHandlerCB added in v1.7.1

type CustomChannelHandlerCB func(nc ssh.NewChannel, sshconn ssh.Conn, ca *ConnectionAlert)

CustomChannelHandlerCB is a callback that is configured in the cfg.CustomChannelHandlers map. Each will be called on its own goroutine already. For example, "custom-inproc-stream" might serve in-process streaming.

type DialConfig

type DialConfig struct {

	// ClientKnownHostsPath is the path to the file
	// on client's disk that holds the known server keys.
	ClientKnownHostsPath string

	// cached to avoid a disk read, we only read
	// from ClientKnownHostsPath if KnownHosts is nil.
	// Users of DialConfig can leave this nil and
	// simply provide ClientKnownHostsPath. It is
	// exposed in case you need to invalidate the
	// cache and start again.
	KnownHosts *KnownHosts

	// the username to login under
	Mylogin string

	// the path on the local file system (client side) from
	// which to read the client's RSA private key.
	RsaPath string

	// the time-based one-time password configuration
	TotpUrl string

	// Pw is the passphrase
	Pw string

	// which sshd to connect to, host and port.
	Sshdhost string
	Sshdport int64

	// DownstreamHostPort is the host:port string of
	// the tcp address to which the sshd should forward
	// our connection to.
	DownstreamHostPort string

	// TofuAddIfNotKnown, for maximum security,
	// should be always left false and
	// the host key database should be configured
	// manually. If true, the client trusts the server's
	// provided key and stores it, which creates
	// vulnerability to a MITM attack.
	//
	// TOFU stands for Trust-On-First-Use.
	//
	// If set to true, Dial() will stoop
	// after storing a new key, or error
	// out if the key is already known.
	// In either case, a 2nd attempt at
	// Dial is required wherein on the
	// TofuAddIfNotKnown is set to false.
	//
	TofuAddIfNotKnown bool

	// DoNotUpdateSshKnownHosts prevents writing
	// to the file given by ClientKnownHostsPath, if true.
	DoNotUpdateSshKnownHosts bool

	Verbose bool

	// test only; see SshegoConfig
	TestAllowOneshotConnect bool

	// SkipKeepAlive default to false and we send
	// a keepalive every minute.
	SkipKeepAlive bool

	KeepAliveEvery time.Duration // default 30 seconds
}

DialConfig provides Dial() with what it needs in order to establish an encrypted and authenticated ssh connection.

func (*DialConfig) Dial

func (dc *DialConfig) Dial(parCtx context.Context, skipDownstream bool) (nc net.Conn, sshClient *ssh.Client, cfg *SshegoConfig, err error)

Dial is a convenience method for contacting an sshd over tcp and creating a direct-tcpip encrypted stream. It is a simple two-step sequence of calling dc.Cfg.SSHConnect() and then calling Dial() on the returned *ssh.Client.

PRE: dc.Cfg.KnownHosts should already be instantiated. To prevent MITM attacks, the host we contact at hostport must have its server key must be already in the KnownHosts.

dc.RsaPath is the path to the our (the client's) rsa private key file.

dc.DownstreamHostPort is the host:port tcp address string to which the sshd should forward our connection after successful authentication.

func (*DialConfig) DialGetTricorder

func (dc *DialConfig) DialGetTricorder(parCtx context.Context) (channelToTcpServer net.Conn, tri *Tricorder, err error)

type Esshd

type Esshd struct {
	Halt ssh.Halter
	// contains filtered or unexported fields
}

Esshd is our embedded sshd server, running from inside this libary.

func (*Esshd) Listen added in v1.5.5

func (e *Esshd) Listen(bs *BasicServer) (*BasicListener, error)

Listen and Accept support BasicServer functionality. Together, Listen() then Accept() replace Start().

func (*Esshd) NewCommandRecv

func (e *Esshd) NewCommandRecv() *CommandRecv

func (*Esshd) Start

func (e *Esshd) Start(ctx context.Context)

func (*Esshd) Stop

func (e *Esshd) Stop() error

type Filedb added in v1.7.2

type Filedb struct {
	HostDb *HostDb `zid:"0"`
	// contains filtered or unexported fields
}

func NewFiledb added in v1.8.0

func NewFiledb(filepath string) (*Filedb, error)

func (*Filedb) Close added in v1.7.2

func (b *Filedb) Close()

func (*Filedb) DecodeMsg added in v1.7.2

func (z *Filedb) DecodeMsg(dc *msgp.Reader) (err error)

DecodeMsg implements msgp.Decodable We treat empty fields as if we read a Nil from the wire.

func (*Filedb) EncodeMsg added in v1.7.2

func (z *Filedb) EncodeMsg(en *msgp.Writer) (err error)

EncodeMsg implements msgp.Encodable

func (*Filedb) MarshalMsg added in v1.7.2

func (z *Filedb) MarshalMsg(b []byte) (o []byte, err error)

MarshalMsg implements msgp.Marshaler

func (*Filedb) Msgsize added in v1.7.2

func (z *Filedb) Msgsize() (s int)

Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message

func (*Filedb) SaveToDisk added in v1.7.2

func (b *Filedb) SaveToDisk() error

func (*Filedb) UnmarshalMsg added in v1.7.2

func (z *Filedb) UnmarshalMsg(bts []byte) (o []byte, err error)

UnmarshalMsg implements msgp.Unmarshaler

func (*Filedb) UnmarshalMsgWithCfg added in v1.7.2

func (z *Filedb) UnmarshalMsgWithCfg(bts []byte, cfg *msgp.RuntimeConfig) (o []byte, err error)

type Forwarder

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

Forwarder represents one bi-directional forward (sshego to sshd) tcp connection.

func NewForward

func NewForward(ctx context.Context, cfg *SshegoConfig, sshClientConn *ssh.Client, fromBrowser net.Conn) *Forwarder

NewForward is called to produce a Forwarder structure for each new forward connection.

type HostDb

type HostDb struct {
	UserHomePrefix string

	HostSshSigner ssh.Signer `msg:"-"`

	Persist HostDbPersist
	// contains filtered or unexported fields
}

func (*HostDb) AddUser

func (h *HostDb) AddUser(mylogin, myemail, pw, issuer, fullname, extantPrivateKeyPath string) (toptPath, qrPath, rsaPath string, err error)

AddUser will use an existing extantRsaPath path to private key if provided, otherwise we make a new private/public key pair.

func (*HostDb) DecodeMsg

func (z *HostDb) DecodeMsg(dc *msgp.Reader) (err error)

DecodeMsg implements msgp.Decodable We treat empty fields as if we read a Nil from the wire.

func (*HostDb) DelUser

func (h *HostDb) DelUser(mylogin string) error

func (*HostDb) EncodeMsg

func (z *HostDb) EncodeMsg(en *msgp.Writer) (err error)

EncodeMsg implements msgp.Encodable

func (*HostDb) MarshalMsg

func (z *HostDb) MarshalMsg(b []byte) (o []byte, err error)

MarshalMsg implements msgp.Marshaler

func (*HostDb) Msgsize

func (z *HostDb) Msgsize() (s int)

Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message

func (*HostDb) Rsapath added in v1.8.0

func (h *HostDb) Rsapath(username string) string

func (*HostDb) String added in v1.5.9

func (h *HostDb) String() string

func (*HostDb) UnmarshalMsg

func (z *HostDb) UnmarshalMsg(bts []byte) (o []byte, err error)

UnmarshalMsg implements msgp.Unmarshaler

func (*HostDb) UnmarshalMsgWithCfg added in v1.7.1

func (z *HostDb) UnmarshalMsgWithCfg(bts []byte, cfg *msgp.RuntimeConfig) (o []byte, err error)

func (*HostDb) UserExists

func (h *HostDb) UserExists(mylogin string) bool

UserExists is used by sshego/cmd/gosshtun/main.go

func (*HostDb) ValidEmail

func (h *HostDb) ValidEmail(myemail string) (bool, error)

func (*HostDb) ValidLogin

func (h *HostDb) ValidLogin(login string) (bool, error)

type HostDbPersist added in v1.8.0

type HostDbPersist struct {
	// Users: key is MyLogin; value is *User.
	Users              *AtomicUserMap `zid:"0"`
	HostPrivateKeyPath string         `zid:"1"`
}

only these fields are actually saved/restored.

func (*HostDbPersist) DecodeMsg added in v1.8.0

func (z *HostDbPersist) DecodeMsg(dc *msgp.Reader) (err error)

DecodeMsg implements msgp.Decodable We treat empty fields as if we read a Nil from the wire.

func (*HostDbPersist) EncodeMsg added in v1.8.0

func (z *HostDbPersist) EncodeMsg(en *msgp.Writer) (err error)

EncodeMsg implements msgp.Encodable

func (*HostDbPersist) MarshalMsg added in v1.8.0

func (z *HostDbPersist) MarshalMsg(b []byte) (o []byte, err error)

MarshalMsg implements msgp.Marshaler

func (*HostDbPersist) Msgsize added in v1.8.0

func (z *HostDbPersist) Msgsize() (s int)

Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message

func (*HostDbPersist) UnmarshalMsg added in v1.8.0

func (z *HostDbPersist) UnmarshalMsg(bts []byte) (o []byte, err error)

UnmarshalMsg implements msgp.Unmarshaler

func (*HostDbPersist) UnmarshalMsgWithCfg added in v1.8.0

func (z *HostDbPersist) UnmarshalMsgWithCfg(bts []byte, cfg *msgp.RuntimeConfig) (o []byte, err error)

type HostState

type HostState int

HostState recognizes host keys are legitimate or impersonated, new, banned, or consitent with what we've seen before and so OK.

const AddedNew HostState = 4

AddedNew means the -new flag was given and we allowed the addition of a new host-key for the first time.

const Banned HostState = 1

Banned means the host has been marked as forbidden.

const KnownOK HostState = 2

KnownOK means the host key matches one we have previously allowed.

const KnownRecordMismatch HostState = 3

KnownRecordMismatch means we have a records for this IP/host-key, but either the IP or the host-key has varied and so it could be a Man-in-the-middle attack.

const Unknown HostState = 0

Unknown means we don't have a matching stored host key.

func (HostState) String

func (s HostState) String() string

type KeepAlivePing

type KeepAlivePing struct {
	Sent    time.Time `zid:"0"`
	Replied time.Time `zid:"1"`
	Serial  int64     `zid:"2"`
}

func (*KeepAlivePing) DecodeMsg

func (z *KeepAlivePing) DecodeMsg(dc *msgp.Reader) (err error)

DecodeMsg implements msgp.Decodable We treat empty fields as if we read a Nil from the wire.

func (KeepAlivePing) EncodeMsg

func (z KeepAlivePing) EncodeMsg(en *msgp.Writer) (err error)

EncodeMsg implements msgp.Encodable

func (KeepAlivePing) MarshalMsg

func (z KeepAlivePing) MarshalMsg(b []byte) (o []byte, err error)

MarshalMsg implements msgp.Marshaler

func (KeepAlivePing) Msgsize

func (z KeepAlivePing) Msgsize() (s int)

Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message

func (*KeepAlivePing) UnmarshalMsg

func (z *KeepAlivePing) UnmarshalMsg(bts []byte) (o []byte, err error)

UnmarshalMsg implements msgp.Unmarshaler

func (*KeepAlivePing) UnmarshalMsgWithCfg

func (z *KeepAlivePing) UnmarshalMsgWithCfg(bts []byte, cfg *msgp.RuntimeConfig) (o []byte, err error)

type KnownHosts

type KnownHosts struct {
	Hosts map[string]*ServerPubKey

	// FilepathPrefix doesn't have the .json.snappy suffix on it.
	FilepathPrefix string

	PersistFormatSuffix string

	// PersistFormat is the format indicator
	PersistFormat KnownHostsPersistFormat

	// NoSave means we don't touch the files we read from
	NoSave bool

	Mut sync.Mutex
	// contains filtered or unexported fields
}

KnownHosts represents in Hosts a hash map of host identifier (ip or name) and the corresponding public key for the server. It corresponds to the ~/.ssh/known_hosts file.

func LoadSshKnownHosts

func LoadSshKnownHosts(path string) (*KnownHosts, error)

LoadSshKnownHosts reads a ~/.ssh/known_hosts style file from path, see the SSH_KNOWN_HOSTS FILE FORMAT section of http://manpages.ubuntu.com/manpages/zesty/en/man8/sshd.8.html or the local sshd(8) man page.

func NewKnownHosts

func NewKnownHosts(filepath string, format KnownHostsPersistFormat) (*KnownHosts, error)

NewKnownHosts creats a new KnownHosts structure. filepathPrefix does not include the PersistFormat suffix. If filepathPrefix + defaultFileFormat() exists as a file on disk, then we read the contents of that file into the new KnownHosts.

The returned KnownHosts will remember the filepathPrefix for future saves.

func (*KnownHosts) AddNeeded

func (h *KnownHosts) AddNeeded(addIfNotKnown, allowOneshotConnect bool, hostname string, remote net.Addr, strPubBytes string, key ssh.PublicKey, record *ServerPubKey) (HostState, *ServerPubKey, error)

func (*KnownHosts) Close

func (h *KnownHosts) Close()

Close cleans up and prepares for shutdown. It calls h.Sync() to write the state to disk.

func (*KnownHosts) HostAlreadyKnown

func (h *KnownHosts) HostAlreadyKnown(hostname string, remote net.Addr, key ssh.PublicKey, pubBytes []byte, addIfNotKnown bool, allowOneshotConnect bool) (HostState, *ServerPubKey, error)

HostAlreadyKnown checks the given host details against our known hosts file.

func (*KnownHosts) Sync

func (h *KnownHosts) Sync() (err error)

Sync writes the contents of the KnownHosts structure to the file h.FilepathPrefix + h.PersistFormat (for json/gob); to just h.FilepathPrefix for "ssh_known_hosts" format.

type KnownHostsPersistFormat

type KnownHostsPersistFormat int

type LoginRecord

type LoginRecord struct {
	FirstTm       time.Time
	LastTm        time.Time
	SeenCount     int64
	AcceptedCount int64
	PubFinger     string
}

LoginRecord is per public key.

func (*LoginRecord) DecodeMsg

func (z *LoginRecord) DecodeMsg(dc *msgp.Reader) (err error)

DecodeMsg implements msgp.Decodable We treat empty fields as if we read a Nil from the wire.

func (*LoginRecord) EncodeMsg

func (z *LoginRecord) EncodeMsg(en *msgp.Writer) (err error)

EncodeMsg implements msgp.Encodable

func (*LoginRecord) MarshalMsg

func (z *LoginRecord) MarshalMsg(b []byte) (o []byte, err error)

MarshalMsg implements msgp.Marshaler

func (*LoginRecord) Msgsize

func (z *LoginRecord) Msgsize() (s int)

Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message

func (LoginRecord) String

func (r LoginRecord) String() string

func (*LoginRecord) UnmarshalMsg

func (z *LoginRecord) UnmarshalMsg(bts []byte) (o []byte, err error)

UnmarshalMsg implements msgp.Unmarshaler

func (*LoginRecord) UnmarshalMsgWithCfg added in v1.7.1

func (z *LoginRecord) UnmarshalMsgWithCfg(bts []byte, cfg *msgp.RuntimeConfig) (o []byte, err error)

type MailgunConfig

type MailgunConfig struct {

	// MAILGUN_DOMAIN
	Domain string

	// MAILGUN_PUBLIC_API_KEY
	PublicApiKey string

	//MAILGUN_SECRET_API_KEY
	SecretApiKey string
}

MailgunConfig sets up sending backup emails through Mailgun. See https://mailgun.com.

func (*MailgunConfig) DefineFlags

func (c *MailgunConfig) DefineFlags(fs *flag.FlagSet)

DefineFlags should be called before myflags.Parse().

func (*MailgunConfig) LoadConfig

func (c *MailgunConfig) LoadConfig(path string) error

LoadConfig reads configuration from a file, expecting KEY=value pair on each line; values optionally enclosed in double quotes.

func (*MailgunConfig) SaveConfig

func (c *MailgunConfig) SaveConfig(fd io.Writer) error

SaveConfig writes the config structs to the given io.Writer

func (*MailgunConfig) SendEmail

func (c *MailgunConfig) SendEmail(senderEmail, subject, plain, html, recipEmail string) (string, error)

func (*MailgunConfig) ValidateConfig

func (c *MailgunConfig) ValidateConfig() error

ValidateConfig should be called after myflags.Parse().

type PerAttempt

type PerAttempt struct {
	PublicKeyOK bool
	OneTimeOK   bool

	User   *User
	State  *AuthState
	Config *ssh.ServerConfig
	// contains filtered or unexported fields
}

PerAttempt holds the auth state that should be reset anew on each login attempt; plus a pointer to the invariant State.

func NewPerAttempt

func NewPerAttempt(s *AuthState, cfg *SshegoConfig) *PerAttempt

func (*PerAttempt) AuthLogCallback

func (a *PerAttempt) AuthLogCallback(conn ssh.ConnMetadata, method string, err error)

func (*PerAttempt) KeyboardInteractiveCallback

func (a *PerAttempt) KeyboardInteractiveCallback(ctx context.Context, conn ssh.ConnMetadata, challenge ssh.KeyboardInteractiveChallenge) (*ssh.Permissions, error)

func (*PerAttempt) NoteLogin

func (a *PerAttempt) NoteLogin(user *User, now time.Time, conn ssh.ConnMetadata)

func (*PerAttempt) PerConnection

func (a *PerAttempt) PerConnection(ctx context.Context, nConn net.Conn, ca *ConnectionAlert) error

func (*PerAttempt) PublicKeyCallback

func (a *PerAttempt) PublicKeyCallback(c ssh.ConnMetadata, providedPubKey ssh.PublicKey) (perm *ssh.Permissions, rerr error)

func (*PerAttempt) SetTripleConfig

func (a *PerAttempt) SetTripleConfig()

SetTripleConfig establishes an a.State.Config that requires *both* public key and one-time password validation.

func (*PerAttempt) SetupAuthRequirements

func (a *PerAttempt) SetupAuthRequirements()

type Reverse

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

Reverse represents one bi-directional (initiated at sshd, tunneled to sshego) tcp connection.

type ServerPubKey

type ServerPubKey struct {
	Hostname string

	// HumanKey is a serialized and readable version of Key, the key for Hosts map in KnownHosts.
	HumanKey     string
	ServerBanned bool

	// reading ~/.ssh/known_hosts
	Markers                  string
	Hostnames                string
	SplitHostnames           map[string]bool
	Keytype                  string
	Base64EncodededPublicKey string
	Comment                  string
	Port                     string
	LineInFileOneBased       int

	// if AlreadySaved, then we don't need to append.
	AlreadySaved bool

	// lock around SplitHostnames access
	Mut sync.Mutex
	// contains filtered or unexported fields
}

ServerPubKey stores the RSA public keys for a particular known server. This structure is stored in KnownHosts.Hosts.

func (*ServerPubKey) AddHostPort

func (prior *ServerPubKey) AddHostPort(hp string)

type SshegoConfig

type SshegoConfig struct {
	Nickname string
	Halt     *ssh.Halter

	KeepAliveEvery time.Duration // default 1 second.
	SkipKeepAlive  bool

	IdleTimeoutDur time.Duration

	ConfigPath string

	SSHdServer    AddrHostPort // the sshd host we are logging into remotely.
	LocalToRemote TunnelSpec
	RemoteToLocal TunnelSpec

	Debug bool

	AddIfNotKnown bool

	// user login creds for client
	Username             string // for client to login with.
	PrivateKeyPath       string // path to user's RSA private key
	ClientKnownHostsPath string // path to user's/client's known hosts

	KnownHosts *KnownHosts

	WriteConfigOut string

	// if -write-config is all we are doing
	WriteConfigOnly bool

	Quiet bool

	Esshd                  *Esshd
	EmbeddedSSHdHostDbPath string
	EmbeddedSSHd           AddrHostPort // optional local sshd, embedded.

	HostDb *HostDb

	AddUser string
	DelUser string

	SshegoSystemMutexPortString string
	SshegoSystemMutexPort       int

	MailCfg MailgunConfig

	// allow less than 3FA
	// Not recommended, but possible.
	SkipTOTP       bool
	SkipPassphrase bool
	SkipRSA        bool

	BitLenRSAkeys int

	DirectTcp   bool
	ShowVersion bool

	//
	// ==== testing support ====
	//
	Origdir, Tempdir string

	// TestAllowOneshotConnect is
	// a convenience for testing.
	//
	// If we discover and add a new
	// sshd host key on this first,
	// allow the connection to
	// continue on without
	// erroring out -- the gosshtun
	// command line does this to
	// teach users safe run
	// practices, but under test
	// it is just annoying.
	TestAllowOneshotConnect bool

	// for "custom-inproc-stream", etc.
	CustomChannelHandlers map[string]CustomChannelHandlerCB

	// SkipCommandRecv if true, says don't
	// start up the CommandRecv goroutine
	// on the SshegoSystemMutexPort port.
	// Commandline adding users won't work.
	SkipCommandRecv bool

	Mut sync.Mutex

	// Underling TCP network connection
	Underlying net.Conn

	// once started, the SSHConnect() call
	// will set this, so that cfg becomes
	// all self-contained.
	SshClient *ssh.Client

	// NoAutoReconnect if true, turns off
	// our automatic reconnect attempts when the
	// connection is lost.
	NoAutoReconnect bool

	ClientReconnectNeededTower *UHPTower
}

SshegoConfig is the top level, main config

func GenTestConfig added in v1.5.7

func GenTestConfig() (c *SshegoConfig, releasePorts func())

func NewSshegoConfig

func NewSshegoConfig() *SshegoConfig

func (*SshegoConfig) ChannelHandlerSummary added in v1.8.0

func (cfg *SshegoConfig) ChannelHandlerSummary() (s string)

func (*SshegoConfig) DefineFlags

func (c *SshegoConfig) DefineFlags(fs *flag.FlagSet)

DefineFlags should be called before myflags.Parse().

func (*SshegoConfig) GenAuthString

func (cfg *SshegoConfig) GenAuthString() string

func (*SshegoConfig) LoadConfig

func (c *SshegoConfig) LoadConfig(path string) error

LoadConfig reads configuration from a file, expecting KEY=value pair on each line; values optionally enclosed in double quotes.

func (*SshegoConfig) NewEsshd

func (cfg *SshegoConfig) NewEsshd() *Esshd

NewEsshd sets cfg.Esshd with a newly constructed Esshd. does NewHostDb() internally.

func (*SshegoConfig) NewHostDb

func (cfg *SshegoConfig) NewHostDb() error

func (*SshegoConfig) NewSSHClient added in v1.9.0

func (cfg *SshegoConfig) NewSSHClient(ctx context.Context, c ssh.Conn, chans <-chan ssh.NewChannel, reqs <-chan *ssh.Request, halt *ssh.Halter) *ssh.Client

derived from ssh.NewClient: NewSSHClient creates a Client on top of the given connection.

func (*SshegoConfig) NewTricorder

func (cfg *SshegoConfig) NewTricorder(halt *ssh.Halter, dc *DialConfig, sshClient *ssh.Client, sshChan net.Conn) (tri *Tricorder)

NewTricorder has got to wait to allocate ssh.Channel until requested. Otherwise we make too many, and get them mixed up.

func (*SshegoConfig) Reset

func (cfg *SshegoConfig) Reset()

func (*SshegoConfig) SSHConnect

func (cfg *SshegoConfig) SSHConnect(ctxPar context.Context, h *KnownHosts, username string, keypath string, sshdHost string, sshdPort int64, passphrase string, toptUrl string, halt *ssh.Halter) (*ssh.Client, net.Conn, error)

SSHConnect is the main entry point for the gosshtun library, establishing an ssh tunnel between two hosts.

passphrase and toptUrl (one-time password used in challenge/response) are optional, but will be offered to the server if set.

func (*SshegoConfig) SaveConfig

func (c *SshegoConfig) SaveConfig(fd io.Writer) error

SaveConfig writes the config structs to the given io.Writer

func (*SshegoConfig) StartNewReverse

func (cfg *SshegoConfig) StartNewReverse(sshClientConn *ssh.Client, fromRemote net.Conn) (*Reverse, error)

StartNewReverse is invoked once per reverse connection made to generate a new Reverse structure.

func (*SshegoConfig) StartupForwardListener

func (cfg *SshegoConfig) StartupForwardListener(ctx context.Context, sshClientConn *ssh.Client) error

StartupForwardListener is called when a forward tunnel is the be listened for.

func (*SshegoConfig) StartupReverseListener

func (cfg *SshegoConfig) StartupReverseListener(ctx context.Context, sshClientConn *ssh.Client) error

StartupReverseListener is called when a reverse tunnel is requested, to listen and tunnel those connections.

func (*SshegoConfig) TcpClientUserAdd

func (cfg *SshegoConfig) TcpClientUserAdd(user *User) (toptPath, qrPath, rsaPath string, err error)

func (*SshegoConfig) TcpClientUserDel

func (cfg *SshegoConfig) TcpClientUserDel(user *User) error

func (*SshegoConfig) ValidateConfig

func (c *SshegoConfig) ValidateConfig() error

ValidateConfig should be called after myflags.Parse().

type TOTP

type TOTP struct {
	UserEmail string
	Issuer    string
	Key       *otp.Key
	QRcodePng []byte
}

func NewTOTP

func NewTOTP(userEmail, issuer string) (w *TOTP, err error)

func (*TOTP) IsValid

func (w *TOTP) IsValid(passcode string, mylogin string) bool

func (*TOTP) LoadFromFile

func (w *TOTP) LoadFromFile(path string) error

func (*TOTP) SaveToFile

func (w *TOTP) SaveToFile(path string) (secretPath, qrPath string, err error)

func (*TOTP) String

func (w *TOTP) String() string

type TcpPort

type TcpPort struct {
	Port int
	Lsn  net.Listener
	// contains filtered or unexported fields
}

func (*TcpPort) Lock

func (t *TcpPort) Lock(limitMsec int) error

func (*TcpPort) Unlock

func (t *TcpPort) Unlock()

type TestSetup added in v1.5.7

type TestSetup struct {
	CliCfg  *SshegoConfig
	SrvCfg  *SshegoConfig
	Mylogin string
	RsaPath string
	Totp    string
	Pw      string
}

func MakeTestSshClientAndServer added in v1.5.7

func MakeTestSshClientAndServer(startEsshd bool) *TestSetup

type Tricorder

type Tricorder struct {

	// optional, parent can provide us
	// a Halter, and we will AddDownstream.
	ParentHalt *ssh.Halter

	// should only reflect close of the internal sshChannel, not cli nor nc.
	ChannelHalt *ssh.Halter
	// contains filtered or unexported fields
}

Tricorder records (holds) three key objects:

an *ssh.Client, the underlyign net.Conn, and a
set of ssh.Channel

Tricorder supports auto reconnect when disconnected.

func (*Tricorder) Cli

func (t *Tricorder) Cli() (cli *ssh.Client, err error)

func (*Tricorder) Nc

func (t *Tricorder) Nc() (nc io.Closer, err error)

func (*Tricorder) SSHChannel

func (t *Tricorder) SSHChannel(ctx context.Context, typ, destHostPort string) (net.Conn, error)

typ can be "direct-tcpip" (specify destHostPort), or "custom-inproc-stream" in which case leave destHostPort as the empty string.

type TunnelSpec

type TunnelSpec struct {
	Listen AddrHostPort
	Remote AddrHostPort
}

TunnelSpec represents either a forward or a reverse tunnel in SshegoConfig.

type UHP

type UHP struct {
	User     string
	HostPort string // IP:port or hostname:port
}

UHP provides User and HostPort strings to identify a remote destination.

type UHPTower

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

UHPTower is an 1:M non-blocking value-loadable channel.

Each subscriber gets their own private channel, and it will get a copy of whatever is sent to UHPTower.

Sends don't block, as subscribers are given buffered channels.

func NewUHPTower

func NewUHPTower(halt *ssh.Halter) *UHPTower

NewUHPTower makes a new UHPTower.

func (*UHPTower) Broadcast

func (b *UHPTower) Broadcast(val *UHP) error

Broadcast sends a copy of val to all subs. Any old unreceived values are purged from the receive queues before sending. Since the receivers are all buffered channels, Broadcast should never block waiting on a receiver.

Any subscriber who subscribes after the Broadcast will not receive the Broadcast value, as it is not stored internally.

func (*UHPTower) Clear

func (b *UHPTower) Clear()

func (*UHPTower) Close

func (b *UHPTower) Close() (err error)

func (*UHPTower) Signal

func (b *UHPTower) Signal(val *UHP) error

func (*UHPTower) Subscribe

func (b *UHPTower) Subscribe(notify chan *UHP) (ch chan *UHP)

Subscribe if given notify (notify is optional) will return notify and notify will receive all Broadcast values. If notify is nil, Subscribe will allocate a new channel and return that. When provided, notify should typically be a size 1 buffered chan. If other sizes of chan are used, be sure to service reads in a timely manner, or we will panic since Subscribe is meant to be non-blocking or minimally blocking for a very short time. Note that buffer size 1 channels are intended for lossy status: where if new status arrives before the old is read, it is desirable to discard the old and update to the new status value. To get non-lossy behavior, use an unbuffered notify or a buffer with size > 1. In both those cases, as above, you must arrange to service the channel promptly.

func (*UHPTower) Unsub

func (b *UHPTower) Unsub(x chan *UHP)

type User

type User struct {
	MyEmail    string
	MyFullname string
	MyLogin    string

	PublicKeyPath  string
	PrivateKeyPath string
	TOTPpath       string
	QrPath         string

	Issuer     string
	PublicKey  ssh.PublicKey `msg:"-"`
	SeenPubKey map[string]LoginRecord

	ScryptedPassword []byte
	ClearPw          string // only on network, never on disk.
	TOTPorig         string

	FirstLoginTime time.Time
	LastLoginTime  time.Time
	LastLoginAddr  string
	IPwhitelist    []string
	DisabledAcct   bool
	// contains filtered or unexported fields
}

User represents a user authorized to login to the embedded sshd.

func NewUser

func NewUser() *User

func (*User) DecodeMsg

func (z *User) DecodeMsg(dc *msgp.Reader) (err error)

DecodeMsg implements msgp.Decodable We treat empty fields as if we read a Nil from the wire.

func (*User) EncodeMsg

func (z *User) EncodeMsg(en *msgp.Writer) (err error)

EncodeMsg implements msgp.Encodable

func (*User) MarshalMsg

func (z *User) MarshalMsg(b []byte) (o []byte, err error)

MarshalMsg implements msgp.Marshaler

func (*User) MatchingHashAndPw

func (user *User) MatchingHashAndPw(password string) bool

func (*User) Msgsize

func (z *User) Msgsize() (s int)

Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message

func (*User) RestoreTotp

func (user *User) RestoreTotp()

func (*User) String added in v1.5.9

func (u *User) String() string

func (*User) UnmarshalMsg

func (z *User) UnmarshalMsg(bts []byte) (o []byte, err error)

UnmarshalMsg implements msgp.Unmarshaler

func (*User) UnmarshalMsgWithCfg added in v1.7.1

func (z *User) UnmarshalMsgWithCfg(bts []byte, cfg *msgp.RuntimeConfig) (o []byte, err error)

type Winsize

type Winsize struct {
	Height uint16
	Width  uint16
	// contains filtered or unexported fields
}

Winsize stores the Height and Width of a terminal.

Directories

Path Synopsis
_vendor
github.com/boombuler/barcode/qr
Package qr can be used to create QR barcodes.
Package qr can be used to create QR barcodes.
github.com/boombuler/barcode/utils
Package utils contain some utilities which are needed to create barcodes
Package utils contain some utilities which are needed to create barcodes
github.com/elithrar/simple-scrypt
Package scrypt provides a convenience wrapper around Go's existing scrypt package that makes it easier to securely derive strong keys from weak inputs (i.e.
Package scrypt provides a convenience wrapper around Go's existing scrypt package that makes it easier to securely derive strong keys from weak inputs (i.e.
github.com/glycerine/goconvey/convey
Oh the stack trace scanning! The density of comments in this file is evidence that the code doesn't exactly explain itself.
Oh the stack trace scanning! The density of comments in this file is evidence that the code doesn't exactly explain itself.
github.com/glycerine/goconvey/convey/assertions
Package assertions contains the implementations for all assertions which are referenced in the convey package for use with the So(...) method.
Package assertions contains the implementations for all assertions which are referenced in the convey package for use with the So(...) method.
github.com/glycerine/goconvey/convey/assertions/oglematchers
Package oglematchers provides a set of matchers useful in a testing or mocking framework.
Package oglematchers provides a set of matchers useful in a testing or mocking framework.
github.com/glycerine/goconvey/convey/gotest
Package gotest contains internal functionality.
Package gotest contains internal functionality.
github.com/glycerine/goconvey/convey/reporting
Package reporting contains internal functionality related to console reporting and output.
Package reporting contains internal functionality related to console reporting and output.
github.com/golang/snappy
Package snappy implements the snappy block-based compression format.
Package snappy implements the snappy block-based compression format.
github.com/gopherjs/gopherjs/js
Package js provides functions for interacting with native JavaScript APIs.
Package js provides functions for interacting with native JavaScript APIs.
github.com/jtolds/gls
Package gls implements goroutine-local storage.
Package gls implements goroutine-local storage.
github.com/kr/pty
Package pty provides functions for working with Unix terminals.
Package pty provides functions for working with Unix terminals.
github.com/mailgun/mailgun-go
The mailgun package provides methods for interacting with the Mailgun API.
The mailgun package provides methods for interacting with the Mailgun API.
github.com/philhofer/fwd
The `fwd` package provides a buffered reader and writer.
The `fwd` package provides a buffered reader and writer.
github.com/pquerna/otp
Package otp implements both HOTP and TOTP based one time passcodes in a Google Authenticator compatible manner.
Package otp implements both HOTP and TOTP based one time passcodes in a Google Authenticator compatible manner.
github.com/skratchdot/open-golang/open
Open a file, directory, or URI using the OS's default application for that object type.
Open a file, directory, or URI using the OS's default application for that object type.
github.com/tinylib/msgp/msgp
This package is the support library for the msgp code generator (http://github.com/tinylib/msgp).
This package is the support library for the msgp code generator (http://github.com/tinylib/msgp).
golang.org/x/crypto/acme
Package acme provides an implementation of the Automatic Certificate Management Environment (ACME) spec.
Package acme provides an implementation of the Automatic Certificate Management Environment (ACME) spec.
golang.org/x/crypto/acme/autocert
Package autocert provides automatic access to certificates from Let's Encrypt and any other ACME-based CA.
Package autocert provides automatic access to certificates from Let's Encrypt and any other ACME-based CA.
golang.org/x/crypto/bcrypt
Package bcrypt implements Provos and Mazières's bcrypt adaptive hashing algorithm.
Package bcrypt implements Provos and Mazières's bcrypt adaptive hashing algorithm.
golang.org/x/crypto/blake2b
Package blake2b implements the BLAKE2b hash algorithm as defined in RFC 7693.
Package blake2b implements the BLAKE2b hash algorithm as defined in RFC 7693.
golang.org/x/crypto/blake2s
Package blake2s implements the BLAKE2s hash algorithm as defined in RFC 7693.
Package blake2s implements the BLAKE2s hash algorithm as defined in RFC 7693.
golang.org/x/crypto/blowfish
Package blowfish implements Bruce Schneier's Blowfish encryption algorithm.
Package blowfish implements Bruce Schneier's Blowfish encryption algorithm.
golang.org/x/crypto/bn256
Package bn256 implements a particular bilinear group at the 128-bit security level.
Package bn256 implements a particular bilinear group at the 128-bit security level.
golang.org/x/crypto/cast5
Package cast5 implements CAST5, as defined in RFC 2144.
Package cast5 implements CAST5, as defined in RFC 2144.
golang.org/x/crypto/chacha20poly1305
Package chacha20poly1305 implements the ChaCha20-Poly1305 AEAD as specified in RFC 7539.
Package chacha20poly1305 implements the ChaCha20-Poly1305 AEAD as specified in RFC 7539.
golang.org/x/crypto/chacha20poly1305/internal/chacha20
Package ChaCha20 implements the core ChaCha20 function as specified in https://tools.ietf.org/html/rfc7539#section-2.3.
Package ChaCha20 implements the core ChaCha20 function as specified in https://tools.ietf.org/html/rfc7539#section-2.3.
golang.org/x/crypto/cryptobyte
Package cryptobyte implements building and parsing of byte strings for DER-encoded ASN.1 and TLS messages.
Package cryptobyte implements building and parsing of byte strings for DER-encoded ASN.1 and TLS messages.
golang.org/x/crypto/curve25519
Package curve25519 provides an implementation of scalar multiplication on the elliptic curve known as curve25519.
Package curve25519 provides an implementation of scalar multiplication on the elliptic curve known as curve25519.
golang.org/x/crypto/ed25519
Package ed25519 implements the Ed25519 signature algorithm.
Package ed25519 implements the Ed25519 signature algorithm.
golang.org/x/crypto/hkdf
Package hkdf implements the HMAC-based Extract-and-Expand Key Derivation Function (HKDF) as defined in RFC 5869.
Package hkdf implements the HMAC-based Extract-and-Expand Key Derivation Function (HKDF) as defined in RFC 5869.
golang.org/x/crypto/md4
Package md4 implements the MD4 hash algorithm as defined in RFC 1320.
Package md4 implements the MD4 hash algorithm as defined in RFC 1320.
golang.org/x/crypto/nacl/box
Package box authenticates and encrypts messages using public-key cryptography.
Package box authenticates and encrypts messages using public-key cryptography.
golang.org/x/crypto/nacl/secretbox
Package secretbox encrypts and authenticates small messages.
Package secretbox encrypts and authenticates small messages.
golang.org/x/crypto/ocsp
Package ocsp parses OCSP responses as specified in RFC 2560.
Package ocsp parses OCSP responses as specified in RFC 2560.
golang.org/x/crypto/openpgp
Package openpgp implements high level operations on OpenPGP messages.
Package openpgp implements high level operations on OpenPGP messages.
golang.org/x/crypto/openpgp/armor
Package armor implements OpenPGP ASCII Armor, see RFC 4880.
Package armor implements OpenPGP ASCII Armor, see RFC 4880.
golang.org/x/crypto/openpgp/clearsign
Package clearsign generates and processes OpenPGP, clear-signed data.
Package clearsign generates and processes OpenPGP, clear-signed data.
golang.org/x/crypto/openpgp/elgamal
Package elgamal implements ElGamal encryption, suitable for OpenPGP, as specified in "A Public-Key Cryptosystem and a Signature Scheme Based on Discrete Logarithms," IEEE Transactions on Information Theory, v.
Package elgamal implements ElGamal encryption, suitable for OpenPGP, as specified in "A Public-Key Cryptosystem and a Signature Scheme Based on Discrete Logarithms," IEEE Transactions on Information Theory, v.
golang.org/x/crypto/openpgp/errors
Package errors contains common error types for the OpenPGP packages.
Package errors contains common error types for the OpenPGP packages.
golang.org/x/crypto/openpgp/packet
Package packet implements parsing and serialization of OpenPGP packets, as specified in RFC 4880.
Package packet implements parsing and serialization of OpenPGP packets, as specified in RFC 4880.
golang.org/x/crypto/openpgp/s2k
Package s2k implements the various OpenPGP string-to-key transforms as specified in RFC 4800 section 3.7.1.
Package s2k implements the various OpenPGP string-to-key transforms as specified in RFC 4800 section 3.7.1.
golang.org/x/crypto/otr
Package otr implements the Off The Record protocol as specified in http://www.cypherpunks.ca/otr/Protocol-v2-3.1.0.html
Package otr implements the Off The Record protocol as specified in http://www.cypherpunks.ca/otr/Protocol-v2-3.1.0.html
golang.org/x/crypto/pbkdf2
Package pbkdf2 implements the key derivation function PBKDF2 as defined in RFC 2898 / PKCS #5 v2.0.
Package pbkdf2 implements the key derivation function PBKDF2 as defined in RFC 2898 / PKCS #5 v2.0.
golang.org/x/crypto/pkcs12
Package pkcs12 implements some of PKCS#12.
Package pkcs12 implements some of PKCS#12.
golang.org/x/crypto/pkcs12/internal/rc2
Package rc2 implements the RC2 cipher https://www.ietf.org/rfc/rfc2268.txt http://people.csail.mit.edu/rivest/pubs/KRRR98.pdf This code is licensed under the MIT license.
Package rc2 implements the RC2 cipher https://www.ietf.org/rfc/rfc2268.txt http://people.csail.mit.edu/rivest/pubs/KRRR98.pdf This code is licensed under the MIT license.
golang.org/x/crypto/poly1305
Package poly1305 implements Poly1305 one-time message authentication code as specified in http://cr.yp.to/mac/poly1305-20050329.pdf.
Package poly1305 implements Poly1305 one-time message authentication code as specified in http://cr.yp.to/mac/poly1305-20050329.pdf.
golang.org/x/crypto/ripemd160
Package ripemd160 implements the RIPEMD-160 hash algorithm.
Package ripemd160 implements the RIPEMD-160 hash algorithm.
golang.org/x/crypto/salsa20
Package salsa20 implements the Salsa20 stream cipher as specified in http://cr.yp.to/snuffle/spec.pdf.
Package salsa20 implements the Salsa20 stream cipher as specified in http://cr.yp.to/snuffle/spec.pdf.
golang.org/x/crypto/salsa20/salsa
Package salsa provides low-level access to functions in the Salsa family.
Package salsa provides low-level access to functions in the Salsa family.
golang.org/x/crypto/scrypt
Package scrypt implements the scrypt key derivation function as defined in Colin Percival's paper "Stronger Key Derivation via Sequential Memory-Hard Functions" (http://www.tarsnap.com/scrypt/scrypt.pdf).
Package scrypt implements the scrypt key derivation function as defined in Colin Percival's paper "Stronger Key Derivation via Sequential Memory-Hard Functions" (http://www.tarsnap.com/scrypt/scrypt.pdf).
golang.org/x/crypto/sha3
Package sha3 implements the SHA-3 fixed-output-length hash functions and the SHAKE variable-output-length hash functions defined by FIPS-202.
Package sha3 implements the SHA-3 fixed-output-length hash functions and the SHAKE variable-output-length hash functions defined by FIPS-202.
golang.org/x/crypto/ssh
Package ssh implements an SSH client and server.
Package ssh implements an SSH client and server.
golang.org/x/crypto/ssh/agent
Package agent implements the ssh-agent protocol, and provides both a client and a server.
Package agent implements the ssh-agent protocol, and provides both a client and a server.
golang.org/x/crypto/ssh/knownhosts
Package knownhosts implements a parser for the OpenSSH known_hosts host key database.
Package knownhosts implements a parser for the OpenSSH known_hosts host key database.
golang.org/x/crypto/ssh/terminal
Package terminal provides support functions for dealing with terminals, as commonly found on UNIX systems.
Package terminal provides support functions for dealing with terminals, as commonly found on UNIX systems.
golang.org/x/crypto/ssh/test
This package contains integration tests for the golang.org/x/crypto/ssh package.
This package contains integration tests for the golang.org/x/crypto/ssh package.
golang.org/x/crypto/twofish
Package twofish implements Bruce Schneier's Twofish encryption algorithm.
Package twofish implements Bruce Schneier's Twofish encryption algorithm.
golang.org/x/crypto/xtea
Package xtea implements XTEA encryption, as defined in Needham and Wheeler's 1997 technical report, "Tea extensions."
Package xtea implements XTEA encryption, as defined in Needham and Wheeler's 1997 technical report, "Tea extensions."
golang.org/x/crypto/xts
Package xts implements the XTS cipher mode as specified in IEEE P1619/D16.
Package xts implements the XTS cipher mode as specified in IEEE P1619/D16.
cmd
manual-test-client
a simple test client.
a simple test client.
manual-test-recv
a simple test receiver (server) to check that your direct-tcpip connections are coming through the sshd.
a simple test receiver (server) to check that your direct-tcpip connections are coming through the sshd.
manual-unixdomain-client
a simple test client.
a simple test client.
manual-unixdomain-recv
a simple test receiver (server) to check that your direct-tcpip connections are coming through the sshd.
a simple test receiver (server) to check that your direct-tcpip connections are coming through the sshd.
xendor
github.com/glycerine/xcryptossh
Package ssh implements an SSH client and server.
Package ssh implements an SSH client and server.
github.com/glycerine/xcryptossh/agent
Package agent implements the ssh-agent protocol, and provides both a client and a server.
Package agent implements the ssh-agent protocol, and provides both a client and a server.
github.com/glycerine/xcryptossh/knownhosts
Package knownhosts implements a parser for the OpenSSH known_hosts host key database.
Package knownhosts implements a parser for the OpenSSH known_hosts host key database.
github.com/glycerine/xcryptossh/terminal
Package terminal provides support functions for dealing with terminals, as commonly found on UNIX systems.
Package terminal provides support functions for dealing with terminals, as commonly found on UNIX systems.
github.com/glycerine/xcryptossh/test
This package contains integration tests for the github.com/glycerine/sshego/xendor/github.com/glycerine/xcryptossh package.
This package contains integration tests for the github.com/glycerine/sshego/xendor/github.com/glycerine/xcryptossh package.

Jump to

Keyboard shortcuts

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