sshlib

package module
v0.0.11-lw Latest Latest
Warning

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

Go to latest
Published: Feb 15, 2024 License: MIT Imports: 33 Imported by: 1

README

go-sshlib

GoDoc

About

A library to handle ssh easily with Golang.It can do multiple proxy, x11 forwarding, etc. Supported on Linux, macOS and Windows.

If use pkcs11 authentication, cgo must be enabled.

Usage

See GoDoc reference.

Download

GO111MODULE=on go get github.com/abakum/go-sshlib

Example

// Copyright (c) 2022 Blacknon. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.

// Shell connection Example file.
// Change the value of the variable and compile to make sure that you can actually connect.
//
// This file uses password authentication. Please replace as appropriate.

package main

import (
    "fmt"
    "os"

    sshlib "github.com/abakum/go-sshlib"
    "golang.org/x/crypto/ssh"
)

var (
    host     = "target.com"
    port     = "22"
    user     = "user"
    password = "password"

    termlog = "./test_termlog"
)

func main() {
    // Create sshlib.Connect
    con := &sshlib.Connect{
        // If you use x11 forwarding, please set to true.
        ForwardX11: false,

        // If you use ssh-agent forwarding, please set to true.
        // And after, run `con.ConnectSshAgent()`.
        ForwardAgent: false,
    }

    // Create ssh.AuthMethod
    authMethod := sshlib.CreateAuthMethodPassword(password)

    // If you use ssh-agent, uncomment it.
    // con.ConnectSshAgent()

    // Connect ssh server
    err := con.CreateClient(host, port, user, []ssh.AuthMethod{authMethod})
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }

    // Set terminal log
    con.SetLog(termlog, false)

    // Create Session
    session, err := con.CreateSession()
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }

    // Start ssh shell
    con.Shell(session)
}

Documentation

Overview

Package sshlib is a library to easily connect with ssh by go. You can perform multiple proxy, x11 forwarding, PKCS11 authentication, etc...

Example simple ssh shell

It is example code. simple connect ssh shell. You can also do tab completion, send sigint signal(Ctrl+C).

package main

import (
	"fmt"
	"os"

	sshlib "github.com/abakum/go-sshlib"
	"golang.org/x/crypto/ssh"
)

var (
	host     = "target.com"
	port     = "22"
	user     = "user"
	password = "password"

	termlog = "./test_termlog"
)

func main() {
	// Create sshlib.Connect
	con := &sshlib.Connect{
		// If you use x11 forwarding, please set to true.
		ForwardX11: false,

		// If you use ssh-agent forwarding, please set to true.
		// And after, run `con.ConnectSshAgent()`.
		ForwardAgent: false,
	}

	// Create ssh.AuthMethod
	authMethod := sshlib.CreateAuthMethodPassword(password)

	// If you use ssh-agent, uncomment it.
	// con.ConnectSshAgent()

	// Connect ssh server
	err := con.CreateClient(host, port, user, []ssh.AuthMethod{authMethod})
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// Set terminal log
	con.SetLog(termlog, false)

	// Start ssh shell
	con.Shell()
}

Example simple ssh proxy shell

Multple proxy by ssh connection is also available. Please refer to the sample code for usage with http and socks5 proxy.

package main

import (
	"fmt"
	"os"

	sshlib "github.com/abakum/go-sshlib"
	"golang.org/x/crypto/ssh"
)

var (
	// Proxy ssh server
	host1     = "proxy.com"
	port1     = "22"
	user1     = "user"
	password1 = "password"

	// Target ssh server
	host2     = "target.com"
	port2     = "22"
	user2     = "user"
	password2 = "password"

	termlog = "./test_termlog"
)

func main() {
	// ==========
	// proxy connect
	// ==========

	// Create proxy sshlib.Connect
	proxyCon := &sshlib.Connect{}

	// Create proxy ssh.AuthMethod
	proxyAuthMethod := sshlib.CreateAuthMethodPassword(password1)

	// Connect proxy server
	err := proxyCon.CreateClient(host1, port1, user1, []ssh.AuthMethod{proxyAuthMethod})
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// ==========
	// target connect
	// ==========

	// Create target sshlib.Connect
	targetCon := &sshlib.Connect{
		ProxyDialer: proxyCon.Client,
	}

	// Create target ssh.AuthMethod
	targetAuthMethod := sshlib.CreateAuthMethodPassword(password2)

	// Connect target server
	err = targetCon.CreateClient(host2, port2, user2, []ssh.AuthMethod{targetAuthMethod})
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// Set terminal log
	targetCon.SetLog(termlog, false)

	// Start ssh shell
	targetCon.Shell()
}

