Port forward now listens on IPv4 and IPv6 localhost address

- Tries to listen 127.0.0.1 and the given port
- Tries to listen [::1] and the given port
- If both of them fails port-forward fails
- If at least one succeeds, port-forward listens on the corresponding interface and displays a warning for the other
- If both succeeds, port-portfward listens on both the interfaces
This commit is contained in:
Akram Ben Aissi 2015-04-28 16:27:00 +02:00
parent 56b7325fa5
commit a788002d0d
2 changed files with 23 additions and 22 deletions

View File

@ -183,17 +183,26 @@ func (pf *PortForwarder) forward() error {
return nil
}
// listenOnPort delegates listener creation and waits for new connections
// in the background.
// listenOnPort delegates tcp4 and tcp6 listener creation and waits for connections on both of these addresses.
// If both listener creation fail, an error is raised.
func (pf *PortForwarder) listenOnPort(port *ForwardedPort) error {
listener, err := pf.getListener("tcp", "localhost", port)
errTcp4 := pf.listenOnPortAndAddress(port, "tcp4", "127.0.0.1")
errTcp6 := pf.listenOnPortAndAddress(port, "tcp6", "[::1]")
if errTcp4 != nil && errTcp6 != nil {
return fmt.Errorf("All listeners failed to create with the following errors: %s, %s", errTcp4, errTcp6)
}
return nil
}
// listenOnPortAndAddress delegates listener creation and waits for new connections
// in the background f
func (pf *PortForwarder) listenOnPortAndAddress(port *ForwardedPort, protocol string, address string) error {
listener, err := pf.getListener(protocol, address, port)
if err != nil {
return err
}
pf.listeners = append(pf.listeners, listener)
go pf.waitForConnection(listener, *port)
return nil
}
@ -213,7 +222,7 @@ func (pf *PortForwarder) getListener(protocol string, hostname string, port *For
return nil, fmt.Errorf("Error parsing local port: %s from %s (%s)", err, listenerAddress, host)
}
port.Local = uint16(localPortUInt)
glog.Infof("Forwarding from %d -> %d", localPortUInt, port.Remote)
glog.Infof("Forwarding from %s:%d -> %d", hostname, localPortUInt, port.Remote)
return listener, nil
}

View File

@ -209,7 +209,7 @@ func (s *fakeUpgradeStream) Headers() http.Header {
return http.Header{}
}
type TestCase struct {
type GetListenerTestCase struct {
Hostname string
Protocol string
ShouldRaiseError bool
@ -218,7 +218,7 @@ type TestCase struct {
func TestGetListener(t *testing.T) {
var pf PortForwarder
testCases := []TestCase{
testCases := []GetListenerTestCase{
{
Hostname: "localhost",
Protocol: "tcp4",
@ -247,20 +247,12 @@ func TestGetListener(t *testing.T) {
Protocol: "tcp6",
ShouldRaiseError: true,
},
}
// On some linux systems, ::1 does not resolve to localhost but to localhost6 or
// ip6-localhost. To make the test case portable, we need to do a reverse lookup on ::1 and
// trying to bind a port with the name.
names, err := net.LookupAddr("::1")
if err == nil && len(names) > 0 {
ipv6TestCase := TestCase{
Hostname: names[0],
Protocol: "tcp6",
ShouldRaiseError: false,
ExpectedListenerAddress: "::1",
}
testCases = append(testCases, ipv6TestCase)
{
// IPv6 address must be put into brackets. This test reveals this.
Hostname: "::1",
Protocol: "tcp6",
ShouldRaiseError: true,
},
}
for i, testCase := range testCases {