mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2024-12-22 23:57:26 +08:00
feat: add direct-nameserver
and direct-nameserver-follow-policy
in dns
section
This commit is contained in:
parent
4a16d22398
commit
c63a851bba
@ -32,7 +32,7 @@ func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata, opts ...
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
opts = append(opts, dialer.WithResolver(resolver.DefaultResolver))
|
||||
opts = append(opts, dialer.WithResolver(resolver.DirectHostResolver))
|
||||
c, err := dialer.DialContext(ctx, "tcp", metadata.RemoteAddress(), d.Base.DialOptions(opts...)...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -49,7 +49,7 @@ func (d *Direct) ListenPacketContext(ctx context.Context, metadata *C.Metadata,
|
||||
}
|
||||
// net.UDPConn.WriteTo only working with *net.UDPAddr, so we need a net.UDPAddr
|
||||
if !metadata.Resolved() {
|
||||
ip, err := resolver.ResolveIPWithResolver(ctx, metadata.Host, resolver.DefaultResolver)
|
||||
ip, err := resolver.ResolveIPWithResolver(ctx, metadata.Host, resolver.DirectHostResolver)
|
||||
if err != nil {
|
||||
return nil, errors.New("can't resolve ip")
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ func resolveUDPAddr(ctx context.Context, network, address string) (*net.UDPAddr,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ip, err := resolver.ResolveProxyServerHost(ctx, host)
|
||||
ip, err := resolver.ResolveIPWithResolver(ctx, host, resolver.ProxyServerHostResolver)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -71,12 +71,12 @@ func resolveUDPAddrWithPrefer(ctx context.Context, network, address string, pref
|
||||
var fallback netip.Addr
|
||||
switch prefer {
|
||||
case C.IPv4Only:
|
||||
ip, err = resolver.ResolveIPv4ProxyServerHost(ctx, host)
|
||||
ip, err = resolver.ResolveIPv4WithResolver(ctx, host, resolver.ProxyServerHostResolver)
|
||||
case C.IPv6Only:
|
||||
ip, err = resolver.ResolveIPv6ProxyServerHost(ctx, host)
|
||||
ip, err = resolver.ResolveIPv6WithResolver(ctx, host, resolver.ProxyServerHostResolver)
|
||||
case C.IPv6Prefer:
|
||||
var ips []netip.Addr
|
||||
ips, err = resolver.LookupIPProxyServerHost(ctx, host)
|
||||
ips, err = resolver.LookupIPWithResolver(ctx, host, resolver.ProxyServerHostResolver)
|
||||
if err == nil {
|
||||
for _, addr := range ips {
|
||||
if addr.Is6() {
|
||||
@ -92,7 +92,7 @@ func resolveUDPAddrWithPrefer(ctx context.Context, network, address string, pref
|
||||
default:
|
||||
// C.IPv4Prefer, C.DualStack and other
|
||||
var ips []netip.Addr
|
||||
ips, err = resolver.LookupIPProxyServerHost(ctx, host)
|
||||
ips, err = resolver.LookupIPWithResolver(ctx, host, resolver.ProxyServerHostResolver)
|
||||
if err == nil {
|
||||
for _, addr := range ips {
|
||||
if addr.Is4() {
|
||||
|
@ -44,7 +44,7 @@ type WireGuard struct {
|
||||
device wireguardGoDevice
|
||||
tunDevice wireguard.Device
|
||||
dialer proxydialer.SingDialer
|
||||
resolver *dns.Resolver
|
||||
resolver resolver.Resolver
|
||||
refP *refProxyAdapter
|
||||
|
||||
initOk atomic.Bool
|
||||
@ -296,7 +296,7 @@ func NewWireGuard(option WireGuardOption) (*WireGuard, error) {
|
||||
for i := range nss {
|
||||
nss[i].ProxyAdapter = refP
|
||||
}
|
||||
outbound.resolver, _ = dns.NewResolver(dns.Config{
|
||||
outbound.resolver = dns.NewResolver(dns.Config{
|
||||
Main: nss,
|
||||
IPv6: has6,
|
||||
})
|
||||
|
@ -340,26 +340,18 @@ func parseAddr(ctx context.Context, network, address string, preferResolver reso
|
||||
return nil, "-1", err
|
||||
}
|
||||
|
||||
if preferResolver == nil {
|
||||
preferResolver = resolver.ProxyServerHostResolver
|
||||
}
|
||||
|
||||
var ips []netip.Addr
|
||||
switch network {
|
||||
case "tcp4", "udp4":
|
||||
if preferResolver == nil {
|
||||
ips, err = resolver.LookupIPv4ProxyServerHost(ctx, host)
|
||||
} else {
|
||||
ips, err = resolver.LookupIPv4WithResolver(ctx, host, preferResolver)
|
||||
}
|
||||
ips, err = resolver.LookupIPv4WithResolver(ctx, host, preferResolver)
|
||||
case "tcp6", "udp6":
|
||||
if preferResolver == nil {
|
||||
ips, err = resolver.LookupIPv6ProxyServerHost(ctx, host)
|
||||
} else {
|
||||
ips, err = resolver.LookupIPv6WithResolver(ctx, host, preferResolver)
|
||||
}
|
||||
ips, err = resolver.LookupIPv6WithResolver(ctx, host, preferResolver)
|
||||
default:
|
||||
if preferResolver == nil {
|
||||
ips, err = resolver.LookupIPProxyServerHost(ctx, host)
|
||||
} else {
|
||||
ips, err = resolver.LookupIPWithResolver(ctx, host, preferResolver)
|
||||
}
|
||||
ips, err = resolver.LookupIPWithResolver(ctx, host, preferResolver)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, "-1", fmt.Errorf("dns resolve failed: %w", err)
|
||||
|
@ -19,9 +19,12 @@ var (
|
||||
// DefaultResolver aim to resolve ip
|
||||
DefaultResolver Resolver
|
||||
|
||||
// ProxyServerHostResolver resolve ip to proxies server host
|
||||
// ProxyServerHostResolver resolve ip for proxies server host, only nil when DefaultResolver is nil
|
||||
ProxyServerHostResolver Resolver
|
||||
|
||||
// DirectHostResolver resolve ip for direct outbound host, only nil when DefaultResolver is nil
|
||||
DirectHostResolver Resolver
|
||||
|
||||
// SystemResolver always using system dns, and was init in dns module
|
||||
SystemResolver Resolver
|
||||
|
||||
@ -193,58 +196,10 @@ func ResolveIP(ctx context.Context, host string) (netip.Addr, error) {
|
||||
return ResolveIPWithResolver(ctx, host, DefaultResolver)
|
||||
}
|
||||
|
||||
// ResolveIPv4ProxyServerHost proxies server host only
|
||||
func ResolveIPv4ProxyServerHost(ctx context.Context, host string) (netip.Addr, error) {
|
||||
if ProxyServerHostResolver != nil {
|
||||
return ResolveIPv4WithResolver(ctx, host, ProxyServerHostResolver)
|
||||
}
|
||||
return ResolveIPv4(ctx, host)
|
||||
}
|
||||
|
||||
// ResolveIPv6ProxyServerHost proxies server host only
|
||||
func ResolveIPv6ProxyServerHost(ctx context.Context, host string) (netip.Addr, error) {
|
||||
if ProxyServerHostResolver != nil {
|
||||
return ResolveIPv6WithResolver(ctx, host, ProxyServerHostResolver)
|
||||
}
|
||||
return ResolveIPv6(ctx, host)
|
||||
}
|
||||
|
||||
// ResolveProxyServerHost proxies server host only
|
||||
func ResolveProxyServerHost(ctx context.Context, host string) (netip.Addr, error) {
|
||||
if ProxyServerHostResolver != nil {
|
||||
return ResolveIPWithResolver(ctx, host, ProxyServerHostResolver)
|
||||
}
|
||||
return ResolveIP(ctx, host)
|
||||
}
|
||||
|
||||
func LookupIPv6ProxyServerHost(ctx context.Context, host string) ([]netip.Addr, error) {
|
||||
if ProxyServerHostResolver != nil {
|
||||
return LookupIPv6WithResolver(ctx, host, ProxyServerHostResolver)
|
||||
}
|
||||
return LookupIPv6(ctx, host)
|
||||
}
|
||||
|
||||
func LookupIPv4ProxyServerHost(ctx context.Context, host string) ([]netip.Addr, error) {
|
||||
if ProxyServerHostResolver != nil {
|
||||
return LookupIPv4WithResolver(ctx, host, ProxyServerHostResolver)
|
||||
}
|
||||
return LookupIPv4(ctx, host)
|
||||
}
|
||||
|
||||
func LookupIPProxyServerHost(ctx context.Context, host string) ([]netip.Addr, error) {
|
||||
if ProxyServerHostResolver != nil {
|
||||
return LookupIPWithResolver(ctx, host, ProxyServerHostResolver)
|
||||
}
|
||||
return LookupIP(ctx, host)
|
||||
}
|
||||
|
||||
func ResetConnection() {
|
||||
if DefaultResolver != nil {
|
||||
go DefaultResolver.ResetConnection()
|
||||
}
|
||||
if ProxyServerHostResolver != nil {
|
||||
go ProxyServerHostResolver.ResetConnection()
|
||||
}
|
||||
}
|
||||
|
||||
func SortationAddr(ips []netip.Addr) (ipv4s, ipv6s []netip.Addr) {
|
||||
|
@ -160,6 +160,8 @@ type DNS struct {
|
||||
Hosts *trie.DomainTrie[resolver.HostValue]
|
||||
NameServerPolicy []dns.Policy
|
||||
ProxyServerNameserver []dns.NameServer
|
||||
DirectNameServer []dns.NameServer
|
||||
DirectFollowPolicy bool
|
||||
}
|
||||
|
||||
// Profile config
|
||||
@ -203,25 +205,27 @@ type RawCors struct {
|
||||
}
|
||||
|
||||
type RawDNS struct {
|
||||
Enable bool `yaml:"enable" json:"enable"`
|
||||
PreferH3 bool `yaml:"prefer-h3" json:"prefer-h3"`
|
||||
IPv6 bool `yaml:"ipv6" json:"ipv6"`
|
||||
IPv6Timeout uint `yaml:"ipv6-timeout" json:"ipv6-timeout"`
|
||||
UseHosts bool `yaml:"use-hosts" json:"use-hosts"`
|
||||
UseSystemHosts bool `yaml:"use-system-hosts" json:"use-system-hosts"`
|
||||
RespectRules bool `yaml:"respect-rules" json:"respect-rules"`
|
||||
NameServer []string `yaml:"nameserver" json:"nameserver"`
|
||||
Fallback []string `yaml:"fallback" json:"fallback"`
|
||||
FallbackFilter RawFallbackFilter `yaml:"fallback-filter" json:"fallback-filter"`
|
||||
Listen string `yaml:"listen" json:"listen"`
|
||||
EnhancedMode C.DNSMode `yaml:"enhanced-mode" json:"enhanced-mode"`
|
||||
FakeIPRange string `yaml:"fake-ip-range" json:"fake-ip-range"`
|
||||
FakeIPFilter []string `yaml:"fake-ip-filter" json:"fake-ip-filter"`
|
||||
FakeIPFilterMode C.FilterMode `yaml:"fake-ip-filter-mode" json:"fake-ip-filter-mode"`
|
||||
DefaultNameserver []string `yaml:"default-nameserver" json:"default-nameserver"`
|
||||
CacheAlgorithm string `yaml:"cache-algorithm" json:"cache-algorithm"`
|
||||
NameServerPolicy *orderedmap.OrderedMap[string, any] `yaml:"nameserver-policy" json:"nameserver-policy"`
|
||||
ProxyServerNameserver []string `yaml:"proxy-server-nameserver" json:"proxy-server-nameserver"`
|
||||
Enable bool `yaml:"enable" json:"enable"`
|
||||
PreferH3 bool `yaml:"prefer-h3" json:"prefer-h3"`
|
||||
IPv6 bool `yaml:"ipv6" json:"ipv6"`
|
||||
IPv6Timeout uint `yaml:"ipv6-timeout" json:"ipv6-timeout"`
|
||||
UseHosts bool `yaml:"use-hosts" json:"use-hosts"`
|
||||
UseSystemHosts bool `yaml:"use-system-hosts" json:"use-system-hosts"`
|
||||
RespectRules bool `yaml:"respect-rules" json:"respect-rules"`
|
||||
NameServer []string `yaml:"nameserver" json:"nameserver"`
|
||||
Fallback []string `yaml:"fallback" json:"fallback"`
|
||||
FallbackFilter RawFallbackFilter `yaml:"fallback-filter" json:"fallback-filter"`
|
||||
Listen string `yaml:"listen" json:"listen"`
|
||||
EnhancedMode C.DNSMode `yaml:"enhanced-mode" json:"enhanced-mode"`
|
||||
FakeIPRange string `yaml:"fake-ip-range" json:"fake-ip-range"`
|
||||
FakeIPFilter []string `yaml:"fake-ip-filter" json:"fake-ip-filter"`
|
||||
FakeIPFilterMode C.FilterMode `yaml:"fake-ip-filter-mode" json:"fake-ip-filter-mode"`
|
||||
DefaultNameserver []string `yaml:"default-nameserver" json:"default-nameserver"`
|
||||
CacheAlgorithm string `yaml:"cache-algorithm" json:"cache-algorithm"`
|
||||
NameServerPolicy *orderedmap.OrderedMap[string, any] `yaml:"nameserver-policy" json:"nameserver-policy"`
|
||||
ProxyServerNameserver []string `yaml:"proxy-server-nameserver" json:"proxy-server-nameserver"`
|
||||
DirectNameServer []string `yaml:"direct-nameserver" json:"direct-nameserver"`
|
||||
DirectNameServerFollowPolicy bool `yaml:"direct-nameserver-follow-policy" json:"direct-nameserver-follow-policy"`
|
||||
}
|
||||
|
||||
type RawFallbackFilter struct {
|
||||
@ -1423,6 +1427,11 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie[resolver.HostValue], rul
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if dnsCfg.DirectNameServer, err = parseNameServer(cfg.DirectNameServer, false, cfg.PreferH3); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dnsCfg.DirectFollowPolicy = cfg.DirectNameServerFollowPolicy
|
||||
|
||||
if len(cfg.DefaultNameserver) == 0 {
|
||||
return nil, errors.New("default nameserver should have at least one nameserver")
|
||||
}
|
||||
|
@ -12,9 +12,6 @@ func FlushCacheWithDefaultResolver() {
|
||||
if r := resolver.DefaultResolver; r != nil {
|
||||
r.ClearCache()
|
||||
}
|
||||
if r := resolver.ProxyServerHostResolver; r != nil {
|
||||
r.ClearCache()
|
||||
}
|
||||
if r := resolver.SystemResolver; r != nil {
|
||||
r.ClearCache()
|
||||
}
|
||||
|
@ -427,6 +427,8 @@ type Config struct {
|
||||
Main, Fallback []NameServer
|
||||
Default []NameServer
|
||||
ProxyServer []NameServer
|
||||
DirectServer []NameServer
|
||||
DirectFollowPolicy bool
|
||||
IPv6 bool
|
||||
IPv6Timeout uint
|
||||
EnhancedMode C.DNSMode
|
||||
@ -446,7 +448,25 @@ func (config Config) newCache() dnsCache {
|
||||
}
|
||||
}
|
||||
|
||||
func NewResolver(config Config) (r *Resolver, pr *Resolver) {
|
||||
type Resolvers struct {
|
||||
*Resolver
|
||||
ProxyResolver *Resolver
|
||||
DirectResolver *Resolver
|
||||
}
|
||||
|
||||
func (rs Resolvers) ClearCache() {
|
||||
rs.Resolver.ClearCache()
|
||||
rs.ProxyResolver.ClearCache()
|
||||
rs.DirectResolver.ClearCache()
|
||||
}
|
||||
|
||||
func (rs Resolvers) ResetConnection() {
|
||||
rs.Resolver.ResetConnection()
|
||||
rs.ProxyResolver.ResetConnection()
|
||||
rs.DirectResolver.ResetConnection()
|
||||
}
|
||||
|
||||
func NewResolver(config Config) (rs Resolvers) {
|
||||
defaultResolver := &Resolver{
|
||||
main: transform(config.Default, nil),
|
||||
cache: config.newCache(),
|
||||
@ -480,7 +500,7 @@ func NewResolver(config Config) (r *Resolver, pr *Resolver) {
|
||||
return
|
||||
}
|
||||
|
||||
r = &Resolver{
|
||||
r := &Resolver{
|
||||
ipv6: config.IPv6,
|
||||
main: cacheTransform(config.Main),
|
||||
cache: config.newCache(),
|
||||
@ -488,9 +508,10 @@ func NewResolver(config Config) (r *Resolver, pr *Resolver) {
|
||||
ipv6Timeout: time.Duration(config.IPv6Timeout) * time.Millisecond,
|
||||
}
|
||||
r.defaultResolver = defaultResolver
|
||||
rs.Resolver = r
|
||||
|
||||
if len(config.ProxyServer) != 0 {
|
||||
pr = &Resolver{
|
||||
rs.ProxyResolver = &Resolver{
|
||||
ipv6: config.IPv6,
|
||||
main: cacheTransform(config.ProxyServer),
|
||||
cache: config.newCache(),
|
||||
@ -499,8 +520,20 @@ func NewResolver(config Config) (r *Resolver, pr *Resolver) {
|
||||
}
|
||||
}
|
||||
|
||||
if len(config.DirectServer) != 0 {
|
||||
rs.DirectResolver = &Resolver{
|
||||
ipv6: config.IPv6,
|
||||
main: cacheTransform(config.DirectServer),
|
||||
cache: config.newCache(),
|
||||
hosts: config.Hosts,
|
||||
ipv6Timeout: time.Duration(config.IPv6Timeout) * time.Millisecond,
|
||||
}
|
||||
}
|
||||
|
||||
if len(config.Fallback) != 0 {
|
||||
r.fallback = cacheTransform(config.Fallback)
|
||||
r.fallbackIPFilters = config.FallbackIPFilter
|
||||
r.fallbackDomainFilters = config.FallbackDomainFilter
|
||||
}
|
||||
|
||||
if len(config.Policy) != 0 {
|
||||
@ -529,9 +562,11 @@ func NewResolver(config Config) (r *Resolver, pr *Resolver) {
|
||||
}
|
||||
}
|
||||
insertPolicy(nil)
|
||||
|
||||
if rs.DirectResolver != nil && config.DirectFollowPolicy {
|
||||
rs.DirectResolver.policy = r.policy
|
||||
}
|
||||
}
|
||||
r.fallbackIPFilters = config.FallbackIPFilter
|
||||
r.fallbackDomainFilters = config.FallbackDomainFilter
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ func newSystemClient() *systemClient {
|
||||
}
|
||||
|
||||
func init() {
|
||||
r, _ := NewResolver(Config{})
|
||||
r := NewResolver(Config{})
|
||||
c := newSystemClient()
|
||||
c.defaultNS = transform([]NameServer{{Addr: "114.114.114.114:53"}, {Addr: "8.8.8.8:53"}}, nil)
|
||||
r.main = []dnsClient{c}
|
||||
|
@ -294,10 +294,15 @@ dns:
|
||||
# - tcp://1.1.1.1
|
||||
# - 'tcp://1.1.1.1#ProxyGroupName' # 指定 DNS 过代理查询,ProxyGroupName 为策略组名或节点名,过代理配置优先于配置出口网卡,当找不到策略组或节点名则设置为出口网卡
|
||||
|
||||
# 专用于节点域名解析的 DNS 服务器,非必要配置项
|
||||
# 专用于节点域名解析的 DNS 服务器,非必要配置项,如果不填则遵循nameserver-policy、nameserver和fallback的配置
|
||||
# proxy-server-nameserver:
|
||||
# - https://dns.google/dns-query
|
||||
# - tls://one.one.one.one
|
||||
# - https://dns.google/dns-query
|
||||
# - tls://one.one.one.one
|
||||
|
||||
# 专用于direct出口域名解析的 DNS 服务器,非必要配置项,如果不填则遵循nameserver-policy、nameserver和fallback的配置
|
||||
# direct-nameserver:
|
||||
# - system://
|
||||
# direct-nameserver-follow-policy: false # 是否遵循nameserver-policy,默认为不遵守,仅当direct-nameserver不为空时生效
|
||||
|
||||
# 配置 fallback 使用条件
|
||||
# fallback-filter:
|
||||
|
@ -235,6 +235,8 @@ func updateDNS(c *config.DNS, generalIPv6 bool) {
|
||||
resolver.DefaultResolver = nil
|
||||
resolver.DefaultHostMapper = nil
|
||||
resolver.DefaultLocalServer = nil
|
||||
resolver.ProxyServerHostResolver = nil
|
||||
resolver.DirectHostResolver = nil
|
||||
dns.ReCreateServer("", nil, nil)
|
||||
return
|
||||
}
|
||||
@ -251,10 +253,12 @@ func updateDNS(c *config.DNS, generalIPv6 bool) {
|
||||
Default: c.DefaultNameserver,
|
||||
Policy: c.NameServerPolicy,
|
||||
ProxyServer: c.ProxyServerNameserver,
|
||||
DirectServer: c.DirectNameServer,
|
||||
DirectFollowPolicy: c.DirectFollowPolicy,
|
||||
CacheAlgorithm: c.CacheAlgorithm,
|
||||
}
|
||||
|
||||
r, pr := dns.NewResolver(cfg)
|
||||
r := dns.NewResolver(cfg)
|
||||
m := dns.NewEnhancer(cfg)
|
||||
|
||||
// reuse cache of old host mapper
|
||||
@ -264,14 +268,22 @@ func updateDNS(c *config.DNS, generalIPv6 bool) {
|
||||
|
||||
resolver.DefaultResolver = r
|
||||
resolver.DefaultHostMapper = m
|
||||
resolver.DefaultLocalServer = dns.NewLocalServer(r, m)
|
||||
resolver.DefaultLocalServer = dns.NewLocalServer(r.Resolver, m)
|
||||
resolver.UseSystemHosts = c.UseSystemHosts
|
||||
|
||||
if pr.Invalid() {
|
||||
resolver.ProxyServerHostResolver = pr
|
||||
if r.ProxyResolver.Invalid() {
|
||||
resolver.ProxyServerHostResolver = r.ProxyResolver
|
||||
} else {
|
||||
resolver.ProxyServerHostResolver = r.Resolver
|
||||
}
|
||||
|
||||
dns.ReCreateServer(c.Listen, r, m)
|
||||
if r.DirectResolver.Invalid() {
|
||||
resolver.DirectHostResolver = r.DirectResolver
|
||||
} else {
|
||||
resolver.DirectHostResolver = r.Resolver
|
||||
}
|
||||
|
||||
dns.ReCreateServer(c.Listen, r.Resolver, m)
|
||||
}
|
||||
|
||||
func updateHosts(tree *trie.DomainTrie[resolver.HostValue]) {
|
||||
|
Loading…
Reference in New Issue
Block a user