Files
ctrld/nameservers_unix.go
Cuong Manh Le c06c8aa859 Unifying DNS from /etc/resolv.conf function
As part of v1.4.0 release, reading DNS from /etc/resolv.conf file is
only available for Macos. However, there's no reason to prevent this
function from working on other *nix systems.

This commit unify the function to *nix, so it could be added as DNS
source for Linux and Freebsd.
2025-04-17 17:19:47 +07:00

65 lines
1.4 KiB
Go

//go:build unix
package ctrld
import (
"net"
"slices"
"time"
"tailscale.com/net/netmon"
"github.com/Control-D-Inc/ctrld/internal/resolvconffile"
)
// currentNameserversFromResolvconf returns the current nameservers set from /etc/resolv.conf file.
func currentNameserversFromResolvconf() []string {
return resolvconffile.NameServers("")
}
// dnsFromResolvConf reads usable nameservers from /etc/resolv.conf file.
// A nameserver is usable if it's not one of current machine's IP addresses
// and loopback IP addresses.
func dnsFromResolvConf() []string {
const (
maxRetries = 10
retryInterval = 100 * time.Millisecond
)
regularIPs, loopbackIPs, _ := netmon.LocalAddresses()
var dns []string
for attempt := 0; attempt < maxRetries; attempt++ {
if attempt > 0 {
time.Sleep(retryInterval)
}
nss := resolvconffile.NameServers("")
var localDNS []string
seen := make(map[string]bool)
for _, ns := range nss {
if ip := net.ParseIP(ns); ip != nil {
// skip loopback IPs
for _, v := range slices.Concat(regularIPs, loopbackIPs) {
ipStr := v.String()
if ip.String() == ipStr {
continue
}
}
if !seen[ip.String()] {
seen[ip.String()] = true
localDNS = append(localDNS, ip.String())
}
}
}
// If we successfully read the file and found nameservers, return them
if len(localDNS) > 0 {
return localDNS
}
}
return dns
}