Apps/DnsBlockListApp/README.md
A DNS App for Technitium DNS Server that implements DNS-based Block Lists (DNSBL) for IP addresses and domain names, based on RFC 5782. This application enables system administrators to create and maintain custom block lists that return standardized responses when queried.
The DNS Block List App extends the core DNS Server functionality by providing DNSBL query response capabilities through APP records configured in primary or forwarder zones.
Key capabilities:
This application provides administrative value for network operators implementing reputation-based filtering, threat intelligence integration, or compliance-driven access control at the DNS layer.
The application is configured using the dnsApp.config JSON file located in the application folder.
The configuration consists of an array of block list definitions under the dnsBlockLists property. Each block list operates independently and can be enabled or disabled without affecting others.
| Property | Type | Default | Description |
|---|---|---|---|
dnsBlockLists | array | [] | Array of block list configuration objects |
Each entry in the dnsBlockLists array defines a single block list instance.
| Property | Type | Default | Description |
|---|---|---|---|
name | string | (required) | Unique identifier for the block list, referenced in APP record data |
type | string | "ip" | Block list type: "ip" or "domain" |
enabled | boolean | true | Whether this block list is active |
responseA | string | "127.0.0.2" | Default IPv4 address returned for blocked entries (A record response) |
responseTXT | string | null | Default TXT record response; supports {ip} and {domain} placeholders |
blockListFile | string | (required) | Path to block list file (relative to application folder or absolute) |
IP block list files support both IPv4 and IPv6 addresses and network ranges.
Format: network [A-response [TXT-response]]
Separator: Space, tab, or pipe (|) character
Examples:
# Single IPv4 address with default response
192.168.1.1
# IPv4 network with default response
192.168.0.0/24
# IPv4 address with custom A response
192.168.2.1 127.0.0.3
# IPv4 network with custom A and TXT responses
10.8.1.0/24 127.0.0.3 malware see: https://example.com/dnsbl?ip={ip}
# IPv6 network
2001:db8::/64
Lines beginning with # are treated as comments. Empty lines are ignored.
Domain block list files support exact domain matches with hierarchical parent zone matching.
Format: domain [A-response [TXT-response]]
Separator: Space, tab, or pipe (|) character
Examples:
# Domain with default response
example.com
# Domain with custom A response
example.net 127.0.0.4
# Domain with custom A and TXT responses
malware.com 127.0.0.4 malware see: https://example.com/dnsbl?domain={domain}
Lines beginning with # are treated as comments. Empty lines are ignored.
{
"dnsBlockLists": [
{
"name": "ipblocklist1",
"type": "ip",
"enabled": true,
"responseA": "127.0.0.2",
"responseTXT": "https://example.com/dnsbl?ip={ip}",
"blockListFile": "ip-blocklist.txt"
},
{
"name": "domainblocklist1",
"type": "domain",
"enabled": true,
"responseA": "127.0.0.2",
"responseTXT": "https://example.com/dnsbl?domain={domain}",
"blockListFile": "domain-blocklist.txt"
}
]
}
To use the DNS Block List App, create an APP record in a zone with the following data structure:
{
"dnsBlockLists": [
"ipblocklist1",
"domainblocklist1"
]
}
The dnsBlockLists array contains the names of block lists (defined in dnsApp.config) that should be consulted for this APP record.
The application processes DNSBL queries according to RFC 5782 specifications:
Query Reception: The DNS server receives a query for a subdomain under the APP record (e.g., 2.0.0.127.dnsbl.example.com)
Address/Domain Extraction: The query name is parsed to extract either:
Block List Lookup: The extracted address or domain is checked against each configured block list in order
Response Generation:
NXDOMAIN Response: If the address/domain is not found in any enabled block list, returns NXDOMAIN
Standard format with reversed octets:
<octet4>.<octet3>.<octet2>.<octet1>.<app-record-name>
Example: 1.168.192.10.dnsbl.example.com queries for IP 10.192.168.1
32 nibbles in reversed order (hex notation):
<nibble32>.<nibble31>....<nibble2>.<nibble1>.<app-record-name>
Example: Query for 2001:db8::1 would be formatted as reversed nibbles under the APP record name
Standard domain name format:
<domain-name>.<app-record-name>
Example: example.com.dnsbl.example.com queries for domain example.com
The domain portion is read as-is from left to right before the APP record name; it is not reversed like IP-based DNSBL queries.
This implementation adheres to RFC 5782 (DNS Blacklists and Whitelists):
127.0.0.2 for IP, test for domain)127.0.0.0/8 rangeThe application monitors block list files for modifications and automatically reloads them when changes are detected.
No server restart or manual intervention is required when updating block list files.
When an entry is found in a block list, the A and TXT responses are selected using the following priority:
dnsApp.config)127.0.0.2)This allows granular control: global defaults can be overridden per block list, and individual entries can specify unique responses.
Symptoms: Queries return NXDOMAIN for known blocked entries; log shows file read errors
Resolution:
blockListFile path in dnsApp.configSymptoms: Known blocked IPs/domains return NXDOMAIN instead of A/TXT records
Resolution:
enabled property is trueSymptoms: A record queries succeed, but TXT queries return NODATA
Resolution:
responseTXT is configured in dnsApp.config or block list file{ip} or {domain})Symptoms: IPv6 address queries return NXDOMAIN; IPv4 queries work correctly
Resolution:
2001:db8::/64)::FFFF:7F00:2 (included as test entry)Symptoms: Exact domains are blocked, but subdomains are not
Behavior: The domain block list implementation uses hierarchical matching. When querying for sub.example.com, the application will check:
sub.example.com (exact match)example.com (parent zone)com (parent zone)Resolution: