@@ -24,6 +24,12 @@ type UpstreamConfig struct {
24
24
// corresponding upstreams.
25
25
SpecifiedDomainUpstreams map [string ][]upstream.Upstream
26
26
27
+ // LocalOnlyDomains is a set of domains which should never be looked up on
28
+ // any upstream server. The value of the boolean doesn't matter, this is only
29
+ // a map to make lookups quicker than if it was a slice. If the key exists,
30
+ // it is treated as local only.
31
+ LocalOnlyDomains map [string ]bool
32
+
27
33
// SubdomainExclusions is set of domains with subdomains exclusions.
28
34
SubdomainExclusions * stringutil.Set
29
35
@@ -58,16 +64,23 @@ var _ io.Closer = (*UpstreamConfig)(nil)
58
64
//
59
65
// [/domain1/../domainN/]#
60
66
//
67
+ // To ensure domains will never be looked up on any upstream servers, and will
68
+ // respond with NXDOMAIN if not resolved locally, use the following syntax:
69
+ //
70
+ // [/domain1/../domainN/]-
71
+ //
61
72
// So the following config:
62
73
//
63
74
// [/host.com/]1.2.3.4
64
75
// [/www.host.com/]2.3.4.5"
76
+ // [/domain.local/]-
65
77
// [/maps.host.com/news.host.com/]#
66
78
// 3.4.5.6
67
79
//
68
80
// will send queries for *.host.com to 1.2.3.4. Except for *.www.host.com,
69
- // which will go to 2.3.4.5. And *.maps.host.com or *.news.host.com, which
70
- // will go to default server 3.4.5.6 with all other domains.
81
+ // which will go to 2.3.4.5. Any requests to *.domain.local or domain.local
82
+ // will only be resolved locally. And *.maps.host.com or *.news.host.com,
83
+ // which will go to default server 3.4.5.6 with all other domains.
71
84
//
72
85
// To exclude top level domain from reserved upstreams querying you could use
73
86
// the following:
@@ -95,6 +108,7 @@ func ParseUpstreamsConfig(upstreamConfig []string, options *upstream.Options) (*
95
108
domainReservedUpstreams : map [string ][]upstream.Upstream {},
96
109
specifiedDomainUpstreams : map [string ][]upstream.Upstream {},
97
110
subdomainsOnlyUpstreams : map [string ][]upstream.Upstream {},
111
+ localOnlyDomains : map [string ]bool {},
98
112
subdomainsOnlyExclusions : stringutil .NewSet (),
99
113
}
100
114
@@ -121,6 +135,12 @@ type configParser struct {
121
135
// corresponding upstreams.
122
136
subdomainsOnlyUpstreams map [string ][]upstream.Upstream
123
137
138
+ // localOnlyDomains is a set of domains which should never be looked up on
139
+ // any upstream server. The value of the boolean doesn't matter, this is only
140
+ // a map to make lookups quicker than if it was a slice. If the key exists,
141
+ // it is treated as local only.
142
+ localOnlyDomains map [string ]bool
143
+
124
144
// subdomainsOnlyExclusions is set of domains with subdomains exclusions.
125
145
subdomainsOnlyExclusions * stringutil.Set
126
146
@@ -147,6 +167,7 @@ func (p *configParser) parse(conf []string) (c *UpstreamConfig, err error) {
147
167
DomainReservedUpstreams : p .domainReservedUpstreams ,
148
168
SpecifiedDomainUpstreams : p .specifiedDomainUpstreams ,
149
169
SubdomainExclusions : p .subdomainsOnlyExclusions ,
170
+ LocalOnlyDomains : p .localOnlyDomains ,
150
171
}, nil
151
172
}
152
173
@@ -158,6 +179,12 @@ func (p *configParser) parseLine(idx int, confLine string) (err error) {
158
179
return err
159
180
}
160
181
182
+ if upstreams [0 ] == "-" && len (domains ) > 0 {
183
+ p .specifyLocalOnly (domains )
184
+
185
+ return nil
186
+ }
187
+
161
188
if upstreams [0 ] == "#" && len (domains ) > 0 {
162
189
p .excludeFromReserved (domains )
163
190
@@ -208,6 +235,12 @@ func splitConfigLine(idx int, confLine string) (upstreams, domains []string, err
208
235
return strings .Fields (upstreamsLine ), domains , nil
209
236
}
210
237
238
+ func (p * configParser ) specifyLocalOnly (domains []string ) {
239
+ for _ , domain := range domains {
240
+ p .localOnlyDomains [domain ] = true
241
+ }
242
+ }
243
+
211
244
// specifyUpstream specifies the upstream for domains.
212
245
func (p * configParser ) specifyUpstream (
213
246
domains []string ,
@@ -296,6 +329,17 @@ func (uc *UpstreamConfig) validate() (err error) {
296
329
}
297
330
}
298
331
332
+ func (uc * UpstreamConfig ) checkLocalOnly (host string ) bool {
333
+ for host != "" {
334
+ var ok bool
335
+ if _ , ok = uc .LocalOnlyDomains [host ]; ok {
336
+ return true
337
+ }
338
+ _ , host , _ = strings .Cut (host , "." )
339
+ }
340
+ return false
341
+ }
342
+
299
343
// getUpstreamsForDomain looks for a domain in the reserved domains map and
300
344
// returns a list of corresponding upstreams. It returns default upstreams list
301
345
// if the domain was not found in the map. More specific domains take priority
0 commit comments