pub struct BlocklistZoneHandler { /* private fields */ }blocklist only.Expand description
A conditional zone handler that will resolve queries against one or more block lists and return a forged response. The typical use case will be to use this in a chained configuration before a forwarding or recursive resolver in order to pre-emptively block queries for hosts that are on a block list. Refer to tests/test-data/test_configs/chained_blocklist.toml for an example of this configuration.
The blocklist zone handler also supports the consult interface, which allows a zone handler to review a query/response that has been processed by another zone handler, and, optionally, overwrite that response before returning it to the requestor. There is an example of this configuration in tests/test-data/test_configs/example_consulting_blocklist.toml. The main intended use of this feature is to allow log-only configurations, to allow administrators to see if blocklist domains are being queried. While this can be configured to overwrite responses, it is not recommended to do so - it is both more efficient, and more secure, to allow the blocklist to drop queries pre-emptively, as in the first example.
Implementations§
Source§impl BlocklistZoneHandler
impl BlocklistZoneHandler
Sourcepub fn try_from_config(
origin: Name,
config: BlocklistConfig,
base_dir: Option<&Path>,
) -> Result<Self, String>
pub fn try_from_config( origin: Name, config: BlocklistConfig, base_dir: Option<&Path>, ) -> Result<Self, String>
Read the ZoneHandler for the origin from the specified configuration
Sourcepub fn add(&mut self, handle: impl Read) -> Result<(), Error>
pub fn add(&mut self, handle: impl Read) -> Result<(), Error>
Add the contents of a block list to the in-memory cache. This function is normally called from try_from_config, but it can be invoked after the blocklist zone handler is created.
§Arguments
handle- A source implementingstd::io::Readthat contains the blocklist entries to insert into the in-memory cache.
§Return value
Result<(), std::io::Error>
§Expected format of blocklist entries
- One entry per line
- Any character after a ‘#’ will be treated as a comment and stripped out.
- Leading wildcard entries are supported when the user has wildcard_match set to true. E.g., ‘*.foo.com’ will match any host in the foo.com domain. Intermediate wildcard matches, such as ‘www.*.com’ are not supported. Note: when wildcard matching is enabled, min_wildcard_depth (default: 2) controls how many static name labels must be present for a wildcard entry to be valid. With the default value of 2, an entry for ‘*.foo.com’ would be accepted, but an entry for ‘*.com’ would not.
- All entries are treated as being fully-qualified. If an entry does not contain a trailing ‘.’, one will be added before insertion into the cache.
§Example
use std::{fs::File, net::{Ipv4Addr, Ipv6Addr}, path::Path, str::FromStr, sync::Arc};
use hickory_proto::rr::{LowerName, RecordType, Name};
use hickory_server::{
store::blocklist::*,
zone_handler::{LookupControlFlow, LookupOptions, ZoneHandler, ZoneType},
};
#[tokio::main]
async fn main() {
let config = BlocklistConfig {
wildcard_match: true,
min_wildcard_depth: 2,
lists: vec!["default/blocklist.txt".to_string()],
sinkhole_ipv4: None,
sinkhole_ipv6: None,
block_message: None,
ttl: 86_400,
consult_action: BlocklistConsultAction::Disabled,
log_clients: true,
};
let mut blocklist = BlocklistZoneHandler::try_from_config(
Name::root(),
config,
Some(Path::new("../../tests/test-data/test_configs")),
).unwrap();
let handle = File::open("../../tests/test-data/test_configs/default/blocklist2.txt").unwrap();
if let Err(e) = blocklist.add(handle) {
panic!("error adding blocklist: {e:?}");
}
let origin = blocklist.origin().clone();
let handler = Arc::new(blocklist) as Arc<dyn ZoneHandler>;
// In this example, malc0de.com only exists in the blocklist2.txt file we added to the
// zone handler after instantiating it. The following simulates a lookup against the
// blocklist zone handler, and checks for the expected response for a blocklist match.
use LookupControlFlow::*;
let Break(Ok(_res)) = handler.lookup(
&LowerName::from(Name::from_ascii("malc0de.com.").unwrap()),
RecordType::A,
None,
LookupOptions::default(),
).await else {
panic!("blocklist zone handler did not return expected match");
};
}Sourcepub fn entry_count(&self) -> usize
pub fn entry_count(&self) -> usize
Number of unique blocklist entries currently loaded in memory.
Trait Implementations§
Source§impl ZoneHandler for BlocklistZoneHandler
impl ZoneHandler for BlocklistZoneHandler
Source§fn lookup<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
name: &'life1 LowerName,
rtype: RecordType,
request_info: Option<&'life2 RequestInfo<'life3>>,
_lookup_options: LookupOptions,
) -> Pin<Box<dyn Future<Output = LookupControlFlow<AuthLookup>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn lookup<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
name: &'life1 LowerName,
rtype: RecordType,
request_info: Option<&'life2 RequestInfo<'life3>>,
_lookup_options: LookupOptions,
) -> Pin<Box<dyn Future<Output = LookupControlFlow<AuthLookup>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Perform a blocklist lookup. This will return LookupControlFlow::Break(Ok) on a match, or LookupControlFlow::Skip on no match.
Source§fn consult<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
name: &'life1 LowerName,
rtype: RecordType,
request_info: Option<&'life2 RequestInfo<'life3>>,
lookup_options: LookupOptions,
last_result: LookupControlFlow<AuthLookup>,
) -> Pin<Box<dyn Future<Output = (LookupControlFlow<AuthLookup>, Option<TSigResponseContext>)> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn consult<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
name: &'life1 LowerName,
rtype: RecordType,
request_info: Option<&'life2 RequestInfo<'life3>>,
lookup_options: LookupOptions,
last_result: LookupControlFlow<AuthLookup>,
) -> Pin<Box<dyn Future<Output = (LookupControlFlow<AuthLookup>, Option<TSigResponseContext>)> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Optionally, perform a blocklist lookup after another zone handler has done a lookup for this query.
Source§fn axfr_policy(&self) -> AxfrPolicy
fn axfr_policy(&self) -> AxfrPolicy
Source§fn origin(&self) -> &LowerName
fn origin(&self) -> &LowerName
Source§fn search<'life0, 'life1, 'async_trait>(
&'life0 self,
request: &'life1 Request,
lookup_options: LookupOptions,
) -> Pin<Box<dyn Future<Output = (LookupControlFlow<AuthLookup>, Option<TSigResponseContext>)> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn search<'life0, 'life1, 'async_trait>(
&'life0 self,
request: &'life1 Request,
lookup_options: LookupOptions,
) -> Pin<Box<dyn Future<Output = (LookupControlFlow<AuthLookup>, Option<TSigResponseContext>)> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn zone_transfer<'life0, 'life1, 'async_trait>(
&'life0 self,
_request: &'life1 Request,
_lookup_options: LookupOptions,
_now: u64,
) -> Pin<Box<dyn Future<Output = Option<(Result<ZoneTransfer, LookupError>, Option<TSigResponseContext>)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn zone_transfer<'life0, 'life1, 'async_trait>(
&'life0 self,
_request: &'life1 Request,
_lookup_options: LookupOptions,
_now: u64,
) -> Pin<Box<dyn Future<Output = Option<(Result<ZoneTransfer, LookupError>, Option<TSigResponseContext>)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn nsec_records<'life0, 'life1, 'async_trait>(
&'life0 self,
_name: &'life1 LowerName,
_lookup_options: LookupOptions,
) -> Pin<Box<dyn Future<Output = LookupControlFlow<AuthLookup>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn nsec_records<'life0, 'life1, 'async_trait>(
&'life0 self,
_name: &'life1 LowerName,
_lookup_options: LookupOptions,
) -> Pin<Box<dyn Future<Output = LookupControlFlow<AuthLookup>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn nsec3_records<'life0, 'life1, 'async_trait>(
&'life0 self,
_info: Nsec3QueryInfo<'life1>,
_lookup_options: LookupOptions,
) -> Pin<Box<dyn Future<Output = LookupControlFlow<AuthLookup>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn nsec3_records<'life0, 'life1, 'async_trait>(
&'life0 self,
_info: Nsec3QueryInfo<'life1>,
_lookup_options: LookupOptions,
) -> Pin<Box<dyn Future<Output = LookupControlFlow<AuthLookup>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
__dnssec only.Source§fn nx_proof_kind(&self) -> Option<&NxProofKind>
fn nx_proof_kind(&self) -> Option<&NxProofKind>
__dnssec only.Source§fn metrics_label(&self) -> &'static str
fn metrics_label(&self) -> &'static str
metrics only.Source§fn can_validate_dnssec(&self) -> bool
fn can_validate_dnssec(&self) -> bool
Source§fn update<'life0, 'life1, 'async_trait>(
&'life0 self,
_update: &'life1 Request,
_now: u64,
) -> Pin<Box<dyn Future<Output = (Result<bool, ResponseCode>, Option<TSigResponseContext>)> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn update<'life0, 'life1, 'async_trait>(
&'life0 self,
_update: &'life1 Request,
_now: u64,
) -> Pin<Box<dyn Future<Output = (Result<bool, ResponseCode>, Option<TSigResponseContext>)> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Auto Trait Implementations§
impl Freeze for BlocklistZoneHandler
impl !RefUnwindSafe for BlocklistZoneHandler
impl Send for BlocklistZoneHandler
impl Sync for BlocklistZoneHandler
impl Unpin for BlocklistZoneHandler
impl UnsafeUnpin for BlocklistZoneHandler
impl !UnwindSafe for BlocklistZoneHandler
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more