瀏覽代碼

Get darwin local DNS server from libresolv

世界 8 月之前
父節點
當前提交
495bdee0aa

+ 1 - 0
dns/transport/local/local.go

@@ -27,6 +27,7 @@ var _ adapter.DNSTransport = (*Transport)(nil)
 
 type Transport struct {
 	dns.TransportAdapter
+	ctx    context.Context
 	hosts  *hosts.File
 	dialer N.Dialer
 }

+ 53 - 0
dns/transport/local/resolv_darwin_cgo.go

@@ -0,0 +1,53 @@
+//go:build darwin && cgo
+
+package local
+
+/*
+#include <stdlib.h>
+#include <stdio.h>
+#include <resolv.h>
+#include <arpa/inet.h>
+*/
+import "C"
+
+import (
+	"time"
+
+	E "github.com/sagernet/sing/common/exceptions"
+
+	"github.com/miekg/dns"
+)
+
+func dnsReadConfig(_ string) *dnsConfig {
+	if C.res_init() != 0 {
+		return &dnsConfig{
+			servers:  defaultNS,
+			search:   dnsDefaultSearch(),
+			ndots:    1,
+			timeout:  5 * time.Second,
+			attempts: 2,
+			err:      E.New("libresolv initialization failed"),
+		}
+	}
+	conf := &dnsConfig{
+		ndots:    1,
+		timeout:  5 * time.Second,
+		attempts: int(C._res.retry),
+	}
+	for i := 0; i < int(C._res.nscount); i++ {
+		ns := C._res.nsaddr_list[i]
+		addr := C.inet_ntoa(ns.sin_addr)
+		if addr == nil {
+			continue
+		}
+		conf.servers = append(conf.servers, C.GoString(addr))
+	}
+	for i := 0; ; i++ {
+		search := C._res.dnsrch[i]
+		if search == nil {
+			break
+		}
+		conf.search = append(conf.search, dns.Fqdn(C.GoString(search)))
+	}
+	return conf
+}

+ 23 - 0
dns/transport/local/resolv_default.go

@@ -0,0 +1,23 @@
+package local
+
+import (
+	"os"
+	"strings"
+	_ "unsafe"
+
+	"github.com/miekg/dns"
+)
+
+//go:linkname defaultNS net.defaultNS
+var defaultNS []string
+
+func dnsDefaultSearch() []string {
+	hn, err := os.Hostname()
+	if err != nil {
+		return nil
+	}
+	if i := strings.IndexRune(hn, '.'); i >= 0 && i < len(hn)-1 {
+		return []string{dns.Fqdn(hn[i+1:])}
+	}
+	return nil
+}

+ 5 - 25
dns/transport/local/resolv_unix.go

@@ -1,4 +1,4 @@
-//go:build !windows
+//go:build !windows && !(darwin && cgo)
 
 package local
 
@@ -9,7 +9,8 @@ import (
 	"os"
 	"strings"
 	"time"
-	_ "unsafe"
+
+	"github.com/miekg/dns"
 )
 
 func dnsReadConfig(name string) *dnsConfig {
@@ -69,13 +70,13 @@ func dnsReadConfig(name string) *dnsConfig {
 			}
 		case "domain":
 			if len(f) > 1 {
-				conf.search = []string{ensureRooted(f[1])}
+				conf.search = []string{dns.Fqdn(f[1])}
 			}
 
 		case "search":
 			conf.search = make([]string, 0, len(f)-1)
 			for i := 1; i < len(f); i++ {
-				name := ensureRooted(f[i])
+				name := dns.Fqdn(f[i])
 				if name == "." {
 					continue
 				}
@@ -137,27 +138,6 @@ func dnsReadConfig(name string) *dnsConfig {
 	return conf
 }
 
-//go:linkname defaultNS net.defaultNS
-var defaultNS []string
-
-func dnsDefaultSearch() []string {
-	hn, err := os.Hostname()
-	if err != nil {
-		return nil
-	}
-	if i := strings.IndexRune(hn, '.'); i >= 0 && i < len(hn)-1 {
-		return []string{ensureRooted(hn[i+1:])}
-	}
-	return nil
-}
-
-func ensureRooted(s string) string {
-	if len(s) > 0 && s[len(s)-1] == '.' {
-		return s
-	}
-	return s + "."
-}
-
 const big = 0xFFFFFF
 
 func dtoi(s string) (n int, i int, ok bool) {

+ 2 - 2
dns/transport_manager.go

@@ -56,12 +56,12 @@ func (m *TransportManager) Start(stage adapter.StartStage) error {
 	}
 	m.started = true
 	m.stage = stage
-	outbounds := m.transports
+	transports := m.transports
 	m.access.Unlock()
 	if stage == adapter.StartStateStart {
 		return m.startTransports(m.transports)
 	} else {
-		for _, outbound := range outbounds {
+		for _, outbound := range transports {
 			err := adapter.LegacyStart(outbound, stage)
 			if err != nil {
 				return E.Cause(err, stage, " dns/", outbound.Type(), "[", outbound.Tag(), "]")

+ 3 - 0
protocol/tun/hook.go

@@ -0,0 +1,3 @@
+package tun
+
+var HookBeforeCreatePlatformInterface func()

+ 3 - 0
protocol/tun/inbound.go

@@ -361,6 +361,9 @@ func (t *Inbound) Start(stage adapter.StartStage) error {
 		if t.platformInterface != nil {
 			tunInterface, err = t.platformInterface.OpenTun(&tunOptions, t.platformOptions)
 		} else {
+			if HookBeforeCreatePlatformInterface != nil {
+				HookBeforeCreatePlatformInterface()
+			}
 			tunInterface, err = tun.New(tunOptions)
 		}
 		monitor.Finish()