Make router director return extra information (needed to route ssh

connections)
This commit is contained in:
Jonathan Leibiusky @xetorthio
2017-10-31 12:49:37 -03:00
parent 36bebe3223
commit 6009bfd781
6 changed files with 74 additions and 55 deletions

View File

@@ -10,10 +10,12 @@ import (
"os"
"time"
"golang.org/x/crypto/ssh"
client "docker.io/go-docker"
"docker.io/go-docker/api/types"
"docker.io/go-docker/api/types/filters"
"docker.io/go-docker/api/types/network"
client "docker.io/go-docker"
"github.com/gorilla/mux"
"github.com/play-with-docker/play-with-docker/config"
"github.com/play-with-docker/play-with-docker/router"
@@ -21,7 +23,7 @@ import (
"github.com/urfave/negroni"
)
func director(protocol router.Protocol, host string) (*net.TCPAddr, error) {
func director(protocol router.Protocol, host string) (*router.DirectorInfo, error) {
info, err := router.DecodeHost(host)
if err != nil {
return nil, err
@@ -33,6 +35,7 @@ func director(protocol router.Protocol, host string) (*net.TCPAddr, error) {
port = info.EncodedPort
}
i := router.DirectorInfo{}
if port == 0 {
if protocol == router.ProtocolHTTP {
port = 80
@@ -40,6 +43,8 @@ func director(protocol router.Protocol, host string) (*net.TCPAddr, error) {
port = 443
} else if protocol == router.ProtocolSSH {
port = 22
i.SSHUser = "root"
i.SSHAuthMethods = []ssh.AuthMethod{ssh.Password("root")}
} else if protocol == router.ProtocolDNS {
port = 53
}
@@ -49,7 +54,8 @@ func director(protocol router.Protocol, host string) (*net.TCPAddr, error) {
if err != nil {
return nil, err
}
return t, nil
i.Dst = t
return &i, nil
}
func connectNetworks() error {

View File

@@ -8,49 +8,50 @@ import (
)
func TestDirector(t *testing.T) {
addr, err := director(router.ProtocolHTTP, "ip10-0-0-1-aabb-8080.foo.bar")
info, err := director(router.ProtocolHTTP, "ip10-0-0-1-aabb-8080.foo.bar")
assert.Nil(t, err)
assert.Equal(t, "10.0.0.1:8080", addr.String())
assert.Equal(t, "10.0.0.1:8080", info.Dst.String())
addr, err = director(router.ProtocolHTTP, "ip10-0-0-1-aabb.foo.bar")
info, err = director(router.ProtocolHTTP, "ip10-0-0-1-aabb.foo.bar")
assert.Nil(t, err)
assert.Equal(t, "10.0.0.1:80", addr.String())
assert.Equal(t, "10.0.0.1:80", info.Dst.String())
addr, err = director(router.ProtocolHTTPS, "ip10-0-0-1-aabb.foo.bar")
info, err = director(router.ProtocolHTTPS, "ip10-0-0-1-aabb.foo.bar")
assert.Nil(t, err)
assert.Equal(t, "10.0.0.1:443", addr.String())
assert.Equal(t, "10.0.0.1:443", info.Dst.String())
addr, err = director(router.ProtocolSSH, "ip10-0-0-1-aabb.foo.bar")
info, err = director(router.ProtocolSSH, "ip10-0-0-1-aabb.foo.bar")
assert.Nil(t, err)
assert.Equal(t, "10.0.0.1:22", addr.String())
assert.Equal(t, "10.0.0.1:22", info.Dst.String())
assert.Equal(t, "root", info.SSHUser)
addr, err = director(router.ProtocolDNS, "ip10-0-0-1-aabb.foo.bar")
info, err = director(router.ProtocolDNS, "ip10-0-0-1-aabb.foo.bar")
assert.Nil(t, err)
assert.Equal(t, "10.0.0.1:53", addr.String())
assert.Equal(t, "10.0.0.1:53", info.Dst.String())
addr, err = director(router.ProtocolHTTP, "ip10-0-0-1-aabb.foo.bar:9090")
info, err = director(router.ProtocolHTTP, "ip10-0-0-1-aabb.foo.bar:9090")
assert.Nil(t, err)
assert.Equal(t, "10.0.0.1:9090", addr.String())
assert.Equal(t, "10.0.0.1:9090", info.Dst.String())
addr, err = director(router.ProtocolHTTP, "ip10-0-0-1-aabb-2222.foo.bar:9090")
info, err = director(router.ProtocolHTTP, "ip10-0-0-1-aabb-2222.foo.bar:9090")
assert.Nil(t, err)
assert.Equal(t, "10.0.0.1:2222", addr.String())
assert.Equal(t, "10.0.0.1:2222", info.Dst.String())
addr, err = director(router.ProtocolHTTP, "lala.ip10-0-0-1-aabb-2222.foo.bar")
info, err = director(router.ProtocolHTTP, "lala.ip10-0-0-1-aabb-2222.foo.bar")
assert.Nil(t, err)
assert.Equal(t, "10.0.0.1:2222", addr.String())
assert.Equal(t, "10.0.0.1:2222", info.Dst.String())
addr, err = director(router.ProtocolHTTP, "lala.ip10-0-0-1-aabb-2222")
info, err = director(router.ProtocolHTTP, "lala.ip10-0-0-1-aabb-2222")
assert.Nil(t, err)
assert.Equal(t, "10.0.0.1:2222", addr.String())
assert.Equal(t, "10.0.0.1:2222", info.Dst.String())
addr, err = director(router.ProtocolHTTP, "ip10-0-0-1-aabb-2222")
info, err = director(router.ProtocolHTTP, "ip10-0-0-1-aabb-2222")
assert.Nil(t, err)
assert.Equal(t, "10.0.0.1:2222", addr.String())
assert.Equal(t, "10.0.0.1:2222", info.Dst.String())
addr, err = director(router.ProtocolHTTP, "ip10-0-0-1-aabb")
info, err = director(router.ProtocolHTTP, "ip10-0-0-1-aabb")
assert.Nil(t, err)
assert.Equal(t, "10.0.0.1:80", addr.String())
assert.Equal(t, "10.0.0.1:80", info.Dst.String())
_, err = director(router.ProtocolHTTP, "lala10-0-0-1-aabb.foo.bar")
assert.NotNil(t, err)

View File

@@ -27,7 +27,13 @@ const (
ProtocolDNS
)
type Director func(protocol Protocol, host string) (*net.TCPAddr, error)
type DirectorInfo struct {
Dst *net.TCPAddr
SSHUser string
SSHAuthMethods []ssh.AuthMethod
}
type Director func(protocol Protocol, host string) (*DirectorInfo, error)
type proxyRouter struct {
sync.Mutex
@@ -121,7 +127,7 @@ func (r *proxyRouter) sshHandle(nConn net.Conn) {
return
}
dstHost, err := r.director(ProtocolSSH, sshCon.User())
info, err := r.director(ProtocolSSH, sshCon.User())
if err != nil {
nConn.Close()
return
@@ -148,19 +154,22 @@ func (r *proxyRouter) sshHandle(nConn net.Conn) {
stderr := channel.Stderr()
fmt.Fprintf(stderr, "Connecting to %s\r\n", dstHost.String())
fmt.Fprintf(stderr, "Connecting to %s\r\n", info.Dst.String())
clientConfig := &ssh.ClientConfig{
User: "root",
/*
Auth: []ssh.AuthMethod{
ssh.Password("root"),
},
*/
clientConfig := &ssh.ClientConfig{
User: info.SSHUser,
Auth: info.SSHAuthMethods,
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
return nil
},
}
client, err := ssh.Dial("tcp", dstHost.String(), clientConfig)
client, err := ssh.Dial("tcp", info.Dst.String(), clientConfig)
if err != nil {
fmt.Fprintf(stderr, "Connect failed: %v\r\n", err)
channel.Close()
@@ -232,7 +241,7 @@ func (r *proxyRouter) dnsRequest(w dns.ResponseWriter, req *dns.Msg) {
return
}
dstHost, err := r.director(ProtocolDNS, strings.TrimSuffix(question, "."))
info, err := r.director(ProtocolDNS, strings.TrimSuffix(question, "."))
if err != nil {
// Director couldn't resolve it, try to lookup in the system's DNS
ips, err := net.LookupIP(question)
@@ -265,6 +274,7 @@ func (r *proxyRouter) dnsRequest(w dns.ResponseWriter, req *dns.Msg) {
w.WriteMsg(m)
return
}
dstHost := info.Dst
m := new(dns.Msg)
m.SetReply(req)
@@ -338,11 +348,12 @@ func (r *proxyRouter) handleConnection(c net.Conn) {
defer vhostConn.Close()
host := vhostConn.ClientHelloMsg.ServerName
log.Printf("Proxying TLS connection to %s. Discover took %s\n", host, discoverElapsed)
dstHost, err := r.director(ProtocolHTTPS, host)
info, err := r.director(ProtocolHTTPS, host)
if err != nil {
log.Printf("Error directing request: %v\n", err)
return
}
dstHost := info.Dst
d, err := r.dialer.Dial("tcp", dstHost.String())
if err != nil {
log.Printf("Error dialing backend %s: %v\n", dstHost.String(), err)
@@ -366,11 +377,12 @@ func (r *proxyRouter) handleConnection(c net.Conn) {
host = req.Host
}
log.Printf("Proxying http connection to %s. Discover took %s. Http read took %s\n", host, discoverElapsed, httpReadElapsed)
dstHost, err := r.director(ProtocolHTTP, host)
info, err := r.director(ProtocolHTTP, host)
if err != nil {
log.Printf("Error directing request: %v\n", err)
return
}
dstHost := info.Dst
d, err := r.dialer.Dial("tcp", dstHost.String())
if err != nil {
log.Printf("Error dialing backend %s: %v\n", dstHost.String(), err)

View File

@@ -231,12 +231,12 @@ func TestProxy_TLS(t *testing.T) {
}))
defer ts.Close()
r := NewRouter(func(protocol Protocol, host string) (*net.TCPAddr, error) {
r := NewRouter(func(protocol Protocol, host string) (*DirectorInfo, error) {
receivedHost = host
receivedProtocol = protocol
u, _ := url.Parse(ts.URL)
a, _ := net.ResolveTCPAddr("tcp", u.Host)
return a, nil
return &DirectorInfo{Dst: a}, nil
}, private)
r.Listen(":0", ":0", ":0")
defer r.Close()
@@ -268,12 +268,12 @@ func TestProxy_Http(t *testing.T) {
}))
defer ts.Close()
r := NewRouter(func(protocol Protocol, host string) (*net.TCPAddr, error) {
r := NewRouter(func(protocol Protocol, host string) (*DirectorInfo, error) {
receivedHost = host
receivedProtocol = protocol
u, _ := url.Parse(ts.URL)
a, _ := net.ResolveTCPAddr("tcp", u.Host)
return a, nil
return &DirectorInfo{Dst: a}, nil
}, private)
r.Listen(":0", ":0", ":0")
defer r.Close()
@@ -323,10 +323,10 @@ func TestProxy_WS(t *testing.T) {
}))
defer ts.Close()
r := NewRouter(func(protocol Protocol, host string) (*net.TCPAddr, error) {
r := NewRouter(func(protocol Protocol, host string) (*DirectorInfo, error) {
u, _ := url.Parse(ts.URL)
a, _ := net.ResolveTCPAddr("tcp", u.Host)
return a, nil
return &DirectorInfo{Dst: a}, nil
}, private)
r.Listen(":0", ":0", ":0")
defer r.Close()
@@ -381,10 +381,10 @@ func TestProxy_WSS(t *testing.T) {
}))
defer ts.Close()
r := NewRouter(func(protocol Protocol, host string) (*net.TCPAddr, error) {
r := NewRouter(func(protocol Protocol, host string) (*DirectorInfo, error) {
u, _ := url.Parse(ts.URL)
a, _ := net.ResolveTCPAddr("tcp", u.Host)
return a, nil
return &DirectorInfo{Dst: a}, nil
}, private)
r.Listen(":0", ":0", ":0")
defer r.Close()
@@ -419,12 +419,12 @@ func TestProxy_DNS_UDP(t *testing.T) {
var receivedHost string
var receivedProtocol Protocol
r := NewRouter(func(protocol Protocol, host string) (*net.TCPAddr, error) {
r := NewRouter(func(protocol Protocol, host string) (*DirectorInfo, error) {
receivedHost = host
receivedProtocol = protocol
if host == "10_0_0_1.foo.bar" {
a, _ := net.ResolveTCPAddr("tcp", "10.0.0.1:0")
return a, nil
return &DirectorInfo{Dst: a}, nil
} else {
return nil, fmt.Errorf("Not recognized")
}
@@ -463,11 +463,11 @@ func TestProxy_DNS_TCP(t *testing.T) {
var receivedHost string
r := NewRouter(func(protocol Protocol, host string) (*net.TCPAddr, error) {
r := NewRouter(func(protocol Protocol, host string) (*DirectorInfo, error) {
receivedHost = host
if host == "10_0_0_1.foo.bar" {
a, _ := net.ResolveTCPAddr("tcp", "10.0.0.1:0")
return a, nil
return &DirectorInfo{Dst: a}, nil
} else {
return nil, fmt.Errorf("Not recognized")
}
@@ -517,13 +517,13 @@ func TestProxy_SSH(t *testing.T) {
})
assert.Nil(t, err)
r := NewRouter(func(protocol Protocol, host string) (*net.TCPAddr, error) {
r := NewRouter(func(protocol Protocol, host string) (*DirectorInfo, error) {
receivedHost = host
receivedProtocol = protocol
if host == "10-0-0-1-aaaabbbb" {
chunks := strings.Split(laddr, ":")
a, _ := net.ResolveTCPAddr("tcp", fmt.Sprintf("127.0.0.1:%s", chunks[len(chunks)-1]))
return a, nil
return &DirectorInfo{Dst: a, SSHUser: "root", SSHAuthMethods: []ssh.AuthMethod{ssh.Password("root")}}, nil
} else {
return nil, fmt.Errorf("Not recognized")
}