mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-02-03 22:18:39 +00:00
all: remove ipv6 check polling
netmon provides ipv6 availability during network event changes, so use this metadata instead of wasting on polling check. Further, repeated network errors will force marking ipv6 as disable if were being enabled, catching a rare case when ipv6 were disabled from cli or system settings.
This commit is contained in:
committed by
Cuong Manh Le
parent
e0d35d8ba2
commit
58c0e4f15a
@@ -556,6 +556,10 @@ func (p *prog) proxy(ctx context.Context, req *proxyRequest) *proxyResponse {
|
|||||||
if errors.As(err, &e) && e.Timeout() {
|
if errors.As(err, &e) && e.Timeout() {
|
||||||
upstreamConfig.ReBootstrap()
|
upstreamConfig.ReBootstrap()
|
||||||
}
|
}
|
||||||
|
// For network error, turn ipv6 off if enabled.
|
||||||
|
if ctrld.HasIPv6() && (errUrlNetworkError(err) || errNetworkError(err)) {
|
||||||
|
ctrld.DisableIPv6()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -485,7 +485,7 @@ func (uc *UpstreamConfig) setupDOHTransport() {
|
|||||||
uc.transport = uc.newDOHTransport(uc.bootstrapIPs6)
|
uc.transport = uc.newDOHTransport(uc.bootstrapIPs6)
|
||||||
case IpStackSplit:
|
case IpStackSplit:
|
||||||
uc.transport4 = uc.newDOHTransport(uc.bootstrapIPs4)
|
uc.transport4 = uc.newDOHTransport(uc.bootstrapIPs4)
|
||||||
if hasIPv6() {
|
if HasIPv6() {
|
||||||
uc.transport6 = uc.newDOHTransport(uc.bootstrapIPs6)
|
uc.transport6 = uc.newDOHTransport(uc.bootstrapIPs6)
|
||||||
} else {
|
} else {
|
||||||
uc.transport6 = uc.transport4
|
uc.transport6 = uc.transport4
|
||||||
@@ -655,7 +655,7 @@ func (uc *UpstreamConfig) bootstrapIPForDNSType(dnsType uint16) string {
|
|||||||
case dns.TypeA:
|
case dns.TypeA:
|
||||||
return pick(uc.bootstrapIPs4)
|
return pick(uc.bootstrapIPs4)
|
||||||
default:
|
default:
|
||||||
if hasIPv6() {
|
if HasIPv6() {
|
||||||
return pick(uc.bootstrapIPs6)
|
return pick(uc.bootstrapIPs6)
|
||||||
}
|
}
|
||||||
return pick(uc.bootstrapIPs4)
|
return pick(uc.bootstrapIPs4)
|
||||||
@@ -677,7 +677,7 @@ func (uc *UpstreamConfig) netForDNSType(dnsType uint16) (string, string) {
|
|||||||
case dns.TypeA:
|
case dns.TypeA:
|
||||||
return "tcp4-tls", "udp4"
|
return "tcp4-tls", "udp4"
|
||||||
default:
|
default:
|
||||||
if hasIPv6() {
|
if HasIPv6() {
|
||||||
return "tcp6-tls", "udp6"
|
return "tcp6-tls", "udp6"
|
||||||
}
|
}
|
||||||
return "tcp4-tls", "udp4"
|
return "tcp4-tls", "udp4"
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ func (uc *UpstreamConfig) setupDOH3Transport() {
|
|||||||
uc.http3RoundTripper = uc.newDOH3Transport(uc.bootstrapIPs6)
|
uc.http3RoundTripper = uc.newDOH3Transport(uc.bootstrapIPs6)
|
||||||
case IpStackSplit:
|
case IpStackSplit:
|
||||||
uc.http3RoundTripper4 = uc.newDOH3Transport(uc.bootstrapIPs4)
|
uc.http3RoundTripper4 = uc.newDOH3Transport(uc.bootstrapIPs4)
|
||||||
if hasIPv6() {
|
if HasIPv6() {
|
||||||
uc.http3RoundTripper6 = uc.newDOH3Transport(uc.bootstrapIPs6)
|
uc.http3RoundTripper6 = uc.newDOH3Transport(uc.bootstrapIPs6)
|
||||||
} else {
|
} else {
|
||||||
uc.http3RoundTripper6 = uc.http3RoundTripper4
|
uc.http3RoundTripper6 = uc.http3RoundTripper4
|
||||||
|
|||||||
@@ -17,9 +17,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
controldIPv6Test = "ipv6.controld.io"
|
v4BootstrapDNS = "76.76.2.22:53"
|
||||||
v4BootstrapDNS = "76.76.2.22:53"
|
v6BootstrapDNS = "[2606:1a40::22]:53"
|
||||||
v6BootstrapDNS = "[2606:1a40::22]:53"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var Dialer = &net.Dialer{
|
var Dialer = &net.Dialer{
|
||||||
|
|||||||
50
net.go
50
net.go
@@ -6,6 +6,8 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"tailscale.com/net/netmon"
|
||||||
|
|
||||||
ctrldnet "github.com/Control-D-Inc/ctrld/internal/net"
|
ctrldnet "github.com/Control-D-Inc/ctrld/internal/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -14,38 +16,38 @@ var (
|
|||||||
ipv6Available atomic.Bool
|
ipv6Available atomic.Bool
|
||||||
)
|
)
|
||||||
|
|
||||||
const ipv6ProbingInterval = 10 * time.Second
|
// HasIPv6 reports whether the current network stack has IPv6 available.
|
||||||
|
func HasIPv6() bool {
|
||||||
func hasIPv6() bool {
|
|
||||||
hasIPv6Once.Do(func() {
|
hasIPv6Once.Do(func() {
|
||||||
Log(context.Background(), ProxyLogger.Load().Debug(), "checking for IPv6 availability once")
|
ProxyLogger.Load().Debug().Msg("checking for IPv6 availability once")
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
val := ctrldnet.IPv6Available(ctx)
|
val := ctrldnet.IPv6Available(ctx)
|
||||||
ipv6Available.Store(val)
|
ipv6Available.Store(val)
|
||||||
go probingIPv6(context.TODO(), val)
|
ProxyLogger.Load().Debug().Msgf("ipv6 availability: %v", val)
|
||||||
|
mon, err := netmon.New(func(format string, args ...any) {})
|
||||||
|
if err != nil {
|
||||||
|
ProxyLogger.Load().Debug().Err(err).Msg("failed to monitor IPv6 state")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mon.RegisterChangeCallback(func(delta *netmon.ChangeDelta) {
|
||||||
|
old := ipv6Available.Load()
|
||||||
|
cur := delta.Monitor.InterfaceState().HaveV6
|
||||||
|
if old != cur {
|
||||||
|
ProxyLogger.Load().Warn().Msgf("ipv6 availability changed, old: %v, new: %v", old, cur)
|
||||||
|
} else {
|
||||||
|
ProxyLogger.Load().Debug().Msg("ipv6 availability does not changed")
|
||||||
|
}
|
||||||
|
ipv6Available.Store(cur)
|
||||||
|
})
|
||||||
|
mon.Start()
|
||||||
})
|
})
|
||||||
return ipv6Available.Load()
|
return ipv6Available.Load()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(cuonglm): doing poll check natively for supported platforms.
|
// DisableIPv6 marks IPv6 as unavailable if enabled.
|
||||||
func probingIPv6(ctx context.Context, old bool) {
|
func DisableIPv6() {
|
||||||
ticker := time.NewTicker(ipv6ProbingInterval)
|
if ipv6Available.CompareAndSwap(true, false) {
|
||||||
defer ticker.Stop()
|
ProxyLogger.Load().Debug().Msg("turned off IPv6 availability")
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
case <-ticker.C:
|
|
||||||
func() {
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
|
||||||
defer cancel()
|
|
||||||
cur := ctrldnet.IPv6Available(ctx)
|
|
||||||
if ipv6Available.CompareAndSwap(old, cur) {
|
|
||||||
old = cur
|
|
||||||
}
|
|
||||||
Log(ctx, ProxyLogger.Load().Debug(), "IPv6 availability: %v", cur)
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user