aboutsummaryrefslogtreecommitdiffstats
path: root/plumbing
diff options
context:
space:
mode:
authorJacob Blain Christen <dweomer5@gmail.com>2019-05-02 12:41:43 -0700
committerJacob Blain Christen <dweomer5@gmail.com>2019-05-02 12:41:43 -0700
commitbbc05c7e371c19c3d85bf394b24061096a2b9a25 (patch)
treeb40fd1e6e332badd11b327512f78765c0ba3fc54 /plumbing
parentf22c6b9dd07d6f4f2d578250c65b4572916488f9 (diff)
downloadgo-git-bbc05c7e371c19c3d85bf394b24061096a2b9a25.tar.gz
ssh: leverage proxy.Dial
This enables interacting with git remotes over SSH when behind a SOCKSv5 firewall. Signed-off-by: Jacob Blain Christen <dweomer5@gmail.com>
Diffstat (limited to 'plumbing')
-rw-r--r--plumbing/transport/ssh/common.go27
-rw-r--r--plumbing/transport/ssh/proxy_test.go36
2 files changed, 62 insertions, 1 deletions
diff --git a/plumbing/transport/ssh/common.go b/plumbing/transport/ssh/common.go
index e4a3d18..d320d43 100644
--- a/plumbing/transport/ssh/common.go
+++ b/plumbing/transport/ssh/common.go
@@ -2,6 +2,7 @@
package ssh
import (
+ "context"
"fmt"
"reflect"
"strconv"
@@ -11,6 +12,7 @@ import (
"github.com/kevinburke/ssh_config"
"golang.org/x/crypto/ssh"
+ "golang.org/x/net/proxy"
)
// DefaultClient is the default SSH client.
@@ -115,7 +117,7 @@ func (c *command) connect() error {
overrideConfig(c.config, config)
- c.client, err = ssh.Dial("tcp", c.getHostWithPort(), config)
+ c.client, err = dial("tcp", c.getHostWithPort(), config)
if err != nil {
return err
}
@@ -130,6 +132,29 @@ func (c *command) connect() error {
return nil
}
+func dial(network, addr string, config *ssh.ClientConfig) (*ssh.Client, error) {
+ var (
+ ctx = context.Background()
+ cancel context.CancelFunc
+ )
+ if config.Timeout > 0 {
+ ctx, cancel = context.WithTimeout(ctx, config.Timeout)
+ } else {
+ ctx, cancel = context.WithCancel(ctx)
+ }
+ defer cancel()
+
+ conn, err := proxy.Dial(ctx, network, addr)
+ if err != nil {
+ return nil, err
+ }
+ c, chans, reqs, err := ssh.NewClientConn(conn, addr, config)
+ if err != nil {
+ return nil, err
+ }
+ return ssh.NewClient(c, chans, reqs), nil
+}
+
func (c *command) getHostWithPort() string {
if addr, found := c.doGetHostWithPortFromSSHConfig(); found {
return addr
diff --git a/plumbing/transport/ssh/proxy_test.go b/plumbing/transport/ssh/proxy_test.go
new file mode 100644
index 0000000..3caf1ff
--- /dev/null
+++ b/plumbing/transport/ssh/proxy_test.go
@@ -0,0 +1,36 @@
+package ssh
+
+import (
+ "fmt"
+ "log"
+ "net"
+ "os"
+
+ "github.com/armon/go-socks5"
+ . "gopkg.in/check.v1"
+)
+
+type ProxySuite struct {
+ UploadPackSuite
+}
+
+var _ = Suite(&ProxySuite{})
+
+func (s *ProxySuite) SetUpSuite(c *C) {
+ s.UploadPackSuite.SetUpSuite(c)
+
+ l, err := net.Listen("tcp", "localhost:0")
+ c.Assert(err, IsNil)
+
+ server, err := socks5.New(&socks5.Config{})
+ c.Assert(err, IsNil)
+
+ port := l.Addr().(*net.TCPAddr).Port
+
+ err = os.Setenv("ALL_PROXY", fmt.Sprintf("socks5://localhost:%d", port))
+ c.Assert(err, IsNil)
+
+ go func() {
+ log.Fatal(server.Serve(l))
+ }()
+}