SOCKS5 proxy support
This commit is contained in:
parent
c85cf0483a
commit
d9b404fa00
|
@ -6,6 +6,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
|
"golang.org/x/net/proxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConnectFunc is a convenience method for returning a function
|
// ConnectFunc is a convenience method for returning a function
|
||||||
|
@ -27,6 +28,25 @@ func ConnectFunc(network, addr string) func() (net.Conn, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConnectFunc is a convenience method for returning a function
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// BastionConnectFunc is a convenience method for returning a function
|
// BastionConnectFunc is a convenience method for returning a function
|
||||||
// that connects to a host over a bastion connection.
|
// that connects to a host over a bastion connection.
|
||||||
func BastionConnectFunc(
|
func BastionConnectFunc(
|
||||||
|
|
|
@ -33,6 +33,10 @@ type Config struct {
|
||||||
SSHBastionPassword string `mapstructure:"ssh_bastion_password"`
|
SSHBastionPassword string `mapstructure:"ssh_bastion_password"`
|
||||||
SSHBastionPrivateKey string `mapstructure:"ssh_bastion_private_key_file"`
|
SSHBastionPrivateKey string `mapstructure:"ssh_bastion_private_key_file"`
|
||||||
SSHFileTransferMethod string `mapstructure:"ssh_file_transfer_method"`
|
SSHFileTransferMethod string `mapstructure:"ssh_file_transfer_method"`
|
||||||
|
SSHProxyHost string `mapstructure:"ssh_proxy_host"`
|
||||||
|
SSHProxyPort int `mapstructure:"ssh_proxy_port"`
|
||||||
|
SSHProxyUsername string `mapstructure:"ssh_proxy_username"`
|
||||||
|
SSHProxyPassword string `mapstructure:"ssh_proxy_password"`
|
||||||
|
|
||||||
// WinRM
|
// WinRM
|
||||||
WinRMUser string `mapstructure:"winrm_username"`
|
WinRMUser string `mapstructure:"winrm_username"`
|
||||||
|
@ -141,6 +145,12 @@ func (c *Config) prepareSSH(ctx *interpolate.Context) []error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.SSHProxyHost != "" {
|
||||||
|
if c.SSHProxyPort == 0 {
|
||||||
|
c.SSHProxyPort = 1080
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if c.SSHFileTransferMethod == "" {
|
if c.SSHFileTransferMethod == "" {
|
||||||
c.SSHFileTransferMethod = "scp"
|
c.SSHFileTransferMethod = "scp"
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
gossh "golang.org/x/crypto/ssh"
|
gossh "golang.org/x/crypto/ssh"
|
||||||
"golang.org/x/crypto/ssh/agent"
|
"golang.org/x/crypto/ssh/agent"
|
||||||
|
"golang.org/x/net/proxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StepConnectSSH is a step that only connects to SSH.
|
// StepConnectSSH is a step that only connects to SSH.
|
||||||
|
@ -88,6 +89,8 @@ func (s *StepConnectSSH) waitForSSH(state multistep.StateBag, cancel <-chan stru
|
||||||
// do this one before entering the retry loop.
|
// do this one before entering the retry loop.
|
||||||
var bProto, bAddr string
|
var bProto, bAddr string
|
||||||
var bConf *gossh.ClientConfig
|
var bConf *gossh.ClientConfig
|
||||||
|
var pAddr string
|
||||||
|
var pAuth *proxy.Auth
|
||||||
if s.Config.SSHBastionHost != "" {
|
if s.Config.SSHBastionHost != "" {
|
||||||
// The protocol is hardcoded for now, but may be configurable one day
|
// The protocol is hardcoded for now, but may be configurable one day
|
||||||
bProto = "tcp"
|
bProto = "tcp"
|
||||||
|
@ -101,6 +104,16 @@ func (s *StepConnectSSH) waitForSSH(state multistep.StateBag, cancel <-chan stru
|
||||||
bConf = conf
|
bConf = conf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.Config.SSHProxyHost != "" {
|
||||||
|
pAddr = fmt.Sprintf("%s:%d", s.Config.SSHProxyHost, s.Config.SSHProxyPort)
|
||||||
|
if s.Config.SSHProxyUsername != "" {
|
||||||
|
pAuth = new(proxy.Auth)
|
||||||
|
pAuth.User = s.Config.SSHBastionUsername
|
||||||
|
pAuth.Password = s.Config.SSHBastionPassword
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
handshakeAttempts := 0
|
handshakeAttempts := 0
|
||||||
|
|
||||||
var comm packer.Communicator
|
var comm packer.Communicator
|
||||||
|
@ -146,6 +159,9 @@ func (s *StepConnectSSH) waitForSSH(state multistep.StateBag, cancel <-chan stru
|
||||||
// We're using a bastion host, so use the bastion connfunc
|
// We're using a bastion host, so use the bastion connfunc
|
||||||
connFunc = ssh.BastionConnectFunc(
|
connFunc = ssh.BastionConnectFunc(
|
||||||
bProto, bAddr, bConf, "tcp", address)
|
bProto, bAddr, bConf, "tcp", address)
|
||||||
|
} else if pAddr != "" {
|
||||||
|
// Connect via SOCKS5 proxy
|
||||||
|
connFunc = ssh.ProxyConnectFunc(pAddr, pAuth, "tcp", address)
|
||||||
} else {
|
} else {
|
||||||
// No bastion host, connect directly
|
// No bastion host, connect directly
|
||||||
connFunc = ssh.ConnectFunc("tcp", address)
|
connFunc = ssh.ConnectFunc("tcp", address)
|
||||||
|
|
Loading…
Reference in New Issue