diff --git a/net/dnscache/dnscache.go b/net/dnscache/dnscache.go index 830091724..4dc7c1757 100644 --- a/net/dnscache/dnscache.go +++ b/net/dnscache/dnscache.go @@ -422,24 +422,21 @@ func (d *dialer) DialContext(ctx context.Context, network, address string) (retC } }() - ip, ip6, allIPs, err := d.dnsCache.LookupIP(ctx, host) + ip, _, allIPs, err := d.dnsCache.LookupIP(ctx, host) if err != nil { return nil, fmt.Errorf("failed to resolve %q: %w", host, err) } - i4s := v4addrs(allIPs) - if len(i4s) < 2 { + + // If we only have one candidate, just dial that, no matter what the + // address family is. + if len(allIPs) == 1 { d.dnsCache.dlogf("dialing %s, %s for %s", network, ip, address) - c, err := dc.dialOne(ctx, ip.Unmap()) - if err == nil || ctx.Err() != nil || !ip6.IsValid() { - return c, err - } - // Fall back to trying IPv6. - return dc.dialOne(ctx, ip6) + return dc.dialOne(ctx, ip.Unmap()) } - // Multiple IPv4 candidates, and 0+ IPv6. - ipsToTry := append(i4s, v6addrs(allIPs)...) - return dc.raceDial(ctx, ipsToTry) + // If we have multiple candidates, across address families, use happy + // eyeballs to find a connection. + return dc.raceDial(ctx, allIPs) } func (d *dialer) shouldTryBootstrap(ctx context.Context, err error, dc *dialCall) bool { @@ -645,25 +642,6 @@ func (dc *dialCall) raceDial(ctx context.Context, ips []netip.Addr) (net.Conn, e } } -func v4addrs(aa []netip.Addr) (ret []netip.Addr) { - for _, a := range aa { - a = a.Unmap() - if a.Is4() { - ret = append(ret, a) - } - } - return ret -} - -func v6addrs(aa []netip.Addr) (ret []netip.Addr) { - for _, a := range aa { - if a.Is6() && !a.Is4In6() { - ret = append(ret, a) - } - } - return ret -} - // TLSDialer is like Dialer but returns a func suitable for using with net/http.Transport.DialTLSContext. // It returns a *tls.Conn type on success. // On TLS cert validation failure, it can invoke a backup DNS resolution strategy. diff --git a/tstest/natlab/vmtest/connectivity_test.go b/tstest/natlab/vmtest/connectivity_test.go index f9be6589a..8cbbfdc29 100644 --- a/tstest/natlab/vmtest/connectivity_test.go +++ b/tstest/natlab/vmtest/connectivity_test.go @@ -4,7 +4,6 @@ package vmtest_test import ( - "flag" "fmt" "testing" @@ -13,8 +12,6 @@ import ( "tailscale.com/tstest/natlab/vnet" ) -var knownBroken = flag.Bool("known-broken", false, "run known-broken tests") - func v6cidr(n int) string { return fmt.Sprintf("2000:%d::1/64", n) } @@ -228,12 +225,7 @@ func TestSingleJustIPv6(t *testing.T) { // TestSingleDualBrokenIPv4 tests a dual-stack node with broken // (blackholed) IPv4. -// -// See https://github.com/tailscale/tailscale/issues/13346 func TestSingleDualBrokenIPv4(t *testing.T) { - if !*knownBroken { - t.Skip("skipping known-broken test; set --known-broken to run; see https://github.com/tailscale/tailscale/issues/13346") - } env := vmtest.New(t) v6AndBlackholedIPv4(env) env.Start()