Skip to content

Commit 1b05b60

Browse files
authored
Merge pull request #5145 from aojea/happyeyeballs
use (sort of) happy-eyeballs for port-forwarding
2 parents effe226 + 305b425 commit 1b05b60

1 file changed

Lines changed: 16 additions & 4 deletions

File tree

pkg/cri/server/sandbox_portforward_linux.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,24 @@ func (c *criService) portForward(ctx context.Context, id string, port int32, str
6262
log.G(ctx).Infof("Executing port forwarding in network namespace %q", netNSPath)
6363
err = netNSDo(func(_ ns.NetNS) error {
6464
defer stream.Close()
65-
// TODO: hardcoded to tcp4 because localhost resolves to ::1 by default if the system has IPv6 enabled.
66-
// Theoretically happy eyeballs will try IPv6 first and fallback to IPv4
67-
// but resolving localhost doesn't seem to return and IPv4 address, thus failing the connection.
65+
// localhost can resolve to both IPv4 and IPv6 addresses in dual-stack systems
66+
// but the application can be listening in one of the IP families only.
67+
// golang has enabled RFC 6555 Fast Fallback (aka HappyEyeballs) by default in 1.12
68+
// It means that if a host resolves to both IPv6 and IPv4, it will try to connect to any
69+
// of those addresses and use the working connection.
70+
// However, the implementation uses go routines to start both connections in parallel,
71+
// and this cases that the connection is done outside the namespace, so we try to connect
72+
// serially.
73+
// We try IPv4 first to keep current behavior and we fallback to IPv6 if the connection fails.
74+
// xref https://github.com/golang/go/issues/44922
75+
var conn net.Conn
6876
conn, err := net.Dial("tcp4", fmt.Sprintf("localhost:%d", port))
6977
if err != nil {
70-
return errors.Wrapf(err, "failed to dial %d", port)
78+
var errV6 error
79+
conn, errV6 = net.Dial("tcp6", fmt.Sprintf("localhost:%d", port))
80+
if errV6 != nil {
81+
return fmt.Errorf("failed to connect to localhost:%d inside namespace %q, IPv4: %v IPv6 %v ", port, id, err, errV6)
82+
}
7183
}
7284
defer conn.Close()
7385

0 commit comments

Comments
 (0)