From 67d04485ca7c3120f3faf1918d7a0ae94e756d5a Mon Sep 17 00:00:00 2001 From: gVisor bot Date: Mon, 28 Mar 2022 00:44:13 +0800 Subject: [PATCH] Refactor: MainResolver --- adapter/outbound/direct.go | 2 + adapter/outbound/util.go | 2 +- component/dialer/dialer.go | 22 ++++----- component/dialer/options.go | 7 +++ component/resolver/resolver.go | 89 +++++++++++++++++++++------------- config/config.go | 52 +++++++++++--------- dns/resolver.go | 15 +++++- hub/executor/executor.go | 14 ++++-- 8 files changed, 128 insertions(+), 75 deletions(-) diff --git a/adapter/outbound/direct.go b/adapter/outbound/direct.go index 4c4305f5..61eb4571 100644 --- a/adapter/outbound/direct.go +++ b/adapter/outbound/direct.go @@ -14,6 +14,7 @@ type Direct struct { // DialContext implements C.ProxyAdapter func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) { + opts = append(opts, dialer.WithDirect()) c, err := dialer.DialContext(ctx, "tcp", metadata.RemoteAddress(), d.Base.DialOptions(opts...)...) if err != nil { return nil, err @@ -24,6 +25,7 @@ func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata, opts ... // ListenPacketContext implements C.ProxyAdapter func (d *Direct) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) { + opts = append(opts, dialer.WithDirect()) pc, err := dialer.ListenPacket(ctx, "udp", "", d.Base.DialOptions(opts...)...) if err != nil { return nil, err diff --git a/adapter/outbound/util.go b/adapter/outbound/util.go index b376522f..9322adc5 100644 --- a/adapter/outbound/util.go +++ b/adapter/outbound/util.go @@ -44,7 +44,7 @@ func resolveUDPAddr(network, address string) (*net.UDPAddr, error) { return nil, err } - ip, err := resolver.ResolveIP(host) + ip, err := resolver.ResolveProxyServerHost(host) if err != nil { return nil, err } diff --git a/component/dialer/dialer.go b/component/dialer/dialer.go index 09254c58..19a5fdd2 100644 --- a/component/dialer/dialer.go +++ b/component/dialer/dialer.go @@ -32,14 +32,14 @@ func DialContext(ctx context.Context, network, address string, options ...Option var ip net.IP switch network { case "tcp4", "udp4": - if opt.interfaceName != "" { - ip, err = resolver.ResolveIPv4WithMain(host) + if !opt.direct { + ip, err = resolver.ResolveIPv4ProxyServerHost(host) } else { ip, err = resolver.ResolveIPv4(host) } default: - if opt.interfaceName != "" { - ip, err = resolver.ResolveIPv6WithMain(host) + if !opt.direct { + ip, err = resolver.ResolveIPv6ProxyServerHost(host) } else { ip, err = resolver.ResolveIPv6(host) } @@ -121,7 +121,7 @@ func dualStackDialContext(ctx context.Context, network, address string, opt *opt results := make(chan dialResult) var primary, fallback dialResult - startRacer := func(ctx context.Context, network, host string, ipv6 bool) { + startRacer := func(ctx context.Context, network, host string, direct bool, ipv6 bool) { result := dialResult{ipv6: ipv6, done: true} defer func() { select { @@ -135,14 +135,14 @@ func dualStackDialContext(ctx context.Context, network, address string, opt *opt var ip net.IP if ipv6 { - if opt.interfaceName != "" { - ip, result.error = resolver.ResolveIPv6WithMain(host) + if !direct { + ip, result.error = resolver.ResolveIPv6ProxyServerHost(host) } else { ip, result.error = resolver.ResolveIPv6(host) } } else { - if opt.interfaceName != "" { - ip, result.error = resolver.ResolveIPv4WithMain(host) + if !direct { + ip, result.error = resolver.ResolveIPv4ProxyServerHost(host) } else { ip, result.error = resolver.ResolveIPv4(host) } @@ -155,8 +155,8 @@ func dualStackDialContext(ctx context.Context, network, address string, opt *opt result.Conn, result.error = dialContext(ctx, network, ip, port, opt) } - go startRacer(ctx, network+"4", host, false) - go startRacer(ctx, network+"6", host, true) + go startRacer(ctx, network+"4", host, opt.direct, false) + go startRacer(ctx, network+"6", host, opt.direct, true) for res := range results { if res.error == nil { diff --git a/component/dialer/options.go b/component/dialer/options.go index 2d884094..2985dc7b 100644 --- a/component/dialer/options.go +++ b/component/dialer/options.go @@ -12,6 +12,7 @@ type option struct { interfaceName string addrReuse bool routingMark int + direct bool } type Option func(opt *option) @@ -33,3 +34,9 @@ func WithRoutingMark(mark int) Option { opt.routingMark = mark } } + +func WithDirect() Option { + return func(opt *option) { + opt.direct = true + } +} diff --git a/component/resolver/resolver.go b/component/resolver/resolver.go index a7300bd7..e1100a31 100644 --- a/component/resolver/resolver.go +++ b/component/resolver/resolver.go @@ -15,8 +15,8 @@ var ( // DefaultResolver aim to resolve ip DefaultResolver Resolver - // MainResolver resolve ip with main domain server - MainResolver Resolver + // ProxyServerHostResolver resolve ip to proxies server host + ProxyServerHostResolver Resolver // DisableIPv6 means don't resolve ipv6 host // default value is true @@ -46,10 +46,6 @@ func ResolveIPv4(host string) (net.IP, error) { return ResolveIPv4WithResolver(host, DefaultResolver) } -func ResolveIPv4WithMain(host string) (net.IP, error) { - return ResolveIPv4WithResolver(host, MainResolver) -} - func ResolveIPv4WithResolver(host string, r Resolver) (net.IP, error) { if node := DefaultHosts.Search(host); node != nil { if ip := node.Data.(net.IP).To4(); ip != nil { @@ -69,16 +65,20 @@ func ResolveIPv4WithResolver(host string, r Resolver) (net.IP, error) { return r.ResolveIPv4(host) } - ctx, cancel := context.WithTimeout(context.Background(), DefaultDNSTimeout) - defer cancel() - ipAddrs, err := net.DefaultResolver.LookupIP(ctx, "ip4", host) - if err != nil { - return nil, err - } else if len(ipAddrs) == 0 { - return nil, ErrIPNotFound + if DefaultResolver == nil { + ctx, cancel := context.WithTimeout(context.Background(), DefaultDNSTimeout) + defer cancel() + ipAddrs, err := net.DefaultResolver.LookupIP(ctx, "ip4", host) + if err != nil { + return nil, err + } else if len(ipAddrs) == 0 { + return nil, ErrIPNotFound + } + + return ipAddrs[rand.Intn(len(ipAddrs))], nil } - return ipAddrs[rand.Intn(len(ipAddrs))], nil + return nil, ErrIPNotFound } // ResolveIPv6 with a host, return ipv6 @@ -86,10 +86,6 @@ func ResolveIPv6(host string) (net.IP, error) { return ResolveIPv6WithResolver(host, DefaultResolver) } -func ResolveIPv6WithMain(host string) (net.IP, error) { - return ResolveIPv6WithResolver(host, MainResolver) -} - func ResolveIPv6WithResolver(host string, r Resolver) (net.IP, error) { if DisableIPv6 { return nil, ErrIPv6Disabled @@ -113,16 +109,20 @@ func ResolveIPv6WithResolver(host string, r Resolver) (net.IP, error) { return r.ResolveIPv6(host) } - ctx, cancel := context.WithTimeout(context.Background(), DefaultDNSTimeout) - defer cancel() - ipAddrs, err := net.DefaultResolver.LookupIP(ctx, "ip6", host) - if err != nil { - return nil, err - } else if len(ipAddrs) == 0 { - return nil, ErrIPNotFound + if DefaultResolver == nil { + ctx, cancel := context.WithTimeout(context.Background(), DefaultDNSTimeout) + defer cancel() + ipAddrs, err := net.DefaultResolver.LookupIP(ctx, "ip6", host) + if err != nil { + return nil, err + } else if len(ipAddrs) == 0 { + return nil, ErrIPNotFound + } + + return ipAddrs[rand.Intn(len(ipAddrs))], nil } - return ipAddrs[rand.Intn(len(ipAddrs))], nil + return nil, ErrIPNotFound } // ResolveIPWithResolver same as ResolveIP, but with a resolver @@ -145,12 +145,16 @@ func ResolveIPWithResolver(host string, r Resolver) (net.IP, error) { return ip, nil } - ipAddr, err := net.ResolveIPAddr("ip", host) - if err != nil { - return nil, err + if DefaultResolver == nil { + ipAddr, err := net.ResolveIPAddr("ip", host) + if err != nil { + return nil, err + } + + return ipAddr.IP, nil } - return ipAddr.IP, nil + return nil, ErrIPNotFound } // ResolveIP with a host, return ip @@ -158,7 +162,26 @@ func ResolveIP(host string) (net.IP, error) { return ResolveIPWithResolver(host, DefaultResolver) } -// ResolveIPWithMainResolver with a host, use main resolver, return ip -func ResolveIPWithMainResolver(host string) (net.IP, error) { - return ResolveIPWithResolver(host, MainResolver) +// ResolveIPv4ProxyServerHost proxies server host only +func ResolveIPv4ProxyServerHost(host string) (net.IP, error) { + if ProxyServerHostResolver != nil { + return ResolveIPv4WithResolver(host, ProxyServerHostResolver) + } + return ResolveIPv4(host) +} + +// ResolveIPv6ProxyServerHost proxies server host only +func ResolveIPv6ProxyServerHost(host string) (net.IP, error) { + if ProxyServerHostResolver != nil { + return ResolveIPv6WithResolver(host, ProxyServerHostResolver) + } + return ResolveIPv6(host) +} + +// ResolveProxyServerHost proxies server host only +func ResolveProxyServerHost(host string) (net.IP, error) { + if ProxyServerHostResolver != nil { + return ResolveIPWithResolver(host, ProxyServerHostResolver) + } + return ResolveIP(host) } diff --git a/config/config.go b/config/config.go index 36c2223a..eedc1959 100644 --- a/config/config.go +++ b/config/config.go @@ -63,17 +63,18 @@ type Controller struct { // DNS config type DNS struct { - Enable bool `yaml:"enable"` - IPv6 bool `yaml:"ipv6"` - NameServer []dns.NameServer `yaml:"nameserver"` - Fallback []dns.NameServer `yaml:"fallback"` - FallbackFilter FallbackFilter `yaml:"fallback-filter"` - Listen string `yaml:"listen"` - EnhancedMode C.DNSMode `yaml:"enhanced-mode"` - DefaultNameserver []dns.NameServer `yaml:"default-nameserver"` - FakeIPRange *fakeip.Pool - Hosts *trie.DomainTrie - NameServerPolicy map[string]dns.NameServer + Enable bool `yaml:"enable"` + IPv6 bool `yaml:"ipv6"` + NameServer []dns.NameServer `yaml:"nameserver"` + Fallback []dns.NameServer `yaml:"fallback"` + FallbackFilter FallbackFilter `yaml:"fallback-filter"` + Listen string `yaml:"listen"` + EnhancedMode C.DNSMode `yaml:"enhanced-mode"` + DefaultNameserver []dns.NameServer `yaml:"default-nameserver"` + FakeIPRange *fakeip.Pool + Hosts *trie.DomainTrie + NameServerPolicy map[string]dns.NameServer + ProxyServerNameserver []dns.NameServer } // FallbackFilter config @@ -125,18 +126,19 @@ type Config struct { } type RawDNS struct { - Enable bool `yaml:"enable"` - IPv6 bool `yaml:"ipv6"` - UseHosts bool `yaml:"use-hosts"` - NameServer []string `yaml:"nameserver"` - Fallback []string `yaml:"fallback"` - FallbackFilter RawFallbackFilter `yaml:"fallback-filter"` - Listen string `yaml:"listen"` - EnhancedMode C.DNSMode `yaml:"enhanced-mode"` - FakeIPRange string `yaml:"fake-ip-range"` - FakeIPFilter []string `yaml:"fake-ip-filter"` - DefaultNameserver []string `yaml:"default-nameserver"` - NameServerPolicy map[string]string `yaml:"nameserver-policy"` + Enable bool `yaml:"enable"` + IPv6 bool `yaml:"ipv6"` + UseHosts bool `yaml:"use-hosts"` + NameServer []string `yaml:"nameserver"` + Fallback []string `yaml:"fallback"` + FallbackFilter RawFallbackFilter `yaml:"fallback-filter"` + Listen string `yaml:"listen"` + EnhancedMode C.DNSMode `yaml:"enhanced-mode"` + FakeIPRange string `yaml:"fake-ip-range"` + FakeIPFilter []string `yaml:"fake-ip-filter"` + DefaultNameserver []string `yaml:"default-nameserver"` + NameServerPolicy map[string]string `yaml:"nameserver-policy"` + ProxyServerNameserver []string `yaml:"proxy-server-nameserver"` } type RawFallbackFilter struct { @@ -679,6 +681,10 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie, rules []C.Rule) (*DNS, return nil, err } + if dnsCfg.ProxyServerNameserver, err = parseNameServer(cfg.ProxyServerNameserver); err != nil { + return nil, err + } + if len(cfg.DefaultNameserver) == 0 { return nil, errors.New("default nameserver should have at least one nameserver") } diff --git a/dns/resolver.go b/dns/resolver.go index f22902d7..4ff12ee8 100644 --- a/dns/resolver.go +++ b/dns/resolver.go @@ -41,6 +41,7 @@ type Resolver struct { group singleflight.Group lruCache *cache.LruCache policy *trie.DomainTrie + proxyServer []dnsClient } // ResolveIP request with TypeA and TypeAAAA, priority return TypeA @@ -301,6 +302,11 @@ func (r *Resolver) asyncExchange(ctx context.Context, client []dnsClient, msg *D return ch } +// HasProxyServer has proxy server dns client +func (r *Resolver) HasProxyServer() bool { + return len(r.main) > 0 +} + type NameServer struct { Net string Addr string @@ -319,6 +325,7 @@ type FallbackFilter struct { type Config struct { Main, Fallback []NameServer Default []NameServer + ProxyServer []NameServer IPv6 bool EnhancedMode C.DNSMode FallbackFilter FallbackFilter @@ -344,6 +351,10 @@ func NewResolver(config Config) *Resolver { r.fallback = transform(config.Fallback, defaultResolver) } + if len(config.ProxyServer) != 0 { + r.proxyServer = transform(config.ProxyServer, defaultResolver) + } + if len(config.Policy) != 0 { r.policy = trie.New() for domain, nameserver := range config.Policy { @@ -377,10 +388,10 @@ func NewResolver(config Config) *Resolver { return r } -func NewMainResolver(old *Resolver) *Resolver { +func NewProxyServerHostResolver(old *Resolver) *Resolver { r := &Resolver{ ipv6: old.ipv6, - main: old.main, + main: old.proxyServer, lruCache: old.lruCache, hosts: old.hosts, policy: old.policy, diff --git a/hub/executor/executor.go b/hub/executor/executor.go index 24b8693e..29096951 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -130,12 +130,13 @@ func updateDNS(c *config.DNS, t *config.Tun) { Domain: c.FallbackFilter.Domain, GeoSite: c.FallbackFilter.GeoSite, }, - Default: c.DefaultNameserver, - Policy: c.NameServerPolicy, + Default: c.DefaultNameserver, + Policy: c.NameServerPolicy, + ProxyServer: c.ProxyServerNameserver, } r := dns.NewResolver(cfg) - mr := dns.NewMainResolver(r) + pr := dns.NewProxyServerHostResolver(r) m := dns.NewEnhancer(cfg) // reuse cache of old host mapper @@ -144,9 +145,12 @@ func updateDNS(c *config.DNS, t *config.Tun) { } resolver.DefaultResolver = r - resolver.MainResolver = mr resolver.DefaultHostMapper = m + if pr.HasProxyServer() { + resolver.ProxyServerHostResolver = pr + } + if t.Enable { resolver.DefaultLocalServer = dns.NewLocalServer(r, m) } @@ -156,9 +160,9 @@ func updateDNS(c *config.DNS, t *config.Tun) { } else { if !t.Enable { resolver.DefaultResolver = nil - resolver.MainResolver = nil resolver.DefaultHostMapper = nil resolver.DefaultLocalServer = nil + resolver.ProxyServerHostResolver = nil } dns.ReCreateServer("", nil, nil) }