Skip to main content
net10.0net8.0net9.0

DNS filter list parser and matching engine supporting hosts files, domains-only lists, and AdGuard/Adblock DNS filtering syntax

Published
May 23, 2026
4mo ago
Total Downloads
847
847

Install

dotnet add package Meziantou.Framework.DnsFilter --version 1.0.1
ProductVersions
.NET
net10.0net8.0net9.0

README

Meziantou.Framework.DnsFilter

A standalone DNS filter list parser and matching engine supporting hosts files, domains-only lists, and AdGuard/Adblock DNS filtering syntax. Inspired by the filtering capabilities of AdGuard Home and Pi-hole.

Features

  • Multiple list formats: Hosts files (0.0.0.0 domain), domains-only lists, and AdGuard/Adblock DNS filtering syntax (||domain^)
  • Auto-detection: Automatically detects the filter list format when not specified
  • AdGuard modifiers: $important, $badfilter, $dnstype, $denyallow, $dnsrewrite, $client, $ctag
  • Priority resolution: Follows the AdGuard priority pipeline — $important block → $important allow → @@ exception → normal block
  • Client-aware filtering: Filter rules by client IP address, CIDR range, client name ($client), or client tags ($ctag)
  • Efficient matching: Hash-based exact domain and suffix lookups with regex fallback for wildcard and pattern rules
  • Thread-safe: Concurrent query evaluation with atomic rule-set replacement via Reload()

Usage

Load a hosts-file blocklist

var ruleSet = new DnsFilterRuleSet();
ruleSet.AddFromList("""
    0.0.0.0 ads.example.com
    0.0.0.0 tracking.example.org
    """, DnsFilterListFormat.Hosts);

var engine = new DnsFilterEngine(ruleSet);
var result = engine.Evaluate("ads.example.com");
// result.IsMatched == true, result.Action == DnsFilterAction.Block

Load an AdGuard-style filter list

var ruleSet = new DnsFilterRuleSet();
ruleSet.AddFromList("""
    ||ads.example.com^
    ||tracking.example.org^
    @@||safe.example.com^
    """, DnsFilterListFormat.AdBlock);

var engine = new DnsFilterEngine(ruleSet);

engine.Evaluate("ads.example.com");
// Blocked

engine.Evaluate("sub.ads.example.com");
// Blocked (subdomain match with || syntax)

engine.Evaluate("safe.example.com");
// Allowed (exception rule)

Combine multiple lists

var ruleSet = new DnsFilterRuleSet();
ruleSet.AddFromList(hostsFileContent, DnsFilterListFormat.Hosts);
ruleSet.AddFromList(adGuardListContent, DnsFilterListFormat.AdBlock);
ruleSet.AddFromList(domainsOnlyContent, DnsFilterListFormat.DomainsOnly);

var engine = new DnsFilterEngine(ruleSet);

Filter by DNS query type

var ruleSet = new DnsFilterRuleSet();
ruleSet.AddFromList("||example.com^$dnstype=AAAA", DnsFilterListFormat.AdBlock);

var engine = new DnsFilterEngine(ruleSet);

engine.Evaluate("example.com", DnsFilterQueryType.AAAA);
// Blocked

engine.Evaluate("example.com", DnsFilterQueryType.A);
// Not matched

Client-aware filtering with $client

var ruleSet = new DnsFilterRuleSet();
ruleSet.AddFromList("||example.com^$client=192.168.1.0/24", DnsFilterListFormat.AdBlock);

var engine = new DnsFilterEngine(ruleSet);

var client = new DnsClientInfo { Address = IPAddress.Parse("192.168.1.50") };
engine.Evaluate("example.com", DnsFilterQueryType.A, client);
// Blocked

var otherClient = new DnsClientInfo { Address = IPAddress.Parse("10.0.0.1") };
engine.Evaluate("example.com", DnsFilterQueryType.A, otherClient);
// Not matched

Tag-based filtering with $ctag

var ruleSet = new DnsFilterRuleSet();
ruleSet.AddFromList("||example.com^$ctag=device_phone", DnsFilterListFormat.AdBlock);

var engine = new DnsFilterEngine(ruleSet);

var phoneClient = new DnsClientInfo { Tags = ["device_phone", "os_android"] };
engine.Evaluate("example.com", DnsFilterQueryType.A, phoneClient);
// Blocked

var pcClient = new DnsClientInfo { Tags = ["device_pc"] };
engine.Evaluate("example.com", DnsFilterQueryType.A, pcClient);
// Not matched

Reload rules at runtime

var ruleSet = new DnsFilterRuleSet();
ruleSet.AddFromList(initialList);
var engine = new DnsFilterEngine(ruleSet);

// Later, replace the rules atomically (thread-safe)
var newRuleSet = new DnsFilterRuleSet();
newRuleSet.AddFromList(updatedList);
engine.Reload(newRuleSet);

DNS rewriting with $dnsrewrite

var ruleSet = new DnsFilterRuleSet();
ruleSet.AddFromList("||example.com^$dnsrewrite=1.2.3.4", DnsFilterListFormat.AdBlock);

var engine = new DnsFilterEngine(ruleSet);
var result = engine.Evaluate("example.com");
// result.Rewrite.ResponseCode == DnsFilterRewriteResponseCode.NoError
// result.Rewrite.RecordType == DnsFilterQueryType.A
// result.Rewrite.Value == "1.2.3.4"

Changes from Previous Version

No structural changes between v1.0.0 and v1.0.1.

Adoption Assessment

A verified publisher signal is available. Assess fit from the package's supported frameworks, license and dependency graph rather than popularity alone.

Compatibility metadata lists 3 target frameworks; confirm the exact target used by your application.

Related Guides & Workflows

Learn how to evaluate, integrate, or audit this package in your .NET project.