Support port forwarding of literal IPv6 addresses (#85)

* Support port forwarding of literal IPv6 addresses

To disambiguate between colons as host:port separators and as IPv6 address separators, literal IPv6 addresses use square brackets around the address (https://en.wikipedia.org/wiki/IPv6_address#Literal_IPv6_addresses_in_network_resource_identifiers).  So host ::1, port 22 is written as [::1]:22, and therefore a simple concatenation of host, colon, and port doesn't work.  Fortunately net.JoinHostPort already implements this functionality, so with a bit of type gymnastics we can generate dest in an IPv6-safe way.

* Support port forwarding of literal IPv6 addresses

To disambiguate between colons as host:port separators and as IPv6 address separators, literal IPv6 addresses use square brackets around the address (https://en.wikipedia.org/wiki/IPv6_address#Literal_IPv6_addresses_in_network_resource_identifiers).  So host ::1, port 22 is written as [::1]:22, and therefore a simple concatenation of host, colon, and port doesn't work.  Fortunately net.JoinHostPort already implements this functionality, so with a bit of type gymnastics we can generate dest in an IPv6-safe way.
This commit is contained in:
Marc Fielding 2018-09-23 20:41:38 -04:00 committed by Jeff Lindsay
parent d3a6756290
commit c072a10770
2 changed files with 5 additions and 5 deletions

@ -1,9 +1,9 @@
package ssh
import (
"fmt"
"io"
"net"
"strconv"
gossh "golang.org/x/crypto/ssh"
)
@ -29,8 +29,8 @@ func directTcpipHandler(srv *Server, conn *gossh.ServerConn, newChan gossh.NewCh
return
}
dest := fmt.Sprintf("%s:%d", d.DestinationHost, d.DestinationPort)
dest := net.JoinHostPort(d.DestinationHost, strconv.FormatInt(int64(d.DestinationPort), 10))
var dialer net.Dialer
dconn, err := dialer.DialContext(ctx, "tcp", dest)
if err != nil {

@ -2,9 +2,9 @@ package ssh
import (
"bytes"
"fmt"
"io/ioutil"
"net"
"strconv"
"strings"
"testing"
@ -34,7 +34,7 @@ func newTestSessionWithForwarding(t *testing.T, forwardingEnabled bool) (net.Lis
_, client, cleanup := newTestSession(t, &Server{
Handler: func(s Session) {},
LocalPortForwardingCallback: func(ctx Context, destinationHost string, destinationPort uint32) bool {
addr := fmt.Sprintf("%s:%d", destinationHost, destinationPort)
addr := net.JoinHostPort(destinationHost, strconv.FormatInt(int64(destinationPort), 10))
if addr != l.Addr().String() {
panic("unexpected destinationHost: " + addr)
}