@@ -26,14 +26,18 @@ type Server interface {
2626
2727// Client is the interface for DNS client.
2828type Client struct {
29- server Server
30- skipFallback bool
31- domains []string
32- expectedIPs []* router.GeoIPMatcher
33- allowUnexpectedIPs bool
34- tag string
35- timeoutMs time.Duration
36- ipOption * dns.IPOption
29+ server Server
30+ skipFallback bool
31+ domains []string
32+ expectedIPs []* router.GeoIPMatcher
33+ unexpectedIPs []* router.GeoIPMatcher
34+ actPrior bool
35+ actUnprior bool
36+ tag string
37+ timeoutMs time.Duration
38+ finalQuery bool
39+ ipOption * dns.IPOption
40+ checkSystem bool
3741}
3842
3943// NewServer creates a name server object according to the network destination url.
@@ -150,13 +154,23 @@ func NewClient(
150154 }
151155
152156 // Establish expected IPs
153- var matchers []* router.GeoIPMatcher
154- for _ , geoip := range ns .Geoip {
157+ var expectedMatchers []* router.GeoIPMatcher
158+ for _ , geoip := range ns .ExpectedGeoip {
155159 matcher , err := router .GlobalGeoIPContainer .Add (geoip )
156160 if err != nil {
157- return errors .New ("failed to create ip matcher" ).Base (err ).AtWarning ()
161+ return errors .New ("failed to create expected ip matcher" ).Base (err ).AtWarning ()
158162 }
159- matchers = append (matchers , matcher )
163+ expectedMatchers = append (expectedMatchers , matcher )
164+ }
165+
166+ // Establish unexpected IPs
167+ var unexpectedMatchers []* router.GeoIPMatcher
168+ for _ , geoip := range ns .UnexpectedGeoip {
169+ matcher , err := router .GlobalGeoIPContainer .Add (geoip )
170+ if err != nil {
171+ return errors .New ("failed to create unexpected ip matcher" ).Base (err ).AtWarning ()
172+ }
173+ unexpectedMatchers = append (unexpectedMatchers , matcher )
160174 }
161175
162176 if len (clientIP ) > 0 {
@@ -173,14 +187,20 @@ func NewClient(
173187 timeoutMs = time .Duration (ns .TimeoutMs ) * time .Millisecond
174188 }
175189
190+ checkSystem := ns .QueryStrategy == QueryStrategy_USE_SYS
191+
176192 client .server = server
177193 client .skipFallback = ns .SkipFallback
178194 client .domains = rules
179- client .expectedIPs = matchers
180- client .allowUnexpectedIPs = ns .AllowUnexpectedIPs
195+ client .expectedIPs = expectedMatchers
196+ client .unexpectedIPs = unexpectedMatchers
197+ client .actPrior = ns .ActPrior
198+ client .actUnprior = ns .ActUnprior
181199 client .tag = tag
182200 client .timeoutMs = timeoutMs
201+ client .finalQuery = ns .FinalQuery
183202 client .ipOption = & ipOption
203+ client .checkSystem = checkSystem
184204 return nil
185205 })
186206 return client , err
@@ -191,10 +211,21 @@ func (c *Client) Name() string {
191211 return c .server .Name ()
192212}
193213
214+ func (c * Client ) IsFinalQuery () bool {
215+ return c .finalQuery
216+ }
217+
194218// QueryIP sends DNS query to the name server with the client's IP.
195219func (c * Client ) QueryIP (ctx context.Context , domain string , option dns.IPOption ) ([]net.IP , uint32 , error ) {
196- option .IPv4Enable = option .IPv4Enable && c .ipOption .IPv4Enable
197- option .IPv6Enable = option .IPv6Enable && c .ipOption .IPv6Enable
220+ if c .checkSystem {
221+ supportIPv4 , supportIPv6 := checkSystemNetwork ()
222+ option .IPv4Enable = option .IPv4Enable && supportIPv4
223+ option .IPv6Enable = option .IPv6Enable && supportIPv6
224+ } else {
225+ option .IPv4Enable = option .IPv4Enable && c .ipOption .IPv4Enable
226+ option .IPv6Enable = option .IPv6Enable && c .ipOption .IPv6Enable
227+ }
228+
198229 if ! option .IPv4Enable && ! option .IPv6Enable {
199230 return nil , 0 , dns .ErrEmptyResponse
200231 }
@@ -212,39 +243,47 @@ func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption
212243 return nil , 0 , dns .ErrEmptyResponse
213244 }
214245
215- if len (c .expectedIPs ) > 0 {
216- newIps := c .MatchExpectedIPs (domain , ips )
217- if len (newIps ) == 0 {
218- if ! c .allowUnexpectedIPs {
219- return nil , 0 , dns .ErrEmptyResponse
220- }
221- } else {
222- ips = newIps
246+ if len (c .expectedIPs ) > 0 && ! c .actPrior {
247+ ips = router .MatchIPs (c .expectedIPs , ips , false )
248+ errors .LogDebug (context .Background (), "domain " , domain , " expectedIPs " , ips , " matched at server " , c .Name ())
249+ if len (ips ) == 0 {
250+ return nil , 0 , dns .ErrEmptyResponse
223251 }
224252 }
225253
226- return ips , ttl , nil
227- }
254+ if len (c .unexpectedIPs ) > 0 && ! c .actUnprior {
255+ ips = router .MatchIPs (c .unexpectedIPs , ips , true )
256+ errors .LogDebug (context .Background (), "domain " , domain , " unexpectedIPs " , ips , " matched at server " , c .Name ())
257+ if len (ips ) == 0 {
258+ return nil , 0 , dns .ErrEmptyResponse
259+ }
260+ }
228261
229- // MatchExpectedIPs matches queried domain IPs with expected IPs and returns matched ones.
230- func (c * Client ) MatchExpectedIPs (domain string , ips []net.IP ) []net.IP {
231- var newIps []net.IP
232- for _ , ip := range ips {
233- for _ , matcher := range c .expectedIPs {
234- if matcher .Match (ip ) {
235- newIps = append (newIps , ip )
236- break
237- }
262+ if len (c .expectedIPs ) > 0 && c .actPrior {
263+ ipsNew := router .MatchIPs (c .expectedIPs , ips , false )
264+ if len (ipsNew ) > 0 {
265+ ips = ipsNew
266+ errors .LogDebug (context .Background (), "domain " , domain , " priorIPs " , ips , " matched at server " , c .Name ())
238267 }
239268 }
240- errors .LogDebug (context .Background (), "domain " , domain , " expectedIPs " , newIps , " matched at server " , c .Name ())
241- return newIps
269+
270+ if len (c .unexpectedIPs ) > 0 && c .actUnprior {
271+ ipsNew := router .MatchIPs (c .unexpectedIPs , ips , true )
272+ if len (ipsNew ) > 0 {
273+ ips = ipsNew
274+ errors .LogDebug (context .Background (), "domain " , domain , " unpriorIPs " , ips , " matched at server " , c .Name ())
275+ }
276+ }
277+
278+ return ips , ttl , nil
242279}
243280
244281func ResolveIpOptionOverride (queryStrategy QueryStrategy , ipOption dns.IPOption ) dns.IPOption {
245282 switch queryStrategy {
246283 case QueryStrategy_USE_IP :
247284 return ipOption
285+ case QueryStrategy_USE_SYS :
286+ return ipOption
248287 case QueryStrategy_USE_IP4 :
249288 return dns.IPOption {
250289 IPv4Enable : ipOption .IPv4Enable ,
0 commit comments