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
In any case, you should realize that this is only an ssh client, and not an sshd server daemon. It is the equivalent to using the ssh client and giving `-L` and/or `-R`. 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
- Variables
- func AddUserAndExit(cfg *SshegoConfig)
- func CryptoRandBytes(n int) []byte
- func CryptoRandInt64() int64
- func CryptoRandNonNegInt(n int64) int64
- func DelUserAndExit(cfg *SshegoConfig)
- func DialRemoteUnixDomain(c *ssh.Client, udpath string) (net.Conn, error)
- func Fingerprint(k ssh.PublicKey) string
- func GenRSAKeyPair(rsaFile string, bits int, email string) (priv *rsa.PrivateKey, sshPriv ssh.Signer, err error)
- func GenRSAKeyPairCrypt(rsaFile string, bits int, password string) (priv *rsa.PrivateKey, sshPriv ssh.Signer, err error)
- func GetAvailPort() (net.Listener, int)
- func GetExternalIP() string
- func IsAlreadyBound(addr string) bool
- func IsRoutableIPv4(ip string) bool
- func KnownHostsEqual(a, b *KnownHosts) (bool, error)
- func LoadRSAPrivateKey(path string) (privkey ssh.Signer, err error)
- func LoadRSAPrivateKeyCrypt(path string, password string) (privkey ssh.Signer, err error)
- func LoadRSAPublicKey(path string) (pubkey ssh.PublicKey, err error)
- func MakeAndMoveToTempDir() (origdir string, tmpdir string)
- func PromptForPassword(username string) (pw string, err error)
- func RSAToSSHPublicKey(pubkey *rsa.PublicKey) []byte
- func RandomString(n int) string
- func ScryptHash(password string) []byte
- func SetWinsize(fd uintptr, w, h uint32)
- func SourceVersion() string
- func StartBackgroundTestTcpServer(serverDone chan bool, payloadByteCount int, confirmationPayload string, ...)
- func TempDirCleanup(origdir string, tmpdir string)
- func TestCreateNewAccount(srvCfg *SshegoConfig) (mylogin, toptPath, rsaPath, pw string, err error)
- func UnencPingPong(dest, confirmationPayload, confirmationReply string, payloadByteCount int)
- func VerifyClientServerExchangeAcrossSshd(channelToTcpServer net.Conn, confirmationPayload, confirmationReply string, ...)
- func WaitUntilAddrAvailable(addr string, dur time.Duration, tries int) int
- type AddrHostPort
- type AtomicUserMap
- func (z *AtomicUserMap) DecodeMsg(dc *msgp.Reader) (err error)
- func (m *AtomicUserMap) Del(key string)
- func (z *AtomicUserMap) EncodeMsg(en *msgp.Writer) (err error)
- func (m *AtomicUserMap) Get(key string) *User
- func (m *AtomicUserMap) Get2(key string) (*User, bool)
- func (z *AtomicUserMap) MarshalMsg(b []byte) (o []byte, err error)
- func (z *AtomicUserMap) Msgsize() (s int)
- func (m *AtomicUserMap) Set(key string, val *User)
- func (z *AtomicUserMap) UnmarshalMsg(bts []byte) (o []byte, err error)
- type AuthState
- type BasicAddress
- type BasicListener
- type BasicServer
- type CommandRecv
- type ConnectionAlert
- type DialConfig
- type Esshd
- type Forwarder
- type HostDb
- func (h *HostDb) AddUser(mylogin, myemail, pw, issuer, fullname string) (toptPath, qrPath, rsaPath string, err error)
- func (z *HostDb) DecodeMsg(dc *msgp.Reader) (err error)
- func (h *HostDb) DelUser(mylogin string) error
- func (z *HostDb) EncodeMsg(en *msgp.Writer) (err error)
- func (z *HostDb) MarshalMsg(b []byte) (o []byte, err error)
- func (z *HostDb) Msgsize() (s int)
- func (z *HostDb) UnmarshalMsg(bts []byte) (o []byte, err error)
- func (h *HostDb) UserExists(mylogin string) bool
- func (h *HostDb) ValidEmail(myemail string) (bool, error)
- func (h *HostDb) ValidLogin(login string) (bool, error)
- type HostState
- type KnownHosts
- func (h *KnownHosts) AddNeeded(addIfNotKnown, allowOneshotConnect bool, hostname string, remote net.Addr, ...) (HostState, *ServerPubKey, error)
- func (h *KnownHosts) Close()
- func (h *KnownHosts) HostAlreadyKnown(hostname string, remote net.Addr, key ssh.PublicKey, pubBytes []byte, ...) (HostState, *ServerPubKey, error)
- func (h *KnownHosts) Sync() (err error)
- type KnownHostsPersistFormat
- type LoginRecord
- func (z *LoginRecord) DecodeMsg(dc *msgp.Reader) (err error)
- func (z *LoginRecord) EncodeMsg(en *msgp.Writer) (err error)
- func (z *LoginRecord) MarshalMsg(b []byte) (o []byte, err error)
- func (z *LoginRecord) Msgsize() (s int)
- func (r LoginRecord) String() string
- func (z *LoginRecord) UnmarshalMsg(bts []byte) (o []byte, err error)
- type MailgunConfig
- func (c *MailgunConfig) DefineFlags(fs *flag.FlagSet)
- func (c *MailgunConfig) LoadConfig(path string) error
- func (c *MailgunConfig) SaveConfig(fd io.Writer) error
- func (c *MailgunConfig) SendEmail(senderEmail, subject, plain, html, recipEmail string) (string, error)
- func (c *MailgunConfig) ValidateConfig() error
- type PerAttempt
- func (a *PerAttempt) AuthLogCallback(conn ssh.ConnMetadata, method string, err error)
- func (a *PerAttempt) KeyboardInteractiveCallback(conn ssh.ConnMetadata, challenge ssh.KeyboardInteractiveChallenge) (*ssh.Permissions, error)
- func (a *PerAttempt) NoteLogin(user *User, now time.Time, conn ssh.ConnMetadata)
- func (a *PerAttempt) PerConnection(nConn net.Conn, ca *ConnectionAlert) error
- func (a *PerAttempt) PublicKeyCallback(c ssh.ConnMetadata, providedPubKey ssh.PublicKey) (perm *ssh.Permissions, rerr error)
- func (a *PerAttempt) SetTripleConfig()
- func (a *PerAttempt) SetupAuthRequirements()
- type Reverse
- type ServerPubKey
- type SshegoConfig
- func (c *SshegoConfig) DefineFlags(fs *flag.FlagSet)
- func (cfg *SshegoConfig) GenAuthString() string
- func (c *SshegoConfig) LoadConfig(path string) error
- func (cfg *SshegoConfig) NewEsshd() *Esshd
- func (cfg *SshegoConfig) NewHostDb() error
- func (cfg *SshegoConfig) SSHConnect(h *KnownHosts, username string, keypath string, sshdHost string, ...) (*ssh.Client, error)
- func (c *SshegoConfig) SaveConfig(fd io.Writer) error
- func (cfg *SshegoConfig) StartNewReverse(sshClientConn *ssh.Client, fromRemote net.Conn) (*Reverse, error)
- func (cfg *SshegoConfig) StartupForwardListener(sshClientConn *ssh.Client) error
- func (cfg *SshegoConfig) StartupReverseListener(sshClientConn *ssh.Client) error
- func (cfg *SshegoConfig) TcpClientUserAdd(user *User) (toptPath, qrPath, rsaPath string, err error)
- func (cfg *SshegoConfig) TcpClientUserDel(user *User) error
- func (c *SshegoConfig) ValidateConfig() error
- type TOTP
- type TcpPort
- type TestSetup
- type TunnelSpec
- type User
- func (z *User) DecodeMsg(dc *msgp.Reader) (err error)
- func (z *User) EncodeMsg(en *msgp.Writer) (err error)
- func (z *User) MarshalMsg(b []byte) (o []byte, err error)
- func (user *User) MatchingHashAndPw(password string) bool
- func (z *User) Msgsize() (s int)
- func (user *User) RestoreTotp()
- func (z *User) UnmarshalMsg(bts []byte) (o []byte, err error)
- type Winsize
Constants ¶
const MUX_C_OPEN_FWD = 0x10000006 // 268435462
const ProgramName = "sshego-library"
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 ¶
var DelUserCmd = []byte("01DELUSER___")
var DelUserCmdStr = string(DelUserCmd)
var DelUserReplyFailed = []byte("01REPLY_FAIL")
var DelUserReplyOK = []byte("01REPLY_OK__")
var ErrCouldNotAquirePort = fmt.Errorf("could not acquire " +
"our -xport before the deadline")
var GIT_BRANCH string
var GO_VERSION string
var LAST_GIT_COMMIT_HASH string
var NEAREST_GIT_TAG string
var NewUserCmd = []byte("00NEWUSER___")
var NewUserCmdStr = string(NewUserCmd)
var NewUserReply = []byte("00REPLY_____")
Functions ¶
func AddUserAndExit ¶ added in v1.5.7
func AddUserAndExit(cfg *SshegoConfig)
func CryptoRandBytes ¶
func CryptoRandNonNegInt ¶
func DelUserAndExit ¶ added in v1.5.7
func DelUserAndExit(cfg *SshegoConfig)
func DialRemoteUnixDomain ¶ added in v1.4.0
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 Fingerprint ¶
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
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 IsRoutableIPv4 ¶
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 ¶
LoadRSAPrivateKey reads a private key from path on disk.
func LoadRSAPrivateKeyCrypt ¶
TODO: Finish this-- specified but password based encryption not implemented. LoadRSAPrivateKey reads a private key from path on disk.
func LoadRSAPublicKey ¶
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 PromptForPassword ¶
PromptForPassword ask
func RSAToSSHPublicKey ¶
RSAToSSHPublicKey convert an RSA Public Key to the SSH authorized_keys format.
func RandomString ¶ added in v1.4.0
func ScryptHash ¶
func SetWinsize ¶
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 TempDirCleanup ¶ added in v1.5.7
func TestCreateNewAccount ¶ added in v1.5.7
func TestCreateNewAccount(srvCfg *SshegoConfig) (mylogin, toptPath, rsaPath, pw string, err error)
func UnencPingPong ¶ added in v1.5.7
func VerifyClientServerExchangeAcrossSshd ¶ added in v1.5.7
func WaitUntilAddrAvailable ¶ added in v1.5.7
waitUntilAddrAvailable returns -1 if the addr was alays 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 ¶
func NewAtomicUserMap ¶
func NewAtomicUserMap() *AtomicUserMap
func (*AtomicUserMap) DecodeMsg ¶
func (z *AtomicUserMap) DecodeMsg(dc *msgp.Reader) (err error)
DecodeMsg implements msgp.Decodable
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) 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) UnmarshalMsg ¶
func (z *AtomicUserMap) UnmarshalMsg(bts []byte) (o []byte, err error)
UnmarshalMsg implements msgp.Unmarshaler
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 (*AuthState) LoadHostKey ¶
func (*AuthState) LoadPublicKeys ¶
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() (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 closes bind to the port that the server has.
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() error
type ConnectionAlert ¶ added in v1.5.5
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 }
DialConfig provides Dial() with what it needs in order to establish an encrypted and authenticated ssh connection.
func (*DialConfig) Dial ¶
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.
type Esshd ¶
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
type Forwarder ¶
type Forwarder struct {
// contains filtered or unexported fields
}
Forwarder represents one bi-directional forward (sshego to sshd) tcp connection.
func NewForward ¶
NewForward is called to produce a Forwarder structure for each new forward connection.
type HostDb ¶
type HostDb struct { // Users: key is MyLogin; value is *User. Users *AtomicUserMap HostPrivateKeyPath string // contains filtered or unexported fields }
func (*HostDb) MarshalMsg ¶
MarshalMsg implements msgp.Marshaler
func (*HostDb) Msgsize ¶
Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (*HostDb) UnmarshalMsg ¶
UnmarshalMsg implements msgp.Unmarshaler
func (*HostDb) UserExists ¶
UserExists is used by sshego/cmd/gosshtun/main.go
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.
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 // 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
const ( KHJson KnownHostsPersistFormat = 0 KHGob KnownHostsPersistFormat = 1 KHSsh KnownHostsPersistFormat = 2 )
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
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
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(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(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 // 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 { ConfigPath string SSHdServer AddrHostPort // the sshd host we are logging into remotely. LocalToRemote TunnelSpec RemoteToLocal TunnelSpec Debug bool AddIfNotKnown bool Username string PrivateKeyPath string ClientKnownHostsPath string 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 TestingModeNoWait bool Mut sync.Mutex }
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) 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) SSHConnect ¶
func (cfg *SshegoConfig) SSHConnect(h *KnownHosts, username string, keypath string, sshdHost string, sshdPort int64, passphrase string, toptUrl string) (*ssh.Client, 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(sshClientConn *ssh.Client) error
StartupForwardListener is called when a forward tunnel is the be listened for.
func (*SshegoConfig) StartupReverseListener ¶
func (cfg *SshegoConfig) StartupReverseListener(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 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
type TunnelSpec ¶
type TunnelSpec struct { Listen AddrHostPort Remote AddrHostPort }
TunnelSpec represents either a forward or a reverse tunnel in SshegoConfig.
type User ¶
type User struct { MyEmail string MyFullname string MyLogin string PublicKeyPath string PrivateKeyPath string TOTPpath string QrPath string Issuer string 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 (*User) MarshalMsg ¶
MarshalMsg implements msgp.Marshaler
func (*User) MatchingHashAndPw ¶
func (*User) Msgsize ¶
Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (*User) RestoreTotp ¶
func (user *User) RestoreTotp()
Source Files ¶
- amap.go
- amap_gen.go
- boltdb.go
- cli.go
- config.go
- cryrand.go
- direct.go
- doc.go
- exists.go
- flock.go
- ipaddr.go
- knownhosts.go
- listen.go
- mailgun.go
- netcli.go
- panic_on_err.go
- pergob.go
- perjson.go
- prompt.go
- pty.go
- rsa.go
- rsacrypt.go
- server.go
- shovel.go
- sshutil.go
- tcplock.go
- testutil.go
- ud.go
- user.go
- user_gen.go
- usermgt.go
- verbose.go
- version.go
Directories ¶
Path | Synopsis |
---|---|
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. |