2013-07-14 20:22:41 +09:00
|
|
|
package ssh
|
|
|
|
|
|
|
|
import (
|
2015-06-17 22:10:42 +02:00
|
|
|
"fmt"
|
2013-07-14 20:22:41 +09:00
|
|
|
"net"
|
2013-07-14 20:31:51 +09:00
|
|
|
"time"
|
2015-06-17 22:10:42 +02:00
|
|
|
|
|
|
|
"golang.org/x/crypto/ssh"
|
2017-10-10 15:04:15 +01:00
|
|
|
"golang.org/x/net/proxy"
|
2013-07-14 20:22:41 +09:00
|
|
|
)
|
|
|
|
|
|
|
|
// ConnectFunc is a convenience method for returning a function
|
|
|
|
// that just uses net.Dial to communicate with the remote end that
|
|
|
|
// is suitable for use with the SSH communicator configuration.
|
2013-08-22 11:53:31 -07:00
|
|
|
func ConnectFunc(network, addr string) func() (net.Conn, error) {
|
2013-07-14 20:22:41 +09:00
|
|
|
return func() (net.Conn, error) {
|
2014-02-21 14:45:40 -08:00
|
|
|
c, err := net.DialTimeout(network, addr, 15*time.Second)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if tcpConn, ok := c.(*net.TCPConn); ok {
|
|
|
|
tcpConn.SetKeepAlive(true)
|
2014-09-04 11:24:01 -07:00
|
|
|
tcpConn.SetKeepAlivePeriod(5 * time.Second)
|
2014-02-21 14:45:40 -08:00
|
|
|
}
|
2014-02-21 14:51:33 -08:00
|
|
|
|
|
|
|
return c, nil
|
2013-07-14 20:22:41 +09:00
|
|
|
}
|
|
|
|
}
|
2015-06-17 22:10:42 +02:00
|
|
|
|
2018-03-23 12:54:33 +00:00
|
|
|
// ProxyConnectFunc is a convenience method for returning a function
|
2017-10-10 15:04:15 +01:00
|
|
|
// that connects to a host using SOCKS5 proxy
|
|
|
|
func ProxyConnectFunc(socksProxy string, socksAuth *proxy.Auth, network, addr string) func() (net.Conn, error) {
|
|
|
|
return func() (net.Conn, error) {
|
|
|
|
// create a socks5 dialer
|
|
|
|
dialer, err := proxy.SOCKS5("tcp", socksProxy, socksAuth, proxy.Direct)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("Can't connect to the proxy: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
c, err := dialer.Dial(network, addr)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return c, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-17 22:10:42 +02:00
|
|
|
// BastionConnectFunc is a convenience method for returning a function
|
|
|
|
// that connects to a host over a bastion connection.
|
|
|
|
func BastionConnectFunc(
|
|
|
|
bProto string,
|
|
|
|
bAddr string,
|
|
|
|
bConf *ssh.ClientConfig,
|
|
|
|
proto string,
|
|
|
|
addr string) func() (net.Conn, error) {
|
|
|
|
return func() (net.Conn, error) {
|
|
|
|
// Connect to the bastion
|
|
|
|
bastion, err := ssh.Dial(bProto, bAddr, bConf)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("Error connecting to bastion: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Connect through to the end host
|
|
|
|
conn, err := bastion.Dial(proto, addr)
|
|
|
|
if err != nil {
|
|
|
|
bastion.Close()
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wrap it up so we close both things properly
|
|
|
|
return &bastionConn{
|
|
|
|
Conn: conn,
|
|
|
|
Bastion: bastion,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type bastionConn struct {
|
|
|
|
net.Conn
|
|
|
|
Bastion *ssh.Client
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *bastionConn) Close() error {
|
|
|
|
c.Conn.Close()
|
|
|
|
return c.Bastion.Close()
|
|
|
|
}
|