feat: add direct-nameserver and direct-nameserver-follow-policy in dns section

This commit is contained in:
wwqgtxx 2024-10-04 13:19:41 +08:00
parent 4a16d22398
commit c63a851bba
11 changed files with 114 additions and 109 deletions

View File

@ -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")
}

View File

@ -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() {

View File

@ -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,
})

View File

@ -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)

View File

@ -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) {

View File

@ -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")
}

View File

@ -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()
}

View File

@ -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
}

View File

@ -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}

View File

@ -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:

View File

@ -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]) {