@@ -19,7 +19,7 @@ use async_trait::async_trait;
1919use directories:: ProjectDirs ;
2020use hickory_proto:: {
2121 op:: { header:: Header , response_code:: ResponseCode } ,
22- rr:: Name
22+ rr:: { rdata :: { A , AAAA } , Name , RData , Record , RecordType }
2323} ;
2424use hickory_server:: {
2525 authority:: { Catalog , MessageResponseBuilder } ,
@@ -41,6 +41,7 @@ use std::{
4141 fs:: { self , File } ,
4242 io:: BufReader ,
4343 iter,
44+ net:: { Ipv4Addr , Ipv6Addr } ,
4445 path:: { Path , PathBuf } ,
4546 process:: ExitCode ,
4647 sync:: {
@@ -136,7 +137,8 @@ struct Handler {
136137 catalog : Catalog ,
137138 blocklist : Arc < BlockList > ,
138139 include_subdomains : bool ,
139- stats : Stats
140+ stats : Stats ,
141+ blocking_mode : BlockingMode
140142}
141143
142144impl Handler {
@@ -158,7 +160,8 @@ impl Handler {
158160 catalog,
159161 blocklist : Arc :: new ( blocklist) ,
160162 include_subdomains : config. blocklist . include_subdomains ,
161- stats
163+ stats,
164+ blocking_mode : config. blocklist . blocking_mode
162165 }
163166 }
164167}
@@ -196,23 +199,59 @@ impl RequestHandler for Handler {
196199 debug ! ( "blocked: {lower_query:?}" ) ;
197200 self . stats . blocked_request . fetch_add ( 1 , Ordering :: Relaxed ) ;
198201 let mut header = Header :: response_from_request ( request. header ( ) ) ;
199- header. set_response_code ( ResponseCode :: NXDomain ) ;
200- return response_handler
201- . send_response (
202- MessageResponseBuilder :: from_message_request ( request) . build (
203- header,
204- iter:: empty ( ) ,
205- iter:: empty ( ) ,
206- iter:: empty ( ) ,
207- iter:: empty ( )
208- )
209- )
210- . await
211- . unwrap_or_else ( |_| {
212- let mut header = Header :: new ( ) ;
213- header. set_response_code ( ResponseCode :: ServFail ) ;
214- header. into ( )
215- } ) ;
202+ match self . blocking_mode {
203+ BlockingMode :: NXDomain => {
204+ header. set_response_code ( ResponseCode :: NXDomain ) ;
205+ return response_handler
206+ . send_response (
207+ MessageResponseBuilder :: from_message_request ( request) . build (
208+ header,
209+ iter:: empty ( ) ,
210+ iter:: empty ( ) ,
211+ iter:: empty ( ) ,
212+ iter:: empty ( )
213+ )
214+ )
215+ . await
216+ . unwrap_or_else ( |_| {
217+ let mut header = Header :: new ( ) ;
218+ header. set_response_code ( ResponseCode :: ServFail ) ;
219+ header. into ( )
220+ } ) ;
221+ } ,
222+ BlockingMode :: Zero => {
223+ header. set_response_code ( ResponseCode :: NoError ) ;
224+ let answers = match lower_query. query_type ( ) {
225+ RecordType :: A => vec ! [ Record :: from_rdata(
226+ lower_query. name( ) . into( ) ,
227+ 3600 ,
228+ RData :: A ( A ( Ipv4Addr :: new( 0 , 0 , 0 , 0 ) ) )
229+ ) ] ,
230+ RecordType :: AAAA => vec ! [ Record :: from_rdata(
231+ lower_query. name( ) . into( ) ,
232+ 3600 ,
233+ RData :: AAAA ( AAAA ( Ipv6Addr :: new( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) ) )
234+ ) ] ,
235+ _ => vec ! [ ]
236+ } ;
237+ return response_handler
238+ . send_response (
239+ MessageResponseBuilder :: from_message_request ( request) . build (
240+ header,
241+ answers. iter ( ) ,
242+ iter:: empty ( ) ,
243+ iter:: empty ( ) ,
244+ iter:: empty ( )
245+ )
246+ )
247+ . await
248+ . unwrap_or_else ( |_| {
249+ let mut header = Header :: new ( ) ;
250+ header. set_response_code ( ResponseCode :: ServFail ) ;
251+ header. into ( )
252+ } ) ;
253+ }
254+ }
216255 }
217256
218257 debug ! ( "{lower_query:?}" ) ;
@@ -487,7 +526,17 @@ struct BlockConfig {
487526 lists : Vec < Url > ,
488527 include_subdomains : bool ,
489528 #[ serde( default ) ]
490- allow_list : Vec < Url >
529+ allow_list : Vec < Url > ,
530+ #[ serde( default ) ]
531+ blocking_mode : BlockingMode
532+ }
533+
534+ #[ derive( Debug , Default , Deserialize , Clone , Copy , PartialEq ) ]
535+ #[ serde( rename_all = "lowercase" ) ]
536+ enum BlockingMode {
537+ #[ default]
538+ NXDomain ,
539+ Zero
491540}
492541
493542#[ derive( Debug , Deserialize ) ]
0 commit comments