From 002245c92aa6ef3310c0ebe998928990f0b9c77b Mon Sep 17 00:00:00 2001 From: patterniha Date: Sat, 3 May 2025 00:56:40 +0330 Subject: [PATCH] add new QueryStrategy "UseSystem" --- app/dns/config.pb.go | 17 ++++++++++------- app/dns/config.proto | 1 + app/dns/dns.go | 40 ++++++++++++++++++++++++++++++++++++++-- app/dns/nameserver.go | 17 +++++++++++++++-- infra/conf/dns.go | 2 ++ 5 files changed, 66 insertions(+), 11 deletions(-) diff --git a/app/dns/config.pb.go b/app/dns/config.pb.go index e7eb6de5..d54142ce 100644 --- a/app/dns/config.pb.go +++ b/app/dns/config.pb.go @@ -80,6 +80,7 @@ const ( QueryStrategy_USE_IP QueryStrategy = 0 QueryStrategy_USE_IP4 QueryStrategy = 1 QueryStrategy_USE_IP6 QueryStrategy = 2 + QueryStrategy_USE_SYS QueryStrategy = 3 ) // Enum value maps for QueryStrategy. @@ -88,11 +89,13 @@ var ( 0: "USE_IP", 1: "USE_IP4", 2: "USE_IP6", + 3: "USE_SYS", } QueryStrategy_value = map[string]int32{ "USE_IP": 0, "USE_IP4": 1, "USE_IP6": 2, + "USE_SYS": 3, } ) @@ -654,16 +657,16 @@ var file_app_dns_config_proto_rawDesc = []byte{ 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x10, 0x02, 0x12, - 0x09, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x10, 0x03, 0x2a, 0x35, 0x0a, 0x0d, 0x51, 0x75, + 0x09, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x10, 0x03, 0x2a, 0x42, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, - 0x02, 0x42, 0x46, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, - 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x50, 0x01, 0x5a, 0x21, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, - 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0xaa, 0x02, 0x0c, 0x58, 0x72, 0x61, - 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x53, 0x59, 0x53, 0x10, 0x03, 0x42, 0x46, + 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, + 0x6e, 0x73, 0x50, 0x01, 0x5a, 0x21, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, + 0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0xaa, 0x02, 0x0c, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, + 0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/app/dns/config.proto b/app/dns/config.proto index 724f016c..4317d0d7 100644 --- a/app/dns/config.proto +++ b/app/dns/config.proto @@ -48,6 +48,7 @@ enum QueryStrategy { USE_IP = 0; USE_IP4 = 1; USE_IP6 = 2; + USE_SYS = 3; } message Config { diff --git a/app/dns/dns.go b/app/dns/dns.go index 29960817..cb0ad780 100644 --- a/app/dns/dns.go +++ b/app/dns/dns.go @@ -28,6 +28,7 @@ type DNS struct { ctx context.Context domainMatcher strmatcher.IndexMatcher matcherInfos []*DomainMatcherInfo + useSystem bool } // DomainMatcherInfo contains information attached to index returned by Server.domainMatcher @@ -47,6 +48,7 @@ func New(ctx context.Context, config *Config) (*DNS, error) { } var ipOption dns.IPOption + useSystem := false switch config.QueryStrategy { case QueryStrategy_USE_IP: ipOption = dns.IPOption{ @@ -54,6 +56,13 @@ func New(ctx context.Context, config *Config) (*DNS, error) { IPv6Enable: true, FakeEnable: false, } + case QueryStrategy_USE_SYS: + ipOption = dns.IPOption{ + IPv4Enable: true, + IPv6Enable: true, + FakeEnable: false, + } + useSystem = true case QueryStrategy_USE_IP4: ipOption = dns.IPOption{ IPv4Enable: true, @@ -118,6 +127,7 @@ func New(ctx context.Context, config *Config) (*DNS, error) { if !clientIPOption.IPv4Enable && !clientIPOption.IPv6Enable { return nil, errors.New("no QueryStrategy available for ", ns.Address) } + client, err := NewClient(ctx, ns, myClientIP, disableCache, tag, clientIPOption, &matcherInfos, updateDomain) if err != nil { return nil, errors.New("failed to create client").Base(err) @@ -139,6 +149,7 @@ func New(ctx context.Context, config *Config) (*DNS, error) { matcherInfos: matcherInfos, disableFallback: config.DisableFallback, disableFallbackIfMatch: config.DisableFallbackIfMatch, + useSystem: useSystem, }, nil } @@ -179,8 +190,14 @@ func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, uint32, er return nil, 0, errors.New("empty domain name") } - option.IPv4Enable = option.IPv4Enable && s.ipOption.IPv4Enable - option.IPv6Enable = option.IPv6Enable && s.ipOption.IPv6Enable + if s.useSystem { + supportIPv4, supportIPv6 := checkSystemNetwork() + option.IPv4Enable = option.IPv4Enable && supportIPv4 + option.IPv6Enable = option.IPv6Enable && supportIPv6 + } else { + option.IPv4Enable = option.IPv4Enable && s.ipOption.IPv4Enable + option.IPv6Enable = option.IPv6Enable && s.ipOption.IPv6Enable + } if !option.IPv4Enable && !option.IPv6Enable { return nil, 0, dns.ErrEmptyResponse @@ -321,3 +338,22 @@ func init() { return New(ctx, config.(*Config)) })) } + +func checkSystemNetwork() (supportIPv4 bool, supportIPv6 bool) { + conn4, err4 := net.Dial("udp4", "8.8.8.8:53") + if err4 != nil { + supportIPv4 = false + } else { + supportIPv4 = true + conn4.Close() + } + + conn6, err6 := net.Dial("udp6", "[2001:4860:4860::8888]:53") + if err6 != nil { + supportIPv6 = false + } else { + supportIPv6 = true + conn6.Close() + } + return +} diff --git a/app/dns/nameserver.go b/app/dns/nameserver.go index 0abe1ccd..6058f302 100644 --- a/app/dns/nameserver.go +++ b/app/dns/nameserver.go @@ -37,6 +37,7 @@ type Client struct { timeoutMs time.Duration finalQuery bool ipOption *dns.IPOption + useSystem bool } // NewServer creates a name server object according to the network destination url. @@ -186,6 +187,8 @@ func NewClient( timeoutMs = time.Duration(ns.TimeoutMs) * time.Millisecond } + useSystem := ns.QueryStrategy == QueryStrategy_USE_SYS + client.server = server client.skipFallback = ns.SkipFallback client.domains = rules @@ -197,6 +200,7 @@ func NewClient( client.timeoutMs = timeoutMs client.finalQuery = ns.FinalQuery client.ipOption = &ipOption + client.useSystem = useSystem return nil }) return client, err @@ -213,8 +217,15 @@ func (c *Client) IsFinalQuery() bool { // QueryIP sends DNS query to the name server with the client's IP. func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption) ([]net.IP, uint32, error) { - option.IPv4Enable = option.IPv4Enable && c.ipOption.IPv4Enable - option.IPv6Enable = option.IPv6Enable && c.ipOption.IPv6Enable + if c.useSystem { + supportIPv4, supportIPv6 := checkSystemNetwork() + option.IPv4Enable = option.IPv4Enable && supportIPv4 + option.IPv6Enable = option.IPv6Enable && supportIPv6 + } else { + option.IPv4Enable = option.IPv4Enable && c.ipOption.IPv4Enable + option.IPv6Enable = option.IPv6Enable && c.ipOption.IPv6Enable + } + if !option.IPv4Enable && !option.IPv6Enable { return nil, 0, dns.ErrEmptyResponse } @@ -271,6 +282,8 @@ func ResolveIpOptionOverride(queryStrategy QueryStrategy, ipOption dns.IPOption) switch queryStrategy { case QueryStrategy_USE_IP: return ipOption + case QueryStrategy_USE_SYS: + return ipOption case QueryStrategy_USE_IP4: return dns.IPOption{ IPv4Enable: ipOption.IPv4Enable, diff --git a/infra/conf/dns.go b/infra/conf/dns.go index 1ba10806..e1071781 100644 --- a/infra/conf/dns.go +++ b/infra/conf/dns.go @@ -425,6 +425,8 @@ func resolveQueryStrategy(queryStrategy string) dns.QueryStrategy { return dns.QueryStrategy_USE_IP4 case "useip6", "useipv6", "use_ip6", "use_ipv6", "use_ip_v6", "use-ip6", "use-ipv6", "use-ip-v6": return dns.QueryStrategy_USE_IP6 + case "usesys", "usesystem", "use_sys", "use_system", "use-sys", "use-system": + return dns.QueryStrategy_USE_SYS default: return dns.QueryStrategy_USE_IP }