cmd/ctrld: workaround ipv6 dns resolver on Windows

On Windows, there's no easy way for disabling/removing IPv6 DNS
resolver, so we check whether we can listen on ::1, then spawn a
listener for receiving DNS requests
This commit is contained in:
Cuong Manh Le
2023-01-20 21:43:04 +07:00
committed by Cuong Manh Le
parent 49e9b8b51c
commit d418e57def
2 changed files with 27 additions and 2 deletions
+15
View File
@@ -6,6 +6,7 @@ import (
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"net" "net"
"runtime"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@@ -51,6 +52,20 @@ func (p *prog) serveUDP(listenerNum string) error {
ctrld.Log(ctx, mainLog.Error().Err(err), "serveUDP: failed to send DNS response to client") ctrld.Log(ctx, mainLog.Error().Err(err), "serveUDP: failed to send DNS response to client")
} }
}) })
// On Windows, there's no easy way for disabling/removing IPv6 DNS resolver, so we check whether we can
// listen on ::1, then spawn a listener for receiving DNS requests.
if runtime.GOOS == "windows" && supportsIPv6ListenLocal() {
go func() {
s := &dns.Server{
Addr: net.JoinHostPort("::1", strconv.Itoa(listenerConfig.Port)),
Net: "udp",
Handler: handler,
}
_ = s.ListenAndServe()
}()
}
s := &dns.Server{ s := &dns.Server{
Addr: net.JoinHostPort(listenerConfig.IP, strconv.Itoa(listenerConfig.Port)), Addr: net.JoinHostPort(listenerConfig.IP, strconv.Itoa(listenerConfig.Port)),
Net: "udp", Net: "udp",
+12 -2
View File
@@ -8,14 +8,19 @@ import (
const controldIPv6Test = "ipv6.controld.io" const controldIPv6Test = "ipv6.controld.io"
var ( var (
stackOnce sync.Once stackOnce sync.Once
ipv6Enabled bool ipv6Enabled bool
canListenIPv6Local bool
) )
func probeStack() { func probeStack() {
if _, err := net.Dial("tcp6", controldIPv6Test); err == nil { if _, err := net.Dial("tcp6", controldIPv6Test); err == nil {
ipv6Enabled = true ipv6Enabled = true
} }
if ln, err := net.Listen("tcp6", "[::1]:53"); err == nil {
ln.Close()
canListenIPv6Local = true
}
} }
func supportsIPv6() bool { func supportsIPv6() bool {
@@ -23,6 +28,11 @@ func supportsIPv6() bool {
return ipv6Enabled return ipv6Enabled
} }
func supportsIPv6ListenLocal() bool {
stackOnce.Do(probeStack)
return canListenIPv6Local
}
// isIPv6 checks if the provided IP is v6. // isIPv6 checks if the provided IP is v6.
func isIPv6(ip string) bool { func isIPv6(ip string) bool {
parsedIP := net.ParseIP(ip) parsedIP := net.ParseIP(ip)