Browse Source

Use a more conservative strategy for resolving with systemd-resolved for local DNS server

世界 2 days ago
parent
commit
cf5d767010

+ 8 - 6
dns/transport/local/local.go

@@ -53,13 +53,15 @@ func (t *Transport) Start(stage adapter.StartStage) error {
 	switch stage {
 	case adapter.StartStateInitialize:
 		if !t.preferGo {
-			resolvedResolver, err := NewResolvedResolver(t.ctx, t.logger)
-			if err == nil {
-				err = resolvedResolver.Start()
+			if isSystemdResolvedManaged() {
+				resolvedResolver, err := NewResolvedResolver(t.ctx, t.logger)
 				if err == nil {
-					t.resolved = resolvedResolver
-				} else {
-					t.logger.Warn(E.Cause(err, "initialize resolved resolver"))
+					err = resolvedResolver.Start()
+					if err == nil {
+						t.resolved = resolvedResolver
+					} else {
+						t.logger.Warn(E.Cause(err, "initialize resolved resolver"))
+					}
 				}
 			}
 		}

+ 27 - 9
dns/transport/local/local_resolved_linux.go

@@ -1,9 +1,11 @@
 package local
 
 import (
+	"bufio"
 	"context"
 	"errors"
 	"os"
+	"strings"
 	"sync"
 	"sync/atomic"
 
@@ -22,6 +24,25 @@ import (
 	mDNS "github.com/miekg/dns"
 )
 
+func isSystemdResolvedManaged() bool {
+	resolvContent, err := os.Open("/etc/resolv.conf")
+	if err != nil {
+		return false
+	}
+	defer resolvContent.Close()
+	scanner := bufio.NewScanner(resolvContent)
+	for scanner.Scan() {
+		line := strings.TrimSpace(scanner.Text())
+		if line == "" || line[0] != '#' {
+			return false
+		}
+		if strings.Contains(line, "systemd-resolved") {
+			return true
+		}
+	}
+	return false
+}
+
 type DBusResolvedResolver struct {
 	ctx               context.Context
 	logger            logger.ContextLogger
@@ -188,7 +209,7 @@ func (t *DBusResolvedResolver) checkResolved(ctx context.Context) (*ResolvedObje
 		int32(defaultInterface.Index),
 	)
 	if call.Err != nil {
-		return nil, err
+		return nil, call.Err
 	}
 	var linkPath dbus.ObjectPath
 	err = call.Store(&linkPath)
@@ -214,15 +235,12 @@ func (t *DBusResolvedResolver) checkResolved(ctx context.Context) (*ResolvedObje
 				return nil, E.New("No appropriate name servers or networks for name found")
 			}
 		}
-		return &ResolvedObject{
-			BusObject: dbusObject,
-		}, nil
-	} else {
-		return &ResolvedObject{
-			BusObject:      dbusObject,
-			InterfaceIndex: int32(defaultInterface.Index),
-		}, nil
+		return nil, E.New("link has no DNS servers configured")
 	}
+	return &ResolvedObject{
+		BusObject:      dbusObject,
+		InterfaceIndex: int32(defaultInterface.Index),
+	}, nil
 }
 
 func (t *DBusResolvedResolver) updateDefaultInterface(defaultInterface *control.Interface, flags int) {

+ 4 - 0
dns/transport/local/local_resolved_stub.go

@@ -9,6 +9,10 @@ import (
 	"github.com/sagernet/sing/common/logger"
 )
 
+func isSystemdResolvedManaged() bool {
+	return false
+}
+
 func NewResolvedResolver(ctx context.Context, logger logger.ContextLogger) (ResolvedResolver, error) {
 	return nil, os.ErrInvalid
 }