Skip to main content

BlocklistZoneHandler

Struct BlocklistZoneHandler 

Source
pub struct BlocklistZoneHandler { /* private fields */ }
Available on crate feature 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

Source

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

Source

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 implementing std::io::Read that 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");
    };
}
Source

pub fn entry_count(&self) -> usize

Number of unique blocklist entries currently loaded in memory.

Trait Implementations§

Source§

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,

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,

Optionally, perform a blocklist lookup after another zone handler has done a lookup for this query.

Source§

fn zone_type(&self) -> ZoneType

What type is this zone
Source§

fn axfr_policy(&self) -> AxfrPolicy

Return the policy for determining if AXFR requests are allowed
Source§

fn origin(&self) -> &LowerName

Get the origin of this zone, i.e. example.com is the origin for www.example.com
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,

Using the specified query, perform a lookup against this zone. Read more
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,

Returns all records in the zone. Read more
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,

Return the NSEC records based on the given name Read more
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,

Available on crate feature __dnssec only.
Return the NSEC3 records based on the information available for a query.
Source§

fn nx_proof_kind(&self) -> Option<&NxProofKind>

Available on crate feature __dnssec only.
Returns the kind of non-existence proof used for this zone.
Source§

fn metrics_label(&self) -> &'static str

Available on crate feature metrics only.
Returns the zone handler metrics label.
Source§

fn can_validate_dnssec(&self) -> bool

Whether the zone handler can perform DNSSEC validation
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,

Perform a dynamic update of a zone

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more