This library was created for my ssh client (https://github.com/blacknon/lssh)

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func CreateAuthMethodCertificate

func CreateAuthMethodCertificate(cert string, keySigner ssh.Signer) (auth ssh.AuthMethod, err error)

CreateAuthMethodCertificate returns ssh.AuthMethod generated from Certificate. To generate an AuthMethod from a certificate, you will need the certificate's private key Signer. Signer should be generated from CreateSignerPublicKey() or CreateSignerPKCS11().

func CreateAuthMethodPKCS11

func CreateAuthMethodPKCS11(provider, pin string) (auth []ssh.AuthMethod, err error)

CreateAuthMethodPKCS11 return []ssh.AuthMethod generated from pkcs11 token. PIN is required to generate a AuthMethod from a PKCS 11 token. Not available if cgo is disabled.

WORNING: Does not work if multiple tokens are stuck at the same time.

func CreateAuthMethodPassword

func CreateAuthMethodPassword(password string) (auth ssh.AuthMethod)

CreateAuthMethodPassword returns ssh.AuthMethod generated from password.

func CreateAuthMethodPublicKey

func CreateAuthMethodPublicKey(key, password string) (auth ssh.AuthMethod, err error)

CreateAuthMethodPublicKey returns ssh.AuthMethod generated from PublicKey. If you have not specified a passphrase, please specify a empty character("").

func CreateSignerAgent

func CreateSignerAgent(sshAgent interface{}) (signers []ssh.Signer, err error)

CreateSignerAgent return []ssh.Signer from ssh-agent. In sshAgent, put agent.Agent or agent.ExtendedAgent.

func CreateSignerCertificate

func CreateSignerCertificate(cert string, keySigner ssh.Signer) (certSigner ssh.Signer, err error)

CreateSignerCertificate returns ssh.Signer generated from Certificate. To generate an AuthMethod from a certificate, you will need the certificate's private key Signer. Signer should be generated from CreateSignerPublicKey() or CreateSignerPKCS11().

func CreateSignerPKCS11

func CreateSignerPKCS11(provider, pin string) (signers []ssh.Signer, err error)

CreateSignerPKCS11 returns []ssh.Signer generated from PKCS11 token. PIN is required to generate a Signer from a PKCS 11 token. Not available if cgo is disabled.

WORNING: Does not work if multiple tokens are stuck at the same time.

func CreateSignerPublicKey

func CreateSignerPublicKey(key, password string) (signer ssh.Signer, err error)

CreateSignerPublicKey returns []ssh.Signer generated from public key. If you have not specified a passphrase, please specify a empty character("").

func CreateSignerPublicKeyData

func CreateSignerPublicKeyData(keyData []byte, password string) (signer ssh.Signer, err error)

CreateSignerPublicKeyData return ssh.Signer from private key and password

func CreateSignerPublicKeyPrompt

func CreateSignerPublicKeyPrompt(key, password string) (signer ssh.Signer, err error)

CreateSignerPublicKeyPrompt wrapper CreateSignerPKCS11. Output a passphrase input prompt if the passphrase is not entered or incorrect.

Only Support UNIX-like OS.

func GetStdin

func GetStdin() io.ReadCloser

func HostKeyCallback

func HostKeyCallback(keys ...ssh.PublicKey) ssh.HostKeyCallback

HostKeyCallback returns a function for use in ClientConfig.HostKeyCallback to accept specific host keys.

func NewConn

func NewConn() (sock net.Conn, err error)

func RequestTty

func RequestTty(session *ssh.Session) (err error)

RequestTty requests the association of a pty with the session on the remote host. Terminal size is obtained from the currently connected terminal

Types

type AgentInterface

type AgentInterface interface{}

AgentInterface Interface for storing agent.Agent or agent.ExtendedAgent.

type C11

type C11 struct {
	Label string
	PIN   string
	Ctx   *crypto11.Context
}

C11 struct for Crypto11 processing. Not available if cgo is disabled.

func (*C11) CreateCtx

func (c *C11) CreateCtx(ctx *pkcs11.Ctx) (err error)

CreateCtx is create crypto11.Context Not available if cgo is disabled.

func (*C11) GetSigner

func (c *C11) GetSigner() (signer []crypto11.Signer, err error)

GetSigner return []crypto11.Signer. Not available if cgo is disabled.

type Connect

type Connect struct {
	// Client *ssh.Client
	Client *ssh.Client

	// Session
	Session *ssh.Session

	// Session Stdin, Stdout, Stderr...
	Stdin  io.Reader
	Stdout io.Writer
	Stderr io.Writer

	// ProxyDialer
	ProxyDialer proxy.Dialer

	// Connect timeout second.
	ConnectTimeout int

	// SendKeepAliveMax and SendKeepAliveInterval
	SendKeepAliveMax      int
	SendKeepAliveInterval int

	// Session use tty flag.
	TTY bool

	// Forward ssh agent flag.
	ForwardAgent bool

	// CheckKnownHosts if true, check knownhosts.
	CheckKnownHosts bool

	// OverwriteKnownHosts if true, if the knownhost is different, check whether to overwrite.
	OverwriteKnownHosts bool

	// KnownHostsFiles is list of knownhosts files path.
	KnownHostsFiles []string

	// TextAskWriteKnownHosts defines a confirmation message when writing a knownhost.
	// We are using Go's template engine and have the following variables available.
	// - Address ... ssh server hostname
	// - RemoteAddr ... ssh server address
	// - Fingerprint ... ssh PublicKey fingerprint
	TextAskWriteKnownHosts string

	// TextAskOverwriteKnownHosts defines a confirmation message when over-writing a knownhost.
	// We are using Go's template engine and have the following variables available.
	// - Address ... ssh server hostname
	// - RemoteAddr ... ssh server address
	// - OldKeyText ... old ssh PublicKey text.
	//                  ex: /home/user/.ssh/known_hosts:17: ecdsa-sha2-nistp256 AAAAE2VjZHN...bJklasnFtkFSDyOjTFSv2g=
	// - NewFingerprint ... new ssh PublicKey fingerprint
	TextAskOverwriteKnownHosts string

	// ssh-agent interface.
	// agent.Agent or agent.ExtendedAgent
	Agent AgentInterface

	// Forward x11 flag.
	ForwardX11 bool

	// Version contains the version identification string that will
	// be used for the connection. If empty, a reasonable default is used.
	Version string

	// HostKeyCallback is the function type used for verifying server keys.
	// A HostKeyCallback must return nil if the host key is OK, or an error to reject it.
	// It receives the hostname as passed to Dial or NewClientConn.
	// The remote address is the RemoteAddr of the net.Conn underlying the SSH connection.
	HostKeyCallback ssh.HostKeyCallback
	// contains filtered or unexported fields
}

Connect structure to store contents about ssh connection.

func (*Connect) AddKeySshAgent

func (c *Connect) AddKeySshAgent(sshAgent interface{}, key interface{})

AddKeySshAgent is wrapper agent.Add(). key must be a *rsa.PrivateKey, *dsa.PrivateKey or *ecdsa.PrivateKey, which will be inserted into the agent.

Should use `ssh.ParseRawPrivateKey()` or `ssh.ParseRawPrivateKeyWithPassphrase()`.

func (*Connect) CheckClientAlive

func (c *Connect) CheckClientAlive() error

CheckClientAlive check alive ssh.Client.

func (*Connect) CmdShell

func (c *Connect) CmdShell(session *ssh.Session, command string) (err error)

Shell connect command shell over ssh. Used to start a shell with a specified command. If session is nil then session will be created.

func (*Connect) Command

func (c *Connect) Command(command string) (err error)

Command connect and run command over ssh. Output data is processed by channel because it is executed in parallel. If specification is troublesome, it is good to generate and process session from ssh package.

func (*Connect) CommandAnsi

func (c *Connect) CommandAnsi(command string, emulate, fixOpenSSH bool) (err error)

CommandAnsi connect and run command over ssh for Windows without VTP.

Output data is processed by channel because it is executed in parallel. If specification is troublesome, it is good to generate and process session from ssh package.

func (*Connect) ConnectSshAgent

func (c *Connect) ConnectSshAgent()

func (*Connect) CreateAuthMethodAgent

func (c *Connect) CreateAuthMethodAgent() (auth ssh.AuthMethod)

CreateAuthMethodAgent returns ssh.AuthMethod from ssh-agent. case c.Agent is nil then ConnectSshAgent to it

func (*Connect) CreateClient

func (c *Connect) CreateClient(host, port, user string, authMethods []ssh.AuthMethod) (err error)

CreateClient set c.Client.

func (*Connect) CreateSession

func (c *Connect) CreateSession() (session *ssh.Session, err error)

CreateSession retrun ssh.Session

func (*Connect) ForwardSshAgent

func (c *Connect) ForwardSshAgent(session *ssh.Session)

ForwardAgent forward ssh-agent in session.

func (*Connect) Output

func (c *Connect) Output(cmd string, pty bool) (bs []byte, err error)

Output runs cmd on the remote host and returns its standard output.

func (*Connect) SendKeepAlive

func (c *Connect) SendKeepAlive(session *ssh.Session)

SendKeepAlive send packet to session. TODO(blacknon): Interval及びMaxを設定できるようにする(v0.1.1)

func (*Connect) SetLog

func (c *Connect) SetLog(path string, timestamp bool)

SetLog set up terminal log logging. This only happens in Connect.Shell().

func (*Connect) SetLogWithRemoveAnsiCode

func (c *Connect) SetLogWithRemoveAnsiCode(path string, timestamp bool)

func (*Connect) Shell

func (c *Connect) Shell(session *ssh.Session) (err error)

Shell connect login shell over ssh. If session is nil then session will be created.

func (*Connect) ShellAnsi

func (c *Connect) ShellAnsi(session *ssh.Session, emulate bool) (err error)

ShellAnsi connect login shell over ssh for Windows without VTP If session is nil then session will be created.

func (*Connect) TCPDynamicForward

func (c *Connect) TCPDynamicForward(address, port string) (err error)

TCPDynamicForward forwarding tcp data. Like Dynamic forward (`ssh -D <port>`). listen port Socks5 proxy server.

func (*Connect) TCPLocalForward

func (c *Connect) TCPLocalForward(localAddr, remoteAddr string) (err error)

TCPLocalForward forwarding tcp data. Like Local port forward (ssh -L). localAddr, remoteAddr is write as "address:port".

example) "127.0.0.1:22", "abc.com:9977"

