Skip to content

Commit

Permalink
feat: add direct-nameserver and direct-nameserver-follow-policy i…
Browse files Browse the repository at this point in the history
…n `dns` section
  • Loading branch information
wwqgtxx committed Oct 4, 2024
1 parent 4a16d22 commit c63a851
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 109 deletions.
4 changes: 2 additions & 2 deletions adapter/outbound/direct.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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")
}
Expand Down
10 changes: 5 additions & 5 deletions adapter/outbound/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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() {
Expand All @@ -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() {
Expand Down
4 changes: 2 additions & 2 deletions adapter/outbound/wireguard.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
})
Expand Down
22 changes: 7 additions & 15 deletions component/dialer/dialer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
53 changes: 4 additions & 49 deletions component/resolver/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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) {
Expand Down
47 changes: 28 additions & 19 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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")
}
Expand Down
3 changes: 0 additions & 3 deletions dns/patch_android.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
Expand Down
45 changes: 40 additions & 5 deletions dns/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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(),
Expand Down Expand Up @@ -480,17 +500,18 @@ func NewResolver(config Config) (r *Resolver, pr *Resolver) {
return
}

r = &Resolver{
r := &Resolver{
ipv6: config.IPv6,
main: cacheTransform(config.Main),
cache: config.newCache(),
hosts: config.Hosts,
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(),
Expand All @@ -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 {
Expand Down Expand Up @@ -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
}
Expand Down
2 changes: 1 addition & 1 deletion dns/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
11 changes: 8 additions & 3 deletions docs/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Loading

0 comments on commit c63a851

Please sign in to comment.