2024-06-13 13:24:24 +02:00
|
|
|
//go:build (linux && !android) || freebsd
|
2023-06-12 14:43:55 +02:00
|
|
|
|
2022-11-23 13:39:42 +01:00
|
|
|
package dns
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"fmt"
|
2024-01-30 09:58:56 +01:00
|
|
|
"io"
|
2024-10-24 10:53:46 +02:00
|
|
|
"net/netip"
|
2022-11-23 13:39:42 +01:00
|
|
|
"os"
|
|
|
|
"strings"
|
2023-07-14 21:56:22 +02:00
|
|
|
|
|
|
|
log "github.com/sirupsen/logrus"
|
2022-11-23 13:39:42 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
netbirdManager osManagerType = iota
|
|
|
|
fileManager
|
|
|
|
networkManager
|
|
|
|
systemdManager
|
|
|
|
resolvConfManager
|
|
|
|
)
|
|
|
|
|
|
|
|
type osManagerType int
|
|
|
|
|
2023-12-08 10:48:21 +01:00
|
|
|
func (t osManagerType) String() string {
|
|
|
|
switch t {
|
|
|
|
case netbirdManager:
|
|
|
|
return "netbird"
|
|
|
|
case fileManager:
|
|
|
|
return "file"
|
|
|
|
case networkManager:
|
|
|
|
return "networkManager"
|
|
|
|
case systemdManager:
|
|
|
|
return "systemd"
|
|
|
|
case resolvConfManager:
|
|
|
|
return "resolvconf"
|
|
|
|
default:
|
|
|
|
return "unknown"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-24 10:53:46 +02:00
|
|
|
type restoreHostManager interface {
|
|
|
|
hostManager
|
|
|
|
restoreUncleanShutdownDNS(*netip.Addr) error
|
|
|
|
}
|
|
|
|
|
2024-01-30 09:58:56 +01:00
|
|
|
func newHostManager(wgInterface string) (hostManager, error) {
|
2022-11-23 13:39:42 +01:00
|
|
|
osManager, err := getOSDNSManagerType()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2024-03-01 15:17:35 +01:00
|
|
|
log.Infof("System DNS manager discovered: %s", osManager)
|
2024-01-30 09:58:56 +01:00
|
|
|
return newHostManagerFromType(wgInterface, osManager)
|
|
|
|
}
|
|
|
|
|
2024-10-24 10:53:46 +02:00
|
|
|
func newHostManagerFromType(wgInterface string, osManager osManagerType) (restoreHostManager, error) {
|
2022-11-23 13:39:42 +01:00
|
|
|
switch osManager {
|
|
|
|
case networkManager:
|
|
|
|
return newNetworkManagerDbusConfigurator(wgInterface)
|
|
|
|
case systemdManager:
|
|
|
|
return newSystemdDbusConfigurator(wgInterface)
|
2022-11-29 14:51:18 +01:00
|
|
|
case resolvConfManager:
|
|
|
|
return newResolvConfConfigurator(wgInterface)
|
2022-11-23 13:39:42 +01:00
|
|
|
default:
|
|
|
|
return newFileConfigurator()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func getOSDNSManagerType() (osManagerType, error) {
|
|
|
|
file, err := os.Open(defaultResolvConfPath)
|
|
|
|
if err != nil {
|
2024-01-30 09:58:56 +01:00
|
|
|
return 0, fmt.Errorf("unable to open %s for checking owner, got error: %w", defaultResolvConfPath, err)
|
2022-11-23 13:39:42 +01:00
|
|
|
}
|
2024-01-30 09:58:56 +01:00
|
|
|
defer func() {
|
|
|
|
if err := file.Close(); err != nil {
|
|
|
|
log.Errorf("close file %s: %s", defaultResolvConfPath, err)
|
|
|
|
}
|
|
|
|
}()
|
2022-11-23 13:39:42 +01:00
|
|
|
|
|
|
|
scanner := bufio.NewScanner(file)
|
|
|
|
for scanner.Scan() {
|
|
|
|
text := scanner.Text()
|
|
|
|
if len(text) == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if text[0] != '#' {
|
|
|
|
return fileManager, nil
|
|
|
|
}
|
|
|
|
if strings.Contains(text, fileGeneratedResolvConfContentHeader) {
|
|
|
|
return netbirdManager, nil
|
|
|
|
}
|
|
|
|
if strings.Contains(text, "NetworkManager") && isDbusListenerRunning(networkManagerDest, networkManagerDbusObjectNode) && isNetworkManagerSupported() {
|
|
|
|
return networkManager, nil
|
|
|
|
}
|
2024-06-13 13:24:24 +02:00
|
|
|
if strings.Contains(text, "systemd-resolved") && isSystemdResolvedRunning() {
|
2024-01-24 16:47:26 +01:00
|
|
|
if checkStub() {
|
|
|
|
return systemdManager, nil
|
|
|
|
} else {
|
|
|
|
return fileManager, nil
|
|
|
|
}
|
2022-11-23 13:39:42 +01:00
|
|
|
}
|
|
|
|
if strings.Contains(text, "resolvconf") {
|
2024-06-13 13:24:24 +02:00
|
|
|
if isSystemdResolveConfMode() {
|
|
|
|
return systemdManager, nil
|
2022-11-29 13:37:50 +01:00
|
|
|
}
|
2024-06-13 13:24:24 +02:00
|
|
|
|
2022-11-23 13:39:42 +01:00
|
|
|
return resolvConfManager, nil
|
|
|
|
}
|
|
|
|
}
|
2024-01-30 09:58:56 +01:00
|
|
|
if err := scanner.Err(); err != nil && err != io.EOF {
|
|
|
|
return 0, fmt.Errorf("scan: %w", err)
|
|
|
|
}
|
|
|
|
|
2022-11-23 13:39:42 +01:00
|
|
|
return fileManager, nil
|
|
|
|
}
|
2024-01-24 16:47:26 +01:00
|
|
|
|
|
|
|
// checkStub checks if the stub resolver is disabled in systemd-resolved. If it is disabled, we fall back to file manager.
|
|
|
|
func checkStub() bool {
|
|
|
|
rConf, err := parseDefaultResolvConf()
|
|
|
|
if err != nil {
|
|
|
|
log.Warnf("failed to parse resolv conf: %s", err)
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, ns := range rConf.nameServers {
|
|
|
|
if ns == "127.0.0.53" {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|