diff --git a/component/resolver/host.go b/component/resolver/host.go index 3b7e9a37..d6eb5873 100644 --- a/component/resolver/host.go +++ b/component/resolver/host.go @@ -4,6 +4,7 @@ import ( "errors" "net/netip" "strings" + _ "unsafe" "github.com/Dreamacro/clash/common/utils" "github.com/Dreamacro/clash/component/trie" @@ -20,28 +21,39 @@ func NewHosts(hosts *trie.DomainTrie[HostValue]) Hosts { } } +// lookupStaticHost looks up the addresses and the canonical name for the given host from /etc/hosts. +// +//go:linkname lookupStaticHost net.lookupStaticHost +func lookupStaticHost(host string) ([]string, string) + // Return the search result and whether to match the parameter `isDomain` func (h *Hosts) Search(domain string, isDomain bool) (*HostValue, bool) { - value := h.DomainTrie.Search(domain) - if value == nil { - return nil, false - } - hostValue := value.Data() - for { - if isDomain && hostValue.IsDomain { - return &hostValue, true - } else { - if node := h.DomainTrie.Search(hostValue.Domain); node != nil { - hostValue = node.Data() + if value := h.DomainTrie.Search(domain); value != nil { + hostValue := value.Data() + for { + if isDomain && hostValue.IsDomain { + return &hostValue, true } else { - break + if node := h.DomainTrie.Search(hostValue.Domain); node != nil { + hostValue = node.Data() + } else { + break + } } } + if isDomain == hostValue.IsDomain { + return &hostValue, true + } + + return &hostValue, false } - if isDomain == hostValue.IsDomain { - return &hostValue, true + if !isDomain { + addr, _ := lookupStaticHost(domain) + if hostValue, err := NewHostValue(addr); err == nil { + return &hostValue, true + } } - return &hostValue, false + return nil, false } type HostValue struct { diff --git a/component/resolver/host_windows.go b/component/resolver/host_windows.go new file mode 100644 index 00000000..669f9547 --- /dev/null +++ b/component/resolver/host_windows.go @@ -0,0 +1,19 @@ +//go:build !go1.22 + +// a simple standard lib fix from: https://github.com/golang/go/commit/33d4a5105cf2b2d549922e909e9239a48b8cefcc + +package resolver + +import ( + "golang.org/x/sys/windows" + _ "unsafe" +) + +//go:linkname testHookHostsPath net.testHookHostsPath +var testHookHostsPath string + +func init() { + if dir, err := windows.GetSystemDirectory(); err == nil { + testHookHostsPath = dir + "/Drivers/etc/hosts" + } +}