all: fix OS resolver looping issue on Windows

By making dnsFromAdapter ignores DNS server which is the same IP address
of the adapter.

While at it, also changes OS resolver to use ctrld bootstrap DNS only if
there's no available nameservers.
This commit is contained in:
Cuong Manh Le
2024-05-22 18:17:20 +07:00
committed by Cuong Manh Le
parent 96085147ff
commit 19020a96bf
3 changed files with 32 additions and 33 deletions

View File

@@ -507,7 +507,7 @@ func initCLI() {
iface = runningIface(s)
tasks := []task{
{s.Stop, false},
{func() error { p.resetDNS(); return nil }, false},
{func() error { resetDnsNoLog(p); return nil }, false},
{s.Start, true},
}
if doTasks(tasks) {
@@ -887,7 +887,10 @@ NOTE: Uninstalling will set DNS to values provided by DHCP.`,
sc := &service.Config{}
*sc = *svcConfig
sc.Executable = bin
s, err := newService(&prog{}, sc)
readConfig(false)
v.Unmarshal(&cfg)
p := &prog{router: router.New(&cfg, runInCdMode())}
s, err := newService(p, sc)
if err != nil {
mainLog.Load().Error().Msg(err.Error())
return
@@ -931,6 +934,7 @@ NOTE: Uninstalling will set DNS to values provided by DHCP.`,
}
tasks := []task{
{s.Stop, false},
{func() error { resetDnsNoLog(p); return nil }, false},
{s.Start, false},
}
if doTasks(tasks) {
@@ -2541,3 +2545,11 @@ func runningIface(s service.Service) string {
}
return ""
}
// resetDnsNoLog performs resetting DNS with logging disable.
func resetDnsNoLog(p *prog) {
lvl := zerolog.GlobalLevel()
zerolog.SetGlobalLevel(zerolog.Disabled)
p.resetDNS()
zerolog.SetGlobalLevel(lvl)
}

View File

@@ -1,10 +1,8 @@
package ctrld
import (
"net"
"syscall"
"golang.org/x/sys/windows"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
)
@@ -19,37 +17,23 @@ func dnsFromAdapter() []string {
}
ns := make([]string, 0, len(aas)*2)
seen := make(map[string]bool)
do := func(addr windows.SocketAddress) {
sa, err := addr.Sockaddr.Sockaddr()
if err != nil {
return
addressMap := make(map[string]struct{})
for _, aa := range aas {
for a := aa.FirstUnicastAddress; a != nil; a = a.Next {
addressMap[a.Address.IP().String()] = struct{}{}
}
var ip net.IP
switch sa := sa.(type) {
case *syscall.SockaddrInet4:
ip = net.IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])
case *syscall.SockaddrInet6:
ip = make(net.IP, net.IPv6len)
copy(ip, sa.Addr[:])
if ip[0] == 0xfe && ip[1] == 0xc0 {
// Ignore these fec0/10 ones. Windows seems to
// populate them as defaults on its misc rando
// interfaces.
return
}
default:
return
}
if ip.IsLoopback() || seen[ip.String()] {
return
}
seen[ip.String()] = true
ns = append(ns, ip.String())
}
for _, aa := range aas {
for dns := aa.FirstDNSServerAddress; dns != nil; dns = dns.Next {
do(dns.Address)
ip := dns.Address.IP()
if ip == nil || ip.IsLoopback() || seen[ip.String()] {
continue
}
if _, ok := addressMap[ip.String()]; ok {
continue
}
seen[ip.String()] = true
ns = append(ns, ip.String())
}
}
return ns

View File

@@ -39,10 +39,13 @@ var OsNameservers = defaultNameservers()
// or is the Resolver used for ResolverTypeOS.
var or = &osResolver{nameservers: OsNameservers}
// defaultNameservers returns OS nameservers plus ctrld bootstrap nameserver.
// defaultNameservers returns nameservers used by the OS.
// If no nameservers can be found, ctrld bootstrap nameserver will be used.
func defaultNameservers() []string {
ns := nameservers()
ns = append(ns, net.JoinHostPort(bootstrapDNS, "53"))
if len(ns) == 0 {
ns = append(ns, net.JoinHostPort(bootstrapDNS, "53"))
}
return ns
}