Example
// host
host := "target.com"
port := "22"
user := "user"
key := "~/.ssh/id_rsa"

// port forwarding
localAddr := "localhost:10022"
remoteAddr := "localhost:22"

// Create ssh.AuthMethod
authMethod, _ := CreateAuthMethodPublicKey(key, "")

// Create sshlib.Connect
con := &Connect{}

// PortForward
con.TCPLocalForward(localAddr, remoteAddr)

// Connect ssh server
con.CreateClient(host, user, port, []ssh.AuthMethod{authMethod})
Output:

func (*Connect) TCPRemoteForward

func (c *Connect) TCPRemoteForward(localAddr, remoteAddr string) (err error)

TCPRemoteForward forwarding tcp data. Like Remote port forward (ssh -R). localAddr, remoteAddr is write as "address:port".

example) "127.0.0.1:22", "abc.com:9977"

func (*Connect) TCPReverseDynamicForward

func (c *Connect) TCPReverseDynamicForward(address, port string) (err error)

TCPReverseDynamicForward reverse forwarding tcp data. Like Openssh Reverse Dynamic forward (`ssh -R <port>`).

func (*Connect) X11Forward

func (c *Connect) X11Forward(session *ssh.Session) (err error)

X11Forward send x11-req to ssh server and do x11 forwarding. Since the display number of the transfer destination and the PATH of the socket communication file are checked from the local environmsdent variable DISPLAY, this does not work if it is not set.

