github.phpd.cn/hashicorp/packer@v1.3.2/communicator/ssh/connect.go (about)

     1  package ssh
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"time"
     7  
     8  	"golang.org/x/crypto/ssh"
     9  	"golang.org/x/net/proxy"
    10  )
    11  
    12  // ConnectFunc is a convenience method for returning a function
    13  // that just uses net.Dial to communicate with the remote end that
    14  // is suitable for use with the SSH communicator configuration.
    15  func ConnectFunc(network, addr string) func() (net.Conn, error) {
    16  	return func() (net.Conn, error) {
    17  		c, err := net.DialTimeout(network, addr, 15*time.Second)
    18  		if err != nil {
    19  			return nil, err
    20  		}
    21  
    22  		if tcpConn, ok := c.(*net.TCPConn); ok {
    23  			tcpConn.SetKeepAlive(true)
    24  			tcpConn.SetKeepAlivePeriod(5 * time.Second)
    25  		}
    26  
    27  		return c, nil
    28  	}
    29  }
    30  
    31  // ProxyConnectFunc is a convenience method for returning a function
    32  // that connects to a host using SOCKS5 proxy
    33  func ProxyConnectFunc(socksProxy string, socksAuth *proxy.Auth, network, addr string) func() (net.Conn, error) {
    34  	return func() (net.Conn, error) {
    35  		// create a socks5 dialer
    36  		dialer, err := proxy.SOCKS5("tcp", socksProxy, socksAuth, proxy.Direct)
    37  		if err != nil {
    38  			return nil, fmt.Errorf("Can't connect to the proxy: %s", err)
    39  		}
    40  
    41  		c, err := dialer.Dial(network, addr)
    42  		if err != nil {
    43  			return nil, err
    44  		}
    45  
    46  		return c, nil
    47  	}
    48  }
    49  
    50  // BastionConnectFunc is a convenience method for returning a function
    51  // that connects to a host over a bastion connection.
    52  func BastionConnectFunc(
    53  	bProto string,
    54  	bAddr string,
    55  	bConf *ssh.ClientConfig,
    56  	proto string,
    57  	addr string) func() (net.Conn, error) {
    58  	return func() (net.Conn, error) {
    59  		// Connect to the bastion
    60  		bastion, err := ssh.Dial(bProto, bAddr, bConf)
    61  		if err != nil {
    62  			return nil, fmt.Errorf("Error connecting to bastion: %s", err)
    63  		}
    64  
    65  		// Connect through to the end host
    66  		conn, err := bastion.Dial(proto, addr)
    67  		if err != nil {
    68  			bastion.Close()
    69  			return nil, err
    70  		}
    71  
    72  		// Wrap it up so we close both things properly
    73  		return &bastionConn{
    74  			Conn:    conn,
    75  			Bastion: bastion,
    76  		}, nil
    77  	}
    78  }
    79  
    80  type bastionConn struct {
    81  	net.Conn
    82  	Bastion *ssh.Client
    83  }
    84  
    85  func (c *bastionConn) Close() error {
    86  	c.Conn.Close()
    87  	return c.Bastion.Close()
    88  }