mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-02-03 22:18:39 +00:00
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.
65 lines
1.4 KiB
Go
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
|
|
}
|