mirror of
https://github.com/fosrl/olm.git
synced 2026-07-16 12:22:51 -05:00
111 lines
2.6 KiB
Go
111 lines
2.6 KiB
Go
//go:build windows
|
|
|
|
package dns
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"net/netip"
|
|
|
|
"golang.org/x/sys/windows/registry"
|
|
)
|
|
|
|
const (
|
|
tcpipInterfacesPath = `SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces`
|
|
dhcpNameServerKey = "DhcpNameServer"
|
|
staticNameServerKey = "NameServer"
|
|
)
|
|
|
|
// readSystemDNS returns the current system DNS servers in "host:53" format by
|
|
// enumerating every network adapter in the Windows registry.
|
|
//
|
|
// For each adapter olm reads the effective DNS servers: static (NameServer)
|
|
// if set, since a static entry overrides DHCP for that adapter and is what
|
|
// the OS resolver actually uses, otherwise falling back to the DHCP-assigned
|
|
// servers (DhcpNameServer). This also picks up olm's own WireGuard adapter,
|
|
// which olm points at its local DNS proxy via a static NameServer entry; that
|
|
// address is expected to be filtered out by the caller via
|
|
// SystemDNSMonitor.SetExcludeIP. Loopback and link-local addresses are
|
|
// excluded.
|
|
func readSystemDNS() []string {
|
|
key, err := registry.OpenKey(registry.LOCAL_MACHINE, tcpipInterfacesPath, registry.ENUMERATE_SUB_KEYS)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
defer key.Close()
|
|
|
|
subkeys, err := key.ReadSubKeyNames(-1)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
seen := make(map[string]bool)
|
|
var result []string
|
|
|
|
for _, guid := range subkeys {
|
|
path := fmt.Sprintf(`%s\%s`, tcpipInterfacesPath, guid)
|
|
iKey, err := registry.OpenKey(registry.LOCAL_MACHINE, path, registry.QUERY_VALUE)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
servers, _, err := iKey.GetStringValue(staticNameServerKey)
|
|
if err != nil || servers == "" {
|
|
servers, _, err = iKey.GetStringValue(dhcpNameServerKey)
|
|
}
|
|
iKey.Close()
|
|
if err != nil || servers == "" {
|
|
continue
|
|
}
|
|
|
|
for _, s := range splitWinDNSList(servers) {
|
|
addr, err := netip.ParseAddr(s)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if addr.IsLoopback() || addr.IsLinkLocalUnicast() {
|
|
continue
|
|
}
|
|
hp := net.JoinHostPort(addr.String(), "53")
|
|
if !seen[hp] {
|
|
seen[hp] = true
|
|
result = append(result, hp)
|
|
}
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// splitWinDNSList splits a Windows DNS server list that may be comma- or
|
|
// space-separated.
|
|
func splitWinDNSList(s string) []string {
|
|
var out []string
|
|
for _, part := range splitByRunes(s, []rune{',', ' '}) {
|
|
if part != "" {
|
|
out = append(out, part)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
func splitByRunes(s string, delims []rune) []string {
|
|
var result []string
|
|
start := 0
|
|
for i, r := range s {
|
|
for _, d := range delims {
|
|
if r == d {
|
|
if i > start {
|
|
result = append(result, s[start:i])
|
|
}
|
|
start = i + len(string(r))
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if start < len(s) {
|
|
result = append(result, s[start:])
|
|
}
|
|
return result
|
|
}
|