Also, the value of COOKIE transfers the local value as it is. This will be addressed in the future.

Example
// Create session
con := &Connect{}
session, err := con.CreateSession()
if err != nil {
	return
}

// X11 forwarding
err = con.X11Forward(session)
if err != nil {
	log.Fatal(err)
}
Output:

type NetPipe

type NetPipe struct {
	Command string
}

func (*NetPipe) Dial

func (n *NetPipe) Dial(network, addr string) (con net.Conn, err error)

type OverwriteInventory

type OverwriteInventory struct {
	Address     string
	RemoteAddr  string
	Fingerprint string
	OldKeyText  string
}

type Proxy

type Proxy struct {
	// Type set proxy type.
	// Can specify `http`, `https`, `socks`, `socks5`, `command`.
	//
	// It is read at the time of specification depending on the type.
	Type string

	// Addr set proxy address.
	//
	Addr string

	// Port set proxy port.
	//
	Port string

	// Port set proxy user.
	//
	User string

	// Port set proxy user.
	//
	Password string

	// Command only use Type `command`.
	//
	Command string

	// Forwarder set Dialer.
	Forwarder proxy.Dialer
}

func (*Proxy) CreateHttpProxyDialer

func (p *Proxy) CreateHttpProxyDialer() (proxyDialer proxy.Dialer, err error)

CreateHttpProxy return proxy.Dialer as http proxy.

func (*Proxy) CreateProxyCommandProxyDialer

func (p *Proxy) CreateProxyCommandProxyDialer() (proxyDialer proxy.Dialer, err error)

CreateProxyCommandProxyDialer as ProxyCommand. When passing ProxyCommand, replace %h, %p and %r etc...

func (*Proxy) CreateProxyDialer

func (p *Proxy) CreateProxyDialer() (proxyDialer proxy.Dialer, err error)

CreateProxyDialer retrun proxy.Dialer.

func (*Proxy) CreateSocks5ProxyDialer

func (p *Proxy) CreateSocks5ProxyDialer() (proxyDialer proxy.Dialer, err error)

CreateSocks5Proxy return proxy.Dialer as Socks5 proxy.

type WriteInventory

type WriteInventory struct {
	Address     string
	RemoteAddr  string
	Fingerprint string
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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