4
4
//! * In the `Forwarding` state, queries are forwarded to a set of configured DNS servers. This
5
5
//! lets us use the routing table to determine where to send them, instead of them being forced
6
6
//! out on the primary interface (in some cases).
7
+ //!
8
+ //! See [start_resolver].
7
9
use std:: {
8
10
io,
9
11
net:: { IpAddr , Ipv4Addr , SocketAddr } ,
@@ -41,8 +43,7 @@ use hickory_server::{
41
43
} ;
42
44
use std:: sync:: LazyLock ;
43
45
44
- const ALLOWED_RECORD_TYPES : & [ RecordType ] =
45
- & [ RecordType :: A , /*RecordType::AAAA,*/ RecordType :: CNAME ] ;
46
+ const ALLOWED_RECORD_TYPES : & [ RecordType ] = & [ RecordType :: A , RecordType :: CNAME ] ;
46
47
const CAPTIVE_PORTAL_DOMAINS : & [ & str ] = & [ "captive.apple.com" , "netcts.cdn-apple.com" ] ;
47
48
48
49
static ALLOWED_DOMAINS : LazyLock < Vec < LowerName > > = LazyLock :: new ( || {
@@ -59,8 +60,8 @@ const RESOLVED_ADDR: Ipv4Addr = Ipv4Addr::new(198, 51, 100, 1);
59
60
60
61
/// Starts a resolver. Returns a cloneable handle, which can activate, deactivate and shut down the
61
62
/// resolver. When all instances of a handle are dropped, the server will stop.
62
- pub ( crate ) async fn start_resolver ( ) -> Result < ResolverHandle , Error > {
63
- let ( resolver, resolver_handle) = ForwardingResolver :: new ( ) . await ?;
63
+ pub async fn start_resolver ( ) -> Result < ResolverHandle , Error > {
64
+ let ( resolver, resolver_handle) = LocalResolver :: new ( ) . await ?;
64
65
tokio:: spawn ( resolver. run ( ) ) ;
65
66
Ok ( resolver_handle)
66
67
}
@@ -77,54 +78,64 @@ pub enum Error {
77
78
GetSocketAddrError ( #[ source] io:: Error ) ,
78
79
}
79
80
80
- /// A forwarding resolver
81
- struct ForwardingResolver {
81
+ /// A DNS resolver that forwards queries to some other DNS server
82
+ ///
83
+ /// Is controlled by commands sent through [ResolverHandle]s.
84
+ struct LocalResolver {
82
85
rx : mpsc:: UnboundedReceiver < ResolverMessage > ,
83
86
dns_server : Option < ( tokio:: task:: JoinHandle < ( ) > , oneshot:: Receiver < ( ) > ) > ,
84
- forward_resolver : LocalResolver ,
87
+ inner_resolver : Resolver ,
85
88
}
86
89
87
- /// Resolver message
90
+ /// A message to [LocalResolver]
88
91
enum ResolverMessage {
89
- /// Set config
92
+ /// Set resolver config
90
93
SetConfig {
91
94
/// New DNS config to use
92
- new_config : LocalConfig ,
95
+ new_config : Config ,
93
96
/// Response channel when resolvers have been updated
94
97
response_tx : oneshot:: Sender < ( ) > ,
95
98
} ,
96
- /// Query
97
- Query (
98
- LowerQuery ,
99
- oneshot:: Sender < std:: result:: Result < Box < dyn LookupObject > , ResolveError > > ,
100
- ) ,
99
+
100
+ /// Send a DNS query to the resolver
101
+ Query {
102
+ dns_query : LowerQuery ,
103
+
104
+ /// Channel for the query response
105
+ response_tx : oneshot:: Sender < std:: result:: Result < Box < dyn LookupObject > , ResolveError > > ,
106
+ } ,
101
107
}
102
108
103
- /// Resolver config
109
+ /// Configuration for [Resolver]
104
110
#[ derive( Debug , Default , Clone ) ]
105
- enum LocalConfig {
106
- /// Drop DNS queries. For captive portal domains, return faux records
111
+ enum Config {
112
+ /// Drop DNS queries. For captive portal domains, return faux records.
107
113
#[ default]
108
- Blocked ,
114
+ Blocking ,
115
+
109
116
/// Forward DNS queries to a configured server
110
- ForwardDns {
117
+ Forwarding {
111
118
/// Remote DNS server to use
112
119
dns_servers : Vec < IpAddr > ,
113
120
} ,
114
121
}
115
122
116
- enum LocalResolver {
123
+ enum Resolver {
117
124
/// Drop DNS queries. For captive portal domains, return faux records
118
- Blocked ,
125
+ Blocking ,
126
+
119
127
/// Forward DNS queries to a configured server
120
- ForwardDns ( TokioAsyncResolver ) ,
128
+ Forwarding ( TokioAsyncResolver ) ,
121
129
}
122
130
123
- impl From < LocalConfig > for LocalResolver {
124
- fn from ( config : LocalConfig ) -> Self {
125
- match config {
126
- LocalConfig :: Blocked => LocalResolver :: Blocked ,
127
- LocalConfig :: ForwardDns { ref dns_servers } => {
131
+ impl From < Config > for Resolver {
132
+ fn from ( mut config : Config ) -> Self {
133
+ match & mut config {
134
+ Config :: Blocking => Resolver :: Blocking ,
135
+ Config :: Forwarding { dns_servers } => {
136
+ // make sure not to accidentally forward queries to ourselves
137
+ dns_servers. retain ( |addr| !addr. is_loopback ( ) ) ;
138
+
128
139
let forward_server_config =
129
140
NameServerConfigGroup :: from_ips_clear ( dns_servers, 53 , true ) ;
130
141
@@ -134,21 +145,21 @@ impl From<LocalConfig> for LocalResolver {
134
145
135
146
let resolver = TokioAsyncResolver :: tokio ( forward_config, resolver_opts) ;
136
147
137
- LocalResolver :: ForwardDns ( resolver)
148
+ Resolver :: Forwarding ( resolver)
138
149
}
139
150
}
140
151
}
141
152
}
142
153
143
- impl LocalResolver {
154
+ impl Resolver {
144
155
pub fn resolve (
145
156
& self ,
146
157
query : LowerQuery ,
147
158
tx : oneshot:: Sender < std:: result:: Result < Box < dyn LookupObject > , ResolveError > > ,
148
159
) {
149
160
let lookup = match self {
150
- LocalResolver :: Blocked => Either :: Left ( async move { Self :: resolve_blocked ( query) } ) ,
151
- LocalResolver :: ForwardDns ( resolver) => {
161
+ Resolver :: Blocking => Either :: Left ( async move { Self :: resolve_blocked ( query) } ) ,
162
+ Resolver :: Forwarding ( resolver) => {
152
163
Either :: Right ( Self :: resolve_forward ( resolver. clone ( ) , query) )
153
164
}
154
165
} ;
@@ -208,10 +219,11 @@ impl LocalResolver {
208
219
}
209
220
}
210
221
211
- /// A handle to control a forwarding resolver. When all resolver handles are dropped, custom
212
- /// resolver will stop.
222
+ /// A handle to control a DNS resolver.
223
+ ///
224
+ /// When all resolver handles are dropped, the resolver will stop.
213
225
#[ derive( Clone ) ]
214
- pub ( crate ) struct ResolverHandle {
226
+ pub struct ResolverHandle {
215
227
tx : Arc < mpsc:: UnboundedSender < ResolverMessage > > ,
216
228
listening_port : u16 ,
217
229
}
@@ -228,14 +240,9 @@ impl ResolverHandle {
228
240
229
241
/// Set the DNS server to forward queries to
230
242
pub async fn enable_forward ( & self , dns_servers : Vec < IpAddr > ) {
231
- let dns_servers = dns_servers
232
- . into_iter ( )
233
- . filter ( |addr| !addr. is_loopback ( ) )
234
- . collect ( ) ;
235
-
236
243
let ( response_tx, response_rx) = oneshot:: channel ( ) ;
237
244
let _ = self . tx . unbounded_send ( ResolverMessage :: SetConfig {
238
- new_config : LocalConfig :: ForwardDns { dns_servers } ,
245
+ new_config : Config :: Forwarding { dns_servers } ,
239
246
response_tx,
240
247
} ) ;
241
248
@@ -246,15 +253,15 @@ impl ResolverHandle {
246
253
pub async fn disable_forward ( & self ) {
247
254
let ( response_tx, response_rx) = oneshot:: channel ( ) ;
248
255
let _ = self . tx . unbounded_send ( ResolverMessage :: SetConfig {
249
- new_config : LocalConfig :: Blocked ,
256
+ new_config : Config :: Blocking ,
250
257
response_tx,
251
258
} ) ;
252
259
253
260
let _ = response_rx. await ;
254
261
}
255
262
}
256
263
257
- impl ForwardingResolver {
264
+ impl LocalResolver {
258
265
/// Constructs a new filtering resolver and it's handle.
259
266
async fn new ( ) -> Result < ( Self , ResolverHandle ) , Error > {
260
267
let ( tx, rx) = mpsc:: unbounded ( ) ;
@@ -291,7 +298,7 @@ impl ForwardingResolver {
291
298
let resolver = Self {
292
299
rx,
293
300
dns_server : Some ( ( server_handle, server_done_rx) ) ,
294
- forward_resolver : LocalResolver :: from ( LocalConfig :: Blocked ) ,
301
+ inner_resolver : Resolver :: from ( Config :: Blocking ) ,
295
302
} ;
296
303
297
304
Ok ( ( resolver, ResolverHandle :: new ( command_tx, port) ) )
@@ -328,12 +335,15 @@ impl ForwardingResolver {
328
335
} => {
329
336
log:: debug!( "Updating config: {new_config:?}" ) ;
330
337
331
- self . forward_resolver = LocalResolver :: from ( new_config) ;
338
+ self . inner_resolver = Resolver :: from ( new_config) ;
332
339
flush_system_cache ( ) ;
333
340
let _ = response_tx. send ( ( ) ) ;
334
341
}
335
- ResolverMessage :: Query ( query, tx) => {
336
- self . forward_resolver . resolve ( query, tx) ;
342
+ ResolverMessage :: Query {
343
+ dns_query,
344
+ response_tx,
345
+ } => {
346
+ self . inner_resolver . resolve ( dns_query, response_tx) ;
337
347
}
338
348
}
339
349
}
@@ -406,12 +416,15 @@ impl ResolverImpl {
406
416
if let Some ( tx_ref) = self . tx . upgrade ( ) {
407
417
let mut tx = ( * tx_ref) . clone ( ) ;
408
418
let query = message. query ( ) ;
409
- let ( lookup_tx , lookup_rx ) = oneshot:: channel ( ) ;
419
+ let ( response_tx , response_rx ) = oneshot:: channel ( ) ;
410
420
let _ = tx
411
- . send ( ResolverMessage :: Query ( query. clone ( ) , lookup_tx) )
421
+ . send ( ResolverMessage :: Query {
422
+ dns_query : query. clone ( ) ,
423
+ response_tx,
424
+ } )
412
425
. await ;
413
426
414
- let lookup_result = lookup_rx . await ;
427
+ let lookup_result = response_rx . await ;
415
428
let response_result = match lookup_result {
416
429
Ok ( Ok ( ref lookup) ) => {
417
430
let response = Self :: build_response ( message, lookup. as_ref ( ) ) ;
0 commit comments