File: README.md
Technitium DNS Server is an open source authoritative as well as recursive DNS server that can be used for self hosting a DNS server for privacy & security. It works out-of-the-box with no or minimal configuration and provides a user friendly web console accessible using any modern web browser.
Nobody really bothers about domain name resolution since it works automatically behind the scenes and is complex to understand. Most computer software use the operating system's DNS resolver that usually query the configured ISP's DNS server using UDP protocol. This way works well for most people but, your ISP can see and control what website you can visit even when the website employ HTTPS security. Not only that, some ISPs can redirect, block or inject content into websites you visit even when you use a different DNS provider like Google DNS or Cloudflare DNS. Having Technitium DNS Server configured to use DNS-over-TLS, DNS-over-HTTPS, or DNS-over-QUIC forwarders, these privacy & security issues can be mitigated very effectively.
Be it a home network or an organization's network, having a locally running DNS server gives you more insights into your network and helps to understand it better using the DNS logs and stats. It improves overall performance since most queries are served from the DNS cache making web sites load faster by not having to wait for frequent DNS resolutions. It also gives you an additional control over your network allowing you to block domain names network wide and also allows you to route your DNS traffic securely using encrypted DNS protocols.
Sponsored By
Features
- Works on Windows, Linux, macOS and Raspberry Pi.
- Docker image available on Docker Hub.
- Installs in just a minute and works out-of-the-box with zero configuration.
- Block ads & malware using one or more block list URLs.
- Supports working as an authoritative as well as a recursive DNS server.
- Includes built-in Clustering feature to allow managing two or more DNS Server instances from a single admin web console.
- Supports Single Sign-On (SSO) with OpenID Connect (OIDC).
- High performance DNS server based on async IO that can serve millions of requests per minute even on a commodity desktop PC hardware (load tested on Intel i7-8700 CPU with more than 100,000 request/second over Gigabit Ethernet).
- Self host DNS-over-TLS, DNS-over-HTTPS, and DNS-over-QUIC DNS services on your network.
- DNS-over-HTTPS implementation supports HTTP/1.1, HTTP/2, and HTTP/3 transport protocols.
- Supports DNS over PROXY protocol version 1 and 2 for both UDP and TCP transports.
- Use public DNS resolvers like Cloudflare, Google, Quad9, or AdGuard with DNS-over-TLS, DNS-over-HTTPS, or DNS-over-QUIC protocols as forwarders.
- Support for latency based name server selection algorithm that works with concurrency feature for both recursive resolution and forwarders.
- Advanced caching with features like serve stale, prefetching and auto prefetching.
- Persistent caching feature that saves cache to disk when DNS Server restarts.
- DNS rebinding attack protection feature available with DNS Rebinding Protection App.
- DNSSEC validation support with RSA, ECDSA & EdDSA algorithms for recursive resolver, forwarders, and conditional forwarders with NSEC and NSEC3 support.
- DNSSEC support for all supported DNS transport protocols including encrypted DNS protocols.
- DANE TLSA RFC 6698 record type support. This includes support for automatically generating the hash values using certificates in PEM format.
- SVCB & HTTPS RFC 9460 record type support.
- URI RFC 7553 record type support.
- SSHFP RFC 4255 record type support.
- CNAME cloaking feature to block domain names that resolve to CNAME which are blocked.
- QNAME minimization support in recursive resolver RFC 9156.
- QNAME case randomization support for UDP transport protocol draft-vixie-dnsext-dns0x20-00.
- DNAME record RFC 6672 support.
- ANAME proprietary record support to allow using CNAME like feature at zone apex (CNAME flattening). Supports multiple ANAME records at both zone apex and sub domains.
- APP proprietary record support that allows custom DNS Apps to directly handle DNS requests and return a custom DNS response based on any business logic.
- Support for features like Split Horizon and Geolocation based responses using DNS Apps feature.
- Support for REGEX based block lists with different block lists for different client IP addresses or subnet using Advanced Blocking DNS App.
- Primary, Secondary, Stub, and Conditional Forwarder zone support.
- Static stub zone support implemented in Conditional Forwarder zone to force a domain name to resolve via given name servers using NS records.
- Supports Catalog Zones RFC 9432.
- Supports record aging where the records with expiry set are automatically removed from the zone.
- Bulk conditional forwarding support using Advanced Forwarding DNS App.
- DNSSEC signed zones support with RSA, ECDSA & EdDSA algorithms.
- DNSSEC support for both NSEC and NSEC3.
- Zone transfer with AXFR and IXFR RFC 1995 and DNS NOTIFY RFC 1996 support.
- Zone transfer over TLS (XFR-over-TLS) RFC 9103 support.
- Zone transfer over QUIC (XFR-over-QUIC) RFC 9250 support.
- Support for zone validation using ZONEMD records RFC 8976 for Secondary zones.
- Dynamic DNS Updates RFC 2136 support with security policy.
- Secret key transaction authentication (TSIG) RFC 8945 support for zone transfers.
- EDNS(0) RFC6891 support.
- EDNS Client Subnet (ECS) RFC 7871 support for recursive resolution and forwarding.
- Extended DNS Errors RFC 8914 support.
- EDNS EXPIRE option RFC 7314 support.
- DNS64 function RFC 6147 support for use by IPv6 only clients using the DNS64 App.
- Support to host DNSBL / RBL block lists RFC 5782.
- Multi-user role based access with non-expiring API token support.
- Self host your domain names on your own DNS Server.
- Wildcard sub domain support.
- Enable/disable zones and records to allow testing with ease.
- Built-in DNS Client with option to import responses to local zone.
- Supports out-of-order DNS request processing for DNS-over-TCP and DNS-over-TLS protocols RFC 7766.
- Built-in DHCP Server that can work for multiple networks.
- IPv6 support in DNS Server core.
- HTTP & SOCKS5 proxy support which can be configured to route DNS over Tor Network or use Cloudflare's hidden DNS resolver.
- Admin web console for easy configuration using any web browser with support for Dark Mode.
- Built in HTTP API to allow 3rd party apps to control and configure the DNS Server.
- Supports TOTP based Two-factor authentication (2FA).
- Built-in system logging and query logging.
- Open source cross-platform .NET 10 implementation hosted on GitHub.
Supported RFCs
Read the complete list of RFCs supported by the DNS Server.
Installation
- Windows: Download setup installer for easy installation.
- Linux & Raspberry Pi: Follow install instructions from this blog post.
- Cross-Platform: Download portable app to run on any platform that has .NET 10 installed.
- Docker: Pull the official image from Docker Hub. Use the docker-compose.yml example to create a new container and edit it as required for your deployments. For more details and troubleshooting read the install instructions.
Archive
You can download binaries for the previous releases of the DNS Server from the archive.
Build Instructions
You can build the DNS Server from source and install it manually by following the Build Instructions.
Docker Environment Variables
Technitium DNS Server supports environment variables to allow initializing the config when the DNS Server starts for the first time. Read the environment variable documentation for complete details.
API Documentation
The DNS Server HTTP API allows any 3rd party app or script to configure the DNS Server. The HTTP API is used by the web console and thus all the actions that the web console does can be performed via the API. Read the HTTP API documentation for complete details.
Help Topics
Read the latest online help topics which contains the DNS Server user manual and covers frequently asked questions.
Support
For support, send an email to [email protected]. For any issues, feedback, or feature request, create an issue on GitHub.
Join /r/technitium on Reddit.
Donate
Make contribution to Technitium and help making new software, updates, and features possible.
Blog Posts
- Technitium Blog: Technitium DNS Server v15 Released! (Apr 2026)
- Technitium Blog: Understanding Clustering And How To Configure It (Nov 2025)
- How-To Geek: These open-source DNS tools block annoyances and speed up your browsing (Nov 2025)
- Technitium Blog: Technitium DNS Server v14 Released! (Nov 2025)
- XDA: Technitium is the best local DNS tool you can deploy (Aug 2025)
- Technitium Blog: How To Configure Catalog Zones For Automatic Provisioning Of Secondary Zones (Oct 2024)
- Technitium Blog: Technitium DNS Server v13 Released! (Sept 2024)
- Technitium Blog: Technitium DNS Server v12 Released! (Feb 2024)
- Technitium Blog: For DNSSEC And Why DANE Is Needed (May 2023)
- Technitium Blog: How To Auto Renew SSL Certificates With Certbot Using DNS Challenge (Mar 2023)
- Technitium Blog: Configuring DNS-over-QUIC and HTTPS/3 For Technitium DNS Server (Feb 2023)
- Technitium Blog: Technitium DNS Server v11 Released! (Feb 2023)
- Technitium Blog: Technitium DNS Server v10 Released! (Nov 2022)
- Technitium Blog: Technitium DNS Server v9 Released! (Sept 2022)
- Technitium Blog: How To Secure Your Domain Name With DNSSEC (Jul 2022)
- Technitium Blog: How To Self Host Your Own Domain Name (Jun 2022)
- Technitium Blog: Technitium DNS Server v8 Released! (Mar 2022)
- Technitium Blog: Running A Root Server Locally On Your DNS Resolver (Jul 2021)
- Yolan Romailler: Being ad-free on Android without rooting (Apr 2021)
- Technitium Blog: Creating And Running DNS Apps On Technitium DNS Server (Mar 2021)
- Technitium Blog: How To Host Your Own DNS-over-HTTPS And DNS-over-TLS Services (Oct 2020)
- Technitium Blog: How To Disable Firefox DNS-over-HTTPS On Your Network (Jul 2020)
- Technitium Blog: How To Enforce Google Safe Search And YouTube Restricted Mode On Your Network (Jul 2020)
- Technitium Blog: Technitium DNS Server v5 Released! (Jul 2020)
- Brian Wojtczak: Keep It Encrypted, Keep It Safe: Working with ESNI, DoH, and DoT (Jan 2020)
- phra's blog: Exfiltrate Like a Pro: Using DNS over HTTPS as a C2 Channel (Aug 2019)
- Scott Hanselman: Exploring DNS with the .NET Core based Technitium DNS Server (Apr 2019)
- Technitium Blog: Turn Raspberry Pi Into Network Wide DNS Server (Jan 2019)
- Technitium Blog: Blocking Internet Ads Using DNS Sinkhole (Oct 2018)
- Technitium Blog: Configuring DNS Server For Privacy & Security (Jun 2018)
- Technitium Blog: Technitium DNS Server v1.3 Released! (Jun 2018)
- Technitium Blog: Running Technitium DNS Server on Ubuntu Linux (Nov 2017)
- Technitium Blog: Technitium DNS Server Released! (Nov 2017)
File: Apps/AdvancedForwardingApp/README.md
Advanced Forwarding App
A DNS App for Technitium DNS Server that performs conditional forwarding to configured upstream resolvers.
Overview
- Conditional forwarding โ route queries by domain and client network
- Multiple forwarders โ define reusable upstream resolvers
- Proxy support โ forwarders may use a proxy server definition
- Group-based control โ forwarding rules are grouped by client network
Integration / extension points
- Implements:
IDnsApplication,IDnsAuthoritativeRequestHandler,IDnsApplicationPreference - Runs in the authoritative request path when forwarding is enabled.
Configuration
dnsApp.config contains these keys:
| Property | Type | Default | Description |
|---|---|---|---|
appPreference |
number | 200 |
App execution order. |
enableForwarding |
boolean | true |
Master switch for forwarding. |
proxyServers |
array | [] |
Proxy server definitions used by forwarders. |
forwarders |
array | [] |
Forwarder definitions. |
networkGroupMap |
object | required | Maps client networks to group names. |
groups |
array | required | Forwarding groups and their domain/forwarder mappings. |
Example
{
"appPreference": 200,
"enableForwarding": true,
"proxyServers": [
{
"name": "local-proxy",
"type": "socks5",
"proxyAddress": "localhost",
"proxyPort": 1080,
"proxyUsername": null,
"proxyPassword": null
}
],
"forwarders": [
{
"name": "quad9-doh",
"proxy": null,
"dnssecValidation": true,
"forwarderProtocol": "Https",
"forwarderAddresses": ["https://dns.quad9.net/dns-query (9.9.9.9)"]
}
],
"networkGroupMap": {
"0.0.0.0/0": "everyone",
"::/0": "everyone"
},
"groups": [
{
"name": "everyone",
"enableForwarding": true,
"forwardings": [
{
"forwarders": ["quad9-doh"],
"domains": ["*"]
}
]
}
]
}Runtime behavior
- The app selects a client group based on
networkGroupMap. - It checks whether forwarding is enabled for the selected group.
- It matches the queried domain against the group's forwarding rules.
- It returns custom FWD records for matching forwarders.
Risks / operational notes
- Overlapping forwarding rules can be hard to reason about.
- A bad upstream or proxy definition can break resolution for selected domains.
- Keep network group mappings explicit to avoid unintended routing.
Troubleshooting
- Confirm the client IP matches a group in
networkGroupMap. - Confirm the group has
enableForwarding: true. - Confirm the query domain matches one of the group's
domainsentries.
File: Apps/AdvancedBlockingApp/README.md
Advanced Blocking App
A DNS App for Technitium DNS Server that provides advanced domain blocking capabilities with support for client-based group policies, multiple block list formats, and fine-grained control over blocking behavior.
Overview
The Advanced Blocking App extends the DNS server's blocking capabilities by allowing administrators to:
- Create client-based groups with different blocking policies based on IP address, subnet, or local endpoint
- Use multiple types of block lists: domain lists, regex patterns, and AdBlock-style lists
- Configure custom blocking responses (NXDOMAIN or custom IP addresses)
- Set up allow lists to whitelist specific domains
- Map clients to groups using network addresses or DNS endpoint identifiers
โ ๏ธ Important Warning: Overlap with Default Blocking
When this app is installed and enabled, it operates independently from the DNS server's built-in blocking feature.
The Advanced Blocking App does NOT use the block lists configured in the DNS server's Settings > Blocking page. You must configure all block lists, allow lists, and blocking behavior within the app's own configuration.
You should choose one approach:
- Option A: Use the DNS server's built-in blocking (Settings > Blocking) and do NOT install this app
- Option B: Install this app and configure ALL your blocking rules here, ignoring the built-in blocking settings
Using both simultaneously may lead to confusion, as they process requests independently. The app's blocking is evaluated during the request processing pipeline and may take precedence based on processing order.
Installation
- Open Technitium DNS Server web console
- Navigate to Apps section
- Click App Store and find the Advanced Blocking App to install
- Configure the app by clicking on the Config button
Configuration
The app is configured via a JSON configuration file (dnsApp.config). Below is a complete reference of all configuration options:
Root Configuration Options
| Property | Type | Default | Description |
|---|---|---|---|
enableBlocking |
boolean | true |
Master switch to enable or disable all blocking |
blockingAnswerTtl |
integer | 30 |
TTL (in seconds) for blocking responses |
blockListUrlUpdateIntervalHours |
integer | 24 |
Hours between automatic block list updates |
blockListUrlUpdateIntervalMinutes |
integer | 0 |
Additional minutes for update interval |
localEndPointGroupMap |
object | {} |
Maps local DNS endpoints to group names |
networkGroupMap |
object | {} |
Maps client networks/IPs to group names |
groups |
array | [] |
Array of group definitions |
Local Endpoint Group Mapping
Maps specific DNS server endpoints to groups. Useful when running multiple DNS listeners (e.g., DoH, DoT, standard DNS) and wanting different policies for each.
"localEndPointGroupMap": {
"127.0.0.1": "bypass",
"192.168.10.2:53": "bypass",
"user1.dot.example.com": "kids",
"user2.doh.example.com:443": "bypass"
}Network Group Mapping
Maps client IP addresses or subnets to groups. More specific matches take precedence.
"networkGroupMap": {
"192.168.10.20": "kids",
"192.168.10.0/24": "standard",
"0.0.0.0/0": "everyone",
"::/0": "everyone"
}Group Configuration
Each group defines its own blocking policy:
| Property | Type | Default | Description |
|---|---|---|---|
name |
string | required | Unique group identifier |
enableBlocking |
boolean | true |
Enable blocking for this group |
allowTxtBlockingReport |
boolean | true |
Return blocking metadata in TXT queries and EDNS Extended DNS Error |
blockAsNxDomain |
boolean | false |
Return NXDOMAIN instead of custom IP for blocked domains |
blockingAddresses |
array | [] |
IP addresses to return for blocked A/AAAA queries |
allowed |
array | [] |
Domains explicitly allowed (whitelist) |
blocked |
array | [] |
Domains explicitly blocked |
allowListUrls |
array | [] |
URLs to domain allow lists |
blockListUrls |
array | [] |
URLs to domain block lists (string or object) |
allowedRegex |
array | [] |
Regex patterns for allowed domains |
blockedRegex |
array | [] |
Regex patterns for blocked domains |
regexAllowListUrls |
array | [] |
URLs to regex allow list files |
regexBlockListUrls |
array | [] |
URLs to regex block list files |
adblockListUrls |
array | [] |
URLs to AdBlock-format lists |
Block List URL Formats
Block list URLs can be specified as simple strings or as objects with additional options:
Simple format:
"blockListUrls": [
"https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts"
]Object format with custom options:
"blockListUrls": [
{
"url": "https://example.com/blocklist.txt",
"blockAsNxDomain": false,
"blockingAddresses": ["192.168.10.2"]
}
]Example Configuration
/* Detailed source-code truncated for AI context efficiency. */Supported Block List Formats
Domain Block Lists
Standard hosts-file format or plain domain lists:
# Comment line
0.0.0.0 ads.example.com
127.0.0.1 tracking.example.com
malware.example.comRegex Block Lists
One regex pattern per line:
# Block all subdomains starting with "ads"
^ads\.
# Block tracking domains
.*tracking.*\.com$AdBlock Lists
Supports a subset of AdBlock syntax:
! Comment
||ads.example.com^
||tracking.example.com^$all
@@||safe.example.com^How Blocking Works
Group Selection: When a DNS request arrives, the app determines which group applies based on:
- First, local endpoint mapping (
localEndPointGroupMap) - Then, client IP/network mapping (
networkGroupMap) - More specific network matches take precedence
- First, local endpoint mapping (
Allow Check: If the domain matches any allow list (static, URL-based, regex, or AdBlock whitelist), the request is NOT blocked.
Block Check: If the domain matches any block list, the app returns:
NXDOMAINifblockAsNxDomainistrue- Configured
blockingAddressesfor A/AAAA queries - NO DATA response for other query types
Blocking Report: When
allowTxtBlockingReportis enabled:- TXT queries for blocked domains return metadata about why the domain was blocked
- EDNS Extended DNS Error option is included in responses
Use Cases
- Parental Controls: Create a "kids" group with stricter blocking for children's devices
- Guest Network: Apply different policies to guest WiFi subnet
- IoT Isolation: Block telemetry for IoT devices on a specific VLAN
- Multi-tenant DNS: Different blocking policies for different clients sharing the same DNS server
- DoH/DoT Differentiation: Apply different policies based on DNS transport protocol
Troubleshooting
Block lists not updating
- Check the DNS server logs for download errors
- Verify the URLs are accessible from the server
- Ensure the server has internet connectivity (or proxy configured)
Domains not being blocked
- Verify the client IP maps to the correct group
- Check if the domain is in an allow list
- Confirm
enableBlockingistrueat both root and group level - Review the group's block list configuration
Testing blocking
Query a TXT record for a blocked domain from the client IP address to see the blocking report:
dig TXT blocked-domain.com @your-dns-serverFile: Apps/AutoPtrApp/README.md
Auto PTR App
A DNS App for Technitium DNS Server that automatically generates reverse DNS (PTR) responses for both IPv4 and IPv6 addresses based on configurable domain name templates.
This app enables dynamic PTR record responses in primary and forwarder zones without manually creating individual PTR records for every IP address. It constructs PTR responses by parsing the IP address from the reverse lookup query and formatting it into a domain name using configurable prefix, suffix, and separator patterns.
Overview
The Auto PTR App extends Technitium DNS Server's core functionality by providing automated PTR record generation for reverse DNS zones. Instead of maintaining extensive static PTR record sets, administrators can deploy APP records that dynamically construct responses based on the queried IP address.
Key capabilities:
- Automatic PTR response generation from reverse DNS queries (in-addr.arpa / ip6.arpa)
- IPv4 and IPv6 support with independent formatting rules
- Customizable domain templates using prefix, suffix, and IP component separators
- Zone-level deployment as APP records in primary or forwarder zones
- Standards-compliant DNS behavior including proper NODATA responses for non-PTR queries
This app is particularly valuable for environments requiring consistent, pattern-based reverse DNS naming without manual PTR record maintenance.
Installation
Open the Technitium DNS Server web console.
Navigate to Apps section.
Click App Store and find the Auto PTR app to install.
Configure APP records in the appropriate reverse DNS zone(s).
Configuration
Configuration is performed per APP record deployment, not at the application level. The app itself requires no global configuration file (dnsApp.config contains no settings).
Each APP record uses JSON-formatted data to define the PTR response template.
APP Record Configuration Properties
When creating an APP record in a reverse DNS zone, use the following JSON structure:
| Property | Type | Default | Description |
|---|---|---|---|
prefix |
string | "" (empty) |
Static string prepended to the generated domain name |
suffix |
string | "" (empty) |
Static string appended to the generated domain name (typically the domain) |
ipSeparator |
string | "" (empty) |
Character(s) inserted between IP address components in the domain name |
Domain Name Construction
The app constructs PTR responses as follows:
For IPv4 addresses:
- Extracts the four octets from the IP address
- Converts each octet to its decimal string representation
- Joins octets using
ipSeparator - Prepends
prefixand appendssuffix
For IPv6 addresses:
- Extracts the 16 bytes from the IP address
- Processes bytes in pairs (16-bit words)
- Converts each pair to lowercase hexadecimal (e.g.,
2001โ2001,00dbโ00db) - Joins words using
ipSeparator - Prepends
prefixand appendssuffix
Example Configuration
Basic IPv4 Example
{
"prefix": "",
"suffix": ".example.com",
"ipSeparator": "-"
}Query: PTR for 1.0.168.192.in-addr.arpa (reverse of 192.168.0.1)
Response: 192-168-0-1.example.com
IPv4 with Prefix
{
"prefix": "host-",
"suffix": ".internal.example.net",
"ipSeparator": "."
}Query: PTR for 10.20.30.10.in-addr.arpa (reverse of 10.30.20.10)
Response: host-10.30.20.10.internal.example.net
IPv6 Example
{
"prefix": "v6-",
"suffix": ".ip6.example.org",
"ipSeparator": "-"
}Query: PTR for IPv6 reverse (e.g., 2001:db8::1)
Response: v6-2001-0db8-0000-0000-0000-0000-0000-0001.ip6.example.org
How It Works
The app processes reverse DNS queries through the following execution pipeline:
Query Reception: The app receives a DNS query for a name within the reverse DNS zone where the APP record is configured.
Reverse Domain Parsing: The query name (QNAME) is parsed to extract the IP address using reverse DNS notation (in-addr.arpa for IPv4, ip6.arpa for IPv6).
Query Type Validation:
- If the query type is PTR, proceed to step 4.
- If the query type is not PTR, return a NODATA response (NOERROR with SOA in authority section).
Domain Name Generation: The IP address is formatted into a domain name using the configured
prefix,ipSeparator, andsuffixvalues.Response Construction: A DNS response is built containing a PTR record with the generated domain name and the APP record's configured TTL.
Response Transmission: The authoritative response is returned to the client with the AA (Authoritative Answer) flag set.
Use Cases
- Automated reverse DNS for DHCP ranges: Generate consistent PTR records for dynamically assigned IP addresses without manual updates.
- ISP customer IP reverse DNS: Automatically provide reverse DNS for customer IP allocations using standardized naming patterns (e.g.,
ip-192-0-2-1.customer.isp.example). - Internal network documentation: Create self-documenting reverse DNS where the PTR record contains the IP address in a readable format.
- IPv6 deployment support: Simplify reverse DNS management for large IPv6 allocations where manual PTR record creation is impractical.
- Multi-tenant hosting environments: Provide automatic reverse DNS for hosting infrastructure using tenant identifiers in the prefix.
- Compliance with email server requirements: Ensure all mail server IPs have reverse DNS records without maintaining extensive PTR record sets.
Troubleshooting
No PTR Response Returned
Symptoms: Queries to the reverse DNS zone return NXDOMAIN or no answer.
Resolution:
- Verify the APP record is configured in the correct reverse DNS zone (e.g.,
168.192.in-addr.arpafor 192.168.0.0/16). - Ensure the APP record name covers the IP range being queried (e.g.,
0.168.192.in-addr.arpafor 192.168.0.0/24). - Check that the AutoPtrApp is installed and enabled in the DNS Server Apps section.
- Review DNS query logs to confirm the query is reaching the zone.
Malformed PTR Response
Symptoms: PTR responses contain unexpected characters or formatting.
Resolution:
- Verify JSON configuration syntax in the APP record data field.
- Check
ipSeparatorvalue for unintended characters or escape sequences. - Ensure
prefixandsuffixvalues do not contain invalid DNS label characters. - Test with minimal configuration (empty prefix/separator) to isolate the issue.
Non-PTR Queries Return Incorrect Responses
Symptoms: A, AAAA, or other query types to the reverse zone return unexpected results.
Resolution:
- This is expected behavior. The app returns NODATA (NOERROR with SOA) for non-PTR queries.
- If other record types are needed, configure them as standard zone records, not APP records.
IPv6 Reverse DNS Not Working
Symptoms: IPv6 PTR queries fail while IPv4 works correctly.
Resolution:
- Verify the APP record is in the correct ip6.arpa zone (e.g.,
8.b.d.0.1.0.0.2.ip6.arpa). - Confirm the query is formatted as a valid IPv6 reverse DNS name.
- Check logs for reverse domain parsing errors.
File: Apps/BlockPageApp/README.md
Block Page App
A DNS App for Technitium DNS Server that serves a configurable block page from an embedded web server.
Overview
- Embedded web server โ serves a local page to users trying to access blocked domains
- Multiple instances โ supports one or more named web server configurations
- TLS support โ self-signed or custom PKCS#12 certificates
- MiTM support - serves block page over HTTPS with TLS certificate for the blocked domain name generated online, that is signed by a self-signed root certificate which can be install on client systems
- Dynamic or static mode โ generate a page or serve files from a web root
Integration / extension points
- Implements:
IDnsApplication - Runs a built-in ASP.NET Core web server.
Configuration
dnsApp.config can be either a single object or an array of objects. Each object supports:
| Property | Type | Default | Description |
|---|---|---|---|
name |
string | default |
Instance name. |
enableWebServer |
boolean | true |
Enables the web server instance. |
webServerLocalAddresses |
string[] | [] |
Local IPs to bind to. |
webServerUseSelfSignedTlsCertificate |
boolean | true |
Use a generated self-signed certificate. |
webServerTlsCertificateFilePath |
string | null |
Path to a .pfx/.p12 certificate. |
webServerTlsCertificatePassword |
string | null |
Certificate password. |
webServerEnableOnlineCertificateSigning |
boolean | Enables the online TLS certificate generation feature for enabling HTTPS MiTM. | |
webServerRootPath |
string | wwwroot |
Static file root. |
serveBlockPageFromWebServerRoot |
boolean | false |
Serve static files instead of generated block page. |
blockPageTitle |
string | Website Blocked |
Page title. |
blockPageHeading |
string | Website Blocked |
Page heading. |
blockPageMessage |
string | This website has been blocked by your network administrator. |
Page message. |
includeBlockingInfo |
boolean | true |
Include blocking info/EDE details on page. |
Example
[
{
"name": "default",
"enableWebServer": true,
"webServerLocalAddresses": ["0.0.0.0", "::"],
"webServerUseSelfSignedTlsCertificate": true,
"webServerTlsCertificateFilePath": null,
"webServerTlsCertificatePassword": null,
"webServerEnableOnlineCertificateSigning": true,
"webServerRootPath": "wwwroot",
"serveBlockPageFromWebServerRoot": false,
"blockPageTitle": "Website Blocked",
"blockPageHeading": "Website Blocked",
"blockPageMessage": "This website has been blocked by your network administrator.",
"includeBlockingInfo": true
}
]Runtime behavior
- The app starts one or more embedded web servers.
- If
serveBlockPageFromWebServerRootisfalse, it generates a page from the title/heading/message values. - If
serveBlockPageFromWebServerRootistrue, it serves static content fromwebServerRootPath. - HTTPS can use a self-signed certificate or a custom PKCS#12 certificate.
Risks / operational notes
- Browsers will warn on self-signed certificates if the certificate is not installed on the client system.
- This app does not block queries by itself; DNS blocking must still be configured separately.
- Ensure the IPs in
webServerLocalAddressesmatch the DNS blocking target addresses.
Troubleshooting
- Confirm the web server binds to the expected IP/port.
- Confirm DNS blocking points clients to the web server IP.
- Verify the certificate path and password if using a custom certificate.
File: Apps/DefaultRecordsApp/README.md
Default Records App
A DNS App for Technitium DNS Server that applies configurable default DNS records to authoritative zones during query post-processing.
This application enables system administrators to define reusable sets of DNS resource records and map them to specific zones or all zones using wildcard patterns. Default records are injected into DNS responses when the server returns authoritative answers, allowing for centralized management of common DNS records across multiple zones.
Overview
The Default Records App extends Technitium DNS Server's core functionality by implementing a post-processor that intercepts authoritative DNS responses and conditionally injects predefined DNS resource records.
Key capabilities include:
- Zone-to-Set Mapping: Associate one or more record sets with specific zones, wildcard zones, or all zones
- Reusable Record Sets: Define named collections of DNS records in standard zone file format
- Conditional Application: Records are applied only to authoritative responses with
NOERRORorNXDOMAINcodes - Dynamic Zone Resolution: Supports wildcard zone mappings with automatic SOA-based zone detection
- Type-Specific Filtering: Default records are matched against query type and name before injection
This application is particularly useful for administrators managing multiple zones that share common DNS records such as SPF, DKIM, MX, or branding-related CNAME records.
Installation
- Open the Technitium DNS Server web console
- Navigate to Apps section
- Click App Store and find the Default Records App to install
- Configure the app by clicking on the Config button
Configuration
The application is configured using a JSON file named dnsApp.config located in the app's installation directory.
The configuration file defines three primary components: global settings, zone-to-set mappings, and record sets.
Root Configuration Options
| Property | Type | Default | Description |
|---|---|---|---|
enableDefaultRecords |
boolean | false |
Master switch to enable or disable default record processing |
defaultTtl |
unsigned integer | 3600 |
Default TTL (in seconds) applied to records when not explicitly specified in zone file format |
zoneSetMap |
object | {} |
Maps zone names (or patterns) to arrays of set names |
sets |
array | [] |
Array of record set objects defining reusable DNS records |
Zone-to-Set Mapping
The zoneSetMap object defines which record sets apply to which zones.
Purpose: Controls the scope of default record application by mapping zone names to one or more record sets.
Key Features:
- Exact zone matching (e.g.,
"example.org") - Wildcard suffix matching (e.g.,
"*.net"applies to all.netzones) - Global wildcard (
"*") applies to all zones not matched by more specific rules - Multiple sets can be assigned to a single zone
JSON Example:
"zoneSetMap": {
"*": ["global-set"],
"*.com": ["commercial-set"],
"*.net": ["network-set", "email-set"],
"example.org": ["custom-set", "email-set"]
}Matching Logic:
- The app performs hierarchical zone matching from most specific to least specific
- Exact zone names have priority over wildcard patterns
- Wildcard patterns (
*.parent.zone) are checked before ascending to parent zones - The global wildcard (
*) is used only when no other match is found
Record Set Configuration
Each object in the sets array defines a named collection of DNS resource records.
| Property | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Unique identifier for the set, referenced in zoneSetMap |
enable |
boolean | Yes | Whether this set is active; disabled sets are ignored even if mapped |
records |
array of strings | Yes | DNS resource records in standard zone file format |
JSON Example:
"sets": [
{
"name": "email-set",
"enable": true,
"records": [
"@ 3600 IN MX 10 mail.example.com.",
"@ 3600 IN TXT \"v=spf1 a mx -all\"",
"@ 3600 IN TXT \"v=DMARC1; p=reject; rua=mailto:[email protected]\""
]
},
{
"name": "web-set",
"enable": true,
"records": [
"www 3600 IN CNAME @",
"ftp 3600 IN CNAME @"
]
}
]DNS Record Format
Records in the records array must follow the standard zone file syntax as defined in RFC 1035.
Format: <name> <ttl> <class> <type> <rdata>
Simple Example:
@ 3600 IN A 192.0.2.1
www 7200 IN CNAME @Advanced Example:
@ 3600 IN MX 10 mail.example.com.
@ 3600 IN TXT "v=spf1 ip4:192.0.2.0/24 -all"
_dmarc 3600 IN TXT "v=DMARC1; p=quarantine; rua=mailto:[email protected]"
mail 3600 IN A 192.0.2.10
mail 3600 IN AAAA 2001:db8::10Formatting Conventions:
- The
@symbol represents the zone apex (e.g.,example.com) - Names without a trailing dot are relative to the zone origin
- Names with a trailing dot are fully qualified domain names (FQDNs)
- TTL values are in seconds; if omitted,
defaultTtlis applied - TXT records must be enclosed in double quotes
Example Configuration
{
"enableDefaultRecords": true,
"defaultTtl": 3600,
"zoneSetMap": {
"*": ["global-defaults"],
"*.com": ["commercial-branding"],
"*.org": ["nonprofit-email"],
"example.net": ["custom-example-net"]
},
"sets": [
{
"name": "global-defaults",
"enable": true,
"records": [
"@ 3600 IN TXT \"v=spf1 -all\"",
"www 3600 IN CNAME @"
]
},
{
"name": "commercial-branding",
"enable": true,
"records": [
"www 7200 IN CNAME @",
"ftp 7200 IN CNAME @",
"mail 3600 IN A 203.0.113.10"
]
},
{
"name": "nonprofit-email",
"enable": true,
"records": [
"@ 3600 IN MX 10 mail.example.org.",
"@ 3600 IN TXT \"v=spf1 mx -all\"",
"_dmarc 3600 IN TXT \"v=DMARC1; p=reject\""
]
},
{
"name": "custom-example-net",
"enable": false,
"records": [
"test 300 IN A 198.51.100.1"
]
}
]
}Supported Resource Record Types
The Default Records App supports all DNS resource record types recognized by Technitium DNS Server and the TechnitiumLibrary zone file parser.
Commonly Used Types:
- A: IPv4 address record
- AAAA: IPv6 address record
- CNAME: Canonical name (alias) record
- MX: Mail exchange record
- TXT: Text record (SPF, DKIM, DMARC, verification tokens)
- NS: Name server record
- SRV: Service locator record
- CAA: Certification Authority Authorization record
- PTR: Pointer record (reverse DNS)
Format Examples:
@ 3600 IN A 192.0.2.1
@ 3600 IN AAAA 2001:db8::1
@ 3600 IN MX 10 mail.example.com.
@ 3600 IN TXT "v=spf1 mx -all"
_sip._tcp 3600 IN SRV 10 60 5060 sipserver.example.com.
@ 3600 IN CAA 0 issue "letsencrypt.org"How Default Record Processing Works
The application operates as a DNS post-processor that intercepts responses before they are sent to the client.
- Response Interception: The app receives the DNS response generated by the server core
- Eligibility Validation: Processing occurs only if:
enableDefaultRecordsis set totrue- The response has the Authoritative Answer flag set
- The operation code is StandardQuery
- The response code is NOERROR or NXDOMAIN
- Zone Matching: The queried domain name is matched against
zoneSetMapusing hierarchical pattern matching - Set Selection: Mapped set names are retrieved; only enabled sets are processed
- Record Parsing: Records from selected sets are parsed using the zone file parser with the resolved zone as origin
- Record Filtering: Parsed records are filtered based on:
- Matching DNS class (e.g.,
IN) - Matching record type or
CNAME - Matching queried domain name (accounting for CNAME chains)
- Matching DNS class (e.g.,
- Response Construction: Matching records are appended to the answer section, and a new response datagram is returned
- Client Delivery: The modified response is sent to the client
Wildcard Zone Handling:
When a wildcard zone pattern is matched (e.g., "*.net"), the app queries the DNS server for the SOA record of the queried domain to determine the actual zone name before parsing records.
Use Cases
- Centralized Email Security Policies: Apply SPF, DKIM, and DMARC records to all zones under management without manual configuration per zone.
- Branding and Redirect Standardization: Automatically create
wwwCNAME records pointing to the zone apex across all commercial domains. - Testing and Staging Environments: Inject test-specific DNS records into staging zones without modifying production zone files.
- Multi-Tenant Hosting Platforms: Apply provider-specific MX, NS, or CAA records to all customer zones using wildcard mappings.
- Compliance and Audit Requirements: Ensure all zones contain mandatory TXT records for domain verification or security policies.
- Default Gateway and Service Discovery: Provide SRV records for common services (e.g., LDAP, SIP) across an organization's internal zones.
Troubleshooting
Default Records Not Appearing in Responses
Diagnostic Steps:
- Verify
enableDefaultRecordsis set totrueindnsApp.config - Confirm the queried zone matches a pattern in
zoneSetMap - Check that the referenced set exists and has
enable: true - Ensure the DNS server is returning an authoritative answer for the zone
- Verify the response code is
NOERRORorNXDOMAIN
Check Logs:
Look for errors related to zone file parsing or record format issues from the Logs section on the web console.
Records Applied to Wrong Zones
Diagnostic Steps:
- Review the
zoneSetMapfor overlapping patterns - Verify wildcard patterns are correctly formatted (e.g.,
"*.com"not".com") - Test zone matching logic by querying domains and checking applied sets
- Ensure zone names in
zoneSetMapare lowercase (case normalization is automatic)
Configuration Check:
Ensure specific zone mappings appear after wildcard patterns in the map to avoid confusion during manual review (although JSON object order does not affect matching).
Zone File Parsing Errors
Diagnostic Steps:
- Validate record syntax against RFC 1035 zone file format
- Check for missing trailing dots on FQDNs
- Verify TXT record content is enclosed in double quotes
- Ensure TTL values are positive integers
- Confirm record class is specified (usually
IN)
Example Error:
Invalid zone file entry: missing TTL or classResolution:
Correct the record format:
"records": [
"@ IN A 192.0.2.1" // Missing TTL - uses defaultTtl
]Should be:
"records": [
"@ 3600 IN A 192.0.2.1"
]Wildcard Zone Matching Not Resolving
Diagnostic Steps:
- Verify the DNS server has an SOA record for the queried zone
- Check that the zone is configured as authoritative
- Test SOA query independently:
dig @server example.com SOA - Review logs for SOA query failures during post-processing
Resolution:
Ensure the zone is properly configured as an authoritative zone in Technitium DNS Server before applying wildcard default records.
File: Apps/Dns64App/README.md
DNS64 App
A DNS App for Technitium DNS Server that implements RFC 6147 DNS64 functionality to enable IPv6-only clients to access IPv4-only resources through DNS protocol translation.
This app extends the Technitium DNS Server to synthesize AAAA records from A records, allowing IPv6-only clients to discover and access IPv4 resources when used in conjunction with a NAT64 gateway. The app operates as both a post-processor for recursive queries and an authoritative request handler for reverse DNS lookups within the DNS64 address space.
Overview
DNS64 App implements DNS Extensions for Network Address Translation from IPv6 Clients to IPv4 Servers as defined in RFC 6147. The app enables seamless connectivity for IPv6-only networks by translating IPv4 addresses into synthesized IPv6 addresses using configurable prefix mappings.
Key capabilities include:
- Automatic AAAA record synthesis from A records for AAAA queries
- Network-based group policies for fine-grained DNS64 control
- Configurable IPv6 prefix mappings with support for standard prefix lengths (32, 40, 48, 56, 64, 96)
- IPv6 address exclusions to prevent synthesis for specific ranges
- Reverse DNS (PTR) handling for synthesized IPv6 addresses
- DNSSEC-aware operation that bypasses DNS64 when DNSSEC validation is requested
This app provides critical infrastructure support for dual-stack migration strategies and IPv6-only network deployments.
โ ๏ธ Important Warning: NAT64 Dependency
DNS64 must be deployed in conjunction with a functional NAT64 gateway. The app performs DNS protocol translation onlyโit does not provide network address translation.
Operational Risk:
Installing and enabling DNS64 App without a corresponding NAT64 gateway in place will cause connectivity failures for IPv6-only clients attempting to reach IPv4-only destinations. Synthesized AAAA records will resolve to IPv6 addresses that cannot be routed without NAT64.
Deployment Options:
- Option A: Deploy NAT64 gateway first, then enable DNS64 App
- Option B: Configure DNS64 App with
enableDns64: falseinitially, deploy NAT64, then enable DNS64
Processing Order:
DNS64 operates as a post-processor in the DNS resolution pipeline. It processes responses after recursive resolution and before returning results to clients.
Installation
Open the Technitium DNS Server web console
Navigate to Apps section
Click App Store and find the DNS64 App to install
Configure the app by clicking on the Config button
Configuration
The DNS64 App is configured through the dnsApp.config JSON file. The configuration defines global settings, network-to-group mappings, and per-group DNS64 policies.
All configuration options are documented below. The structure supports hierarchical policy enforcement based on client network origin.
Root Configuration Options
| Property | Type | Default | Description |
|---|---|---|---|
appPreference |
integer | 30 | Processing priority when multiple apps implement IDnsApplicationPreference. Lower values execute first. |
enableDns64 |
boolean | (required) | Global DNS64 enable flag. When false, app is inactive regardless of group settings. |
networkGroupMap |
object | (required) | Maps client network addresses (CIDR notation) to named groups. Longest prefix match determines group assignment. |
groups |
array | (required) | Array of group objects defining DNS64 policies. Groups are referenced by name from networkGroupMap. |
Network Group Mapping
The networkGroupMap object maps client source networks to named policy groups using CIDR notation as keys and group names as values.
Purpose:
Enables differentiated DNS64 behavior based on client network origin. Supports granular policy enforcement for internal vs. external clients, different VLANs, or trust zones.
Matching Logic:
The app performs longest prefix match. If a client IP matches multiple networks, the most specific (longest prefix length) mapping is selected.
JSON Example:
"networkGroupMap": {
"::/0": "default-group",
"2001:db8:1000::/48": "internal-group",
"2001:db8:2000::/48": "guest-group"
}Group Configuration
Each group object defines a complete DNS64 policy.
| Property | Type | Default | Description |
|---|---|---|---|
name |
string | (required) | Unique identifier for the group. Referenced by networkGroupMap. |
enableDns64 |
boolean | (required) | Group-level DNS64 enable flag. Allows per-group activation/deactivation. |
dns64PrefixMap |
object | (required) | Maps IPv4 network ranges to DNS64 IPv6 prefixes. Keys are IPv4 CIDR, values are IPv6 prefix strings or null. |
excludedIpv6 |
array | [] |
Array of IPv6 network addresses (CIDR) to exclude from DNS64 processing. Existing AAAA records in these ranges suppress synthesis. |
DNS64 Prefix Mapping
The dns64PrefixMap object within each group defines how IPv4 addresses are translated into IPv6 addresses.
Structure:
Keys are IPv4 network addresses in CIDR notation. Values are either:
- IPv6 prefix string (CIDR notation) to use for synthesis
nullto exclude the IPv4 range from DNS64 processing
Prefix Length Constraints:
DNS64 prefixes must use one of the following RFC 6147-compliant prefix lengths: 32, 40, 48, 56, 64, or 96.
Matching Logic:
Longest prefix match. The most specific IPv4 network match determines the DNS64 prefix used for synthesis.
JSON Example:
"dns64PrefixMap": {
"0.0.0.0/0": "64:ff9b::/96",
"10.0.0.0/8": null,
"172.16.0.0/12": null,
"192.168.0.0/16": null,
"203.0.113.0/24": "2001:db8:64::/96"
}Explanation:
- All IPv4 addresses use
64:ff9b::/96prefix (well-known prefix from RFC 6052) - RFC 1918 private addresses (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) are excluded
- Public range 203.0.113.0/24 uses custom prefix
2001:db8:64::/96
IPv6 Exclusion List
The excludedIpv6 array prevents DNS64 synthesis when existing AAAA records fall within specified IPv6 ranges.
Purpose:
Prevents synthesis when legitimate IPv6 addresses already exist but should not be used (e.g., IPv4-mapped IPv6 addresses).
Common Exclusions:
::ffff:0:0/96โ IPv4-mapped IPv6 addresses (RFC 4291 Section 2.5.5.2)
JSON Example:
"excludedIpv6": [
"::ffff:0:0/96",
"2001:db8:exclude::/48"
]Example Configuration
{
"appPreference": 30,
"enableDns64": true,
"networkGroupMap": {
"::/0": "everyone",
"2001:db8:internal::/48": "internal-ipv6"
},
"groups": [
{
"name": "everyone",
"enableDns64": true,
"dns64PrefixMap": {
"0.0.0.0/0": "64:ff9b::/96",
"10.0.0.0/8": null,
"172.16.0.0/12": null,
"192.168.0.0/16": null
},
"excludedIpv6": [
"::ffff:0:0/96"
]
},
{
"name": "internal-ipv6",
"enableDns64": true,
"dns64PrefixMap": {
"0.0.0.0/0": "2001:db8:64::/96",
"10.0.0.0/8": "2001:db8:64:a::/96",
"172.16.0.0/12": "2001:db8:64:ac::/96",
"192.168.0.0/16": "2001:db8:64:c0::/96"
},
"excludedIpv6": [
"::ffff:0:0/96"
]
}
]
}DNS64 Prefix Formats
The app supports standard RFC 6147 prefix lengths. The IPv4 address is embedded within the IPv6 prefix according to the prefix length.
Supported Prefix Lengths:
| Prefix Length | Format | IPv4 Embedding |
|---|---|---|
/32 |
pppp:pppp::/32 |
Bits 32-63 and 64-95 |
/40 |
pppp:pppp:pp00::/40 |
Bits 40-63 and 64-95 |
/48 |
pppp:pppp:pppp::/48 |
Bits 48-63 and 64-95 |
/56 |
pppp:pppp:pppp:pp00::/56 |
Bits 56-63 and 64-95 |
/64 |
pppp:pppp:pppp:pppp::/64 |
Bits 64-95 |
/96 |
pppp:pppp:pppp:pppp:pppp:pppp::/96 |
Bits 96-127 |
Well-Known Prefix:
RFC 6052 defines 64:ff9b::/96 as the well-known prefix for DNS64/NAT64 deployments.
Example:
IPv4 address 192.0.2.1 with prefix 64:ff9b::/96 becomes 64:ff9b::192.0.2.1 or 64:ff9b::c000:201.
How DNS64 Processing Works
The DNS64 App implements two distinct processing paths:
AAAA Query Processing (Post-Processor)
- Request Validation: App checks if DNS64 is enabled globally and DNSSEC is not requested
- Response Analysis: App evaluates recursive resolver response for AAAA query
- Group Selection: Client source IP is matched against
networkGroupMapusing longest prefix match - Exclusion Check: If AAAA records exist and fall outside
excludedIpv6ranges, no synthesis occurs - A Record Query: If no valid AAAA records exist, app performs internal A record query
- Prefix Mapping: Each A record is matched against
dns64PrefixMapusing longest prefix match - AAAA Synthesis: IPv4 addresses are embedded in IPv6 prefix to generate synthesized AAAA records
- Response Construction: Synthesized AAAA records are added to response with TTL capped by SOA minimum
PTR Query Processing (Authoritative Handler)
- Request Validation: App checks if query is PTR for
.ip6.arpadomain - Group Selection: Client source IP is matched against
networkGroupMap - Prefix Match: Reverse IPv6 address is matched against configured
dns64PrefixMapvalues - IPv4 Extraction: IPv4 address is extracted from synthesized IPv6 address
- CNAME Response: App returns authoritative CNAME record pointing to
.in-addr.arpadomain - Recursive Resolution: DNS server follows CNAME to resolve PTR from IPv4 reverse zone
Use Cases
- IPv6-Only Client Networks: Deploy DNS64 App to enable IPv6-only clients to access IPv4-only internet resources without dual-stack client configuration. Commonly used in mobile carrier networks and modern enterprise IPv6 migrations.
- Dual-Stack Transition Strategy: Use DNS64 to provide fallback connectivity for IPv6-capable clients when communicating with legacy IPv4-only services during incremental IPv6 deployment.
- ISP IPv6 Service Delivery: Internet service providers deploy DNS64 alongside carrier-grade NAT64 to offer IPv6-only residential or business services while maintaining backward compatibility with IPv4 internet.
- Enterprise Internal IPv6 Migration: Organizations deploying IPv6-only internal networks use DNS64 to maintain access to IPv4-only internal applications and third-party SaaS platforms during migration.
- Testing and Development Environments: Network engineers use DNS64 in lab environments to simulate IPv6-only client conditions and validate application IPv6 readiness without full infrastructure changes.
- Geographic DNS64 Prefix Routing: Organizations with multiple regional NAT64 gateways use network group mappings to direct clients to geographically appropriate DNS64 prefixes and NAT64 infrastructure.
Troubleshooting
DNS64 Not Synthesizing AAAA Records
Symptoms: IPv6-only clients receive no AAAA records for domains that should trigger DNS64 synthesis.
Diagnostic Steps:
- Verify
enableDns64: trueat both root and group level - Confirm client source IP matches a network in
networkGroupMap - Check that target IPv4 address is not excluded via
dns64PrefixMap: nullmapping - Verify DNSSEC is not requested by client (app bypasses DNSSEC queries)
- Confirm existing AAAA records are not present or are in
excludedIpv6ranges
Configuration Check:
Review dns64PrefixMap for correct CIDR notation and prefix lengths (32, 40, 48, 56, 64, 96 only).
Logs:
Enable DNS server query logging to observe DNS64 post-processing behavior and internal A record queries.
Synthesized AAAA Records Not Reachable
Symptoms: Clients receive AAAA records but connections fail or time out.
Diagnostic Steps:
- Verify NAT64 gateway is operational and reachable from client network
- Confirm NAT64 prefix configuration matches DNS64
dns64PrefixMapprefixes - Test NAT64 connectivity using ping6 to known IPv4 address:
ping6 64:ff9b::8.8.8.8 - Check routing for DNS64 prefix range to NAT64 gateway
- Verify NAT64 gateway has IPv4 routing to destination
Common Cause:
DNS64 deployed without corresponding NAT64 infrastructure.
Private IPv4 Addresses Being Synthesized
Symptoms: RFC 1918 private addresses (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) are converted to IPv6.
Resolution:
Add exclusions to dns64PrefixMap:
"dns64PrefixMap": {
"10.0.0.0/8": null,
"172.16.0.0/12": null,
"192.168.0.0/16": null
}Private IPv4 addresses should generally not be translated unless dual-stack NAT64 is explicitly configured.
Reverse DNS (PTR) Queries Failing
Symptoms: PTR queries for synthesized IPv6 addresses return NXDOMAIN.
Diagnostic Steps:
- Verify synthesized IPv6 address falls within configured DNS64 prefix
- Confirm corresponding IPv4 reverse zone (
.in-addr.arpa) exists and is resolvable - Check DNS server logs for CNAME processing from
.ip6.arpato.in-addr.arpa
Expected Behavior:
App returns authoritative CNAME from .ip6.arpa to .in-addr.arpa, then server recursively resolves PTR.
DNS64 Prefix Length Error
Symptoms: Configuration validation fails with "DNS64 prefix can have only the following prefixes" error.
Resolution:
Verify all DNS64 prefix values in dns64PrefixMap use only permitted prefix lengths: /32, /40, /48, /56, /64, or /96.
Invalid Example:
"dns64PrefixMap": {
"0.0.0.0/0": "2001:db8::/80" // Invalid - /80 is not one of the supported prefix lengths
}Corrected Example:
"dns64PrefixMap": {
"0.0.0.0/0": "2001:db8:64::/96"
}File: Apps/DnsBlockListApp/README.md
DNS Block List App
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.
Overview
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:
- IP-based block lists supporting both IPv4 and IPv6 addresses and networks
- Domain-based block lists with hierarchical matching
- Customizable A and TXT record responses per block list or per entry
- Automatic file reloading when block list files are modified
- Multiple block list support with independent configuration
- RFC 5782 compliance for DNS blacklist/whitelist implementation
This application provides administrative value for network operators implementing reputation-based filtering, threat intelligence integration, or compliance-driven access control at the DNS layer.
Installation
- Open the Technitium DNS Server web console
- Navigate to Apps section
- Click App Store and find the DNS Block List (DNSBL) App to install
- Configure the app by clicking on the Config button
Configuration
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.
Root Configuration Options
| Property | Type | Default | Description |
|---|---|---|---|
dnsBlockLists |
array | [] |
Array of block list configuration objects |
Block List Configuration
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 Format
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::/64Lines beginning with # are treated as comments. Empty lines are ignored.
Domain Block List Format
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.
Example Configuration
{
"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"
}
]
}APP Record Configuration
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.
How DNSBL Queries Work
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:
- An IPv4 address (4 reversed octets)
- An IPv6 address (32 reversed hex nibbles)
- A domain name (standard label format)
Block List Lookup: The extracted address or domain is checked against each configured block list in order
Response Generation:
- For A queries: Returns the configured A record (default or entry-specific)
- For TXT queries: Returns the configured TXT record with placeholder substitution
- For other query types: Returns NODATA response (SOA record from zone)
NXDOMAIN Response: If the address/domain is not found in any enabled block list, returns NXDOMAIN
Supported Query Formats
IPv4 Address Queries
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
IPv6 Address Queries
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
Domain Queries
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.
RFC 5782 Compliance
This implementation adheres to RFC 5782 (DNS Blacklists and Whitelists):
- Test entries: Both IP and domain block lists include RFC-mandated test entries (
127.0.0.2for IP,testfor domain) - Response format: Standard A record responses in the
127.0.0.0/8range - TXT record support: Optional descriptive TXT records for blocked entries
- NXDOMAIN semantics: Unlisted entries return NXDOMAIN as specified
Use Cases
- Spam Prevention: Deploy email server IP reputation lists to identify and block mail from known spam sources
- Threat Intelligence Integration: Load IP addresses and domains from threat feeds to prevent connections to malicious infrastructure
- Compliance Enforcement: Implement organizational policies blocking access to specific IP ranges or domain categories
- Network Abuse Mitigation: Maintain dynamic block lists of IPs exhibiting abusive behavior detected by intrusion prevention systems
- Content Filtering: Create domain block lists for categories requiring access restrictions (parental controls, workplace policies)
- Security Testing: Verify DNSBL integration in mail servers and security appliances using standardized test entries
Automatic Reloading
The application monitors block list files for modifications and automatically reloads them when changes are detected.
- Reload interval: 60 seconds
- Detection method: File modification timestamp comparison
- Logging: Reload events and errors are written to the DNS Server log
- Thread safety: Atomic updates ensure consistent lookups during reload operations
No server restart or manual intervention is required when updating block list files.
Response Priority
When an entry is found in a block list, the A and TXT responses are selected using the following priority:
- Entry-specific response (defined in block list file)
- Block list default response (defined in
dnsApp.config) - Application default (
127.0.0.2)
This allows granular control: global defaults can be overridden per block list, and individual entries can specify unique responses.
Troubleshooting
Block List Not Loading
Symptoms: Queries return NXDOMAIN for known blocked entries; log shows file read errors
Resolution:
- Verify the
blockListFilepath indnsApp.config - Check file permissions (application must have read access)
- Review DNS Server logs for specific error messages
- Ensure file uses UTF-8 encoding without BOM
- Validate file format (check separator characters, syntax)
Queries Return NXDOMAIN for Blocked Entries
Symptoms: Known blocked IPs/domains return NXDOMAIN instead of A/TXT records
Resolution:
- Verify block list
enabledproperty istrue - Check APP record data includes correct block list name
- Confirm query format matches DNSBL reverse notation (for IPs)
- Review block list file for correct entry format
- Check logs for parsing errors during block list load
- Use DNS query logging to verify query name extraction
TXT Records Not Returned
Symptoms: A record queries succeed, but TXT queries return NODATA
Resolution:
- Verify
responseTXTis configured indnsApp.configor block list file - Check that TXT queries target the same name as successful A queries
- Confirm entry-specific TXT response exists (if A response is entry-specific)
- Review placeholder syntax (
{ip}or{domain})
IPv6 Queries Not Working
Symptoms: IPv6 address queries return NXDOMAIN; IPv4 queries work correctly
Resolution:
- Verify query name contains exactly 32 hex nibbles in reversed order
- Check block list file contains IPv6 addresses or networks
- Confirm network notation is correct (e.g.,
2001:db8::/64) - Test with standard IPv6 localhost:
::FFFF:7F00:2(included as test entry)
Domain Matching Not Working for Subdomains
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:
- Add parent domain to block list if subdomain blocking is desired
- Verify domain in block list file is lowercase
- Check domain format is valid per DNS specifications
File: Apps/DnsRebindingProtectionApp/README.md
DNS Rebinding Protection App
Summary
A DNS App for Technitium DNS Server that protects against DNS rebinding attacks by filtering private IP addresses from DNS responses for non-local domain names.
Integration / extension points
- Implements:
IDnsApplication,IDnsPostProcessor - Runs as: a post-processor (operates on DNS responses after core resolution).
Overview
This application extends Technitium DNS Server by implementing IDnsPostProcessor to analyze DNS query responses before they are returned to clients. The app prevents DNS rebinding attacks by:
- Filtering private IP addresses from A and AAAA records for public domain names
- Allowing private IP addresses only for explicitly configured private domains
- Supporting IPv4 and IPv6 private network ranges per RFC 1918 and RFC 4193
- Bypassing protection for trusted client networks when needed
- Preserving authoritative responses to avoid interfering with locally hosted zones
This protection is critical for environments where clients access both internal and external resources, preventing malicious websites from accessing internal network services.
โ ๏ธ Important Warning: Impact on Legitimate Private IP Responses
This app will remove private IP addresses from DNS responses for any domain name not explicitly listed in the privateDomains configuration.
Processing behavior:
- If a public DNS query returns private IP addresses (e.g.,
example.comโ192.168.1.1), those records will be removed from the response - Only domains listed in
privateDomainsare permitted to resolve to private IP addresses - Authoritative responses from local zones are never filtered, as rebinding is considered intentional in this context
Configuration options:
- Option A: Add all legitimate internal domain names to the
privateDomainsarray - Option B: Disable the app entirely if private IP responses are required for domains you cannot enumerate
- Option C: Add trusted client networks to
bypassNetworksto exclude them from protection
Processing order:
The app processes responses after the DNS server completes resolution but before sending the response to the client. Filtering applies only to non-authoritative answers.
Installation
Open the Technitium DNS Server web console
Navigate to Apps section
Click App Store and find the DNS Rebinding Protection App to install
Configure the app by clicking on the Config button
Configuration
The application is configured through the dnsApp.config file located in the app's installation directory.
The configuration uses a JSON structure with four root-level properties that control protection behavior, network definitions, and domain exemptions.
Root Configuration Options
| Property | Type | Default | Description |
|---|---|---|---|
enableProtection |
Boolean | true |
Master switch to enable or disable DNS rebinding protection globally |
bypassNetworks |
Array of Strings | [] |
List of CIDR network ranges for client IP addresses that should bypass protection entirely |
privateNetworks |
Array of Strings | See below | List of CIDR network ranges considered private; responses containing these IPs will be filtered |
privateDomains |
Array of Strings | ["home.arpa"] |
List of domain names permitted to resolve to private IP addresses without filtering |
Private Networks Configuration
The privateNetworks array defines which IP address ranges are considered private and subject to rebinding protection.
Default configuration includes all RFC-defined private ranges:
"privateNetworks": [
"10.0.0.0/8",
"127.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16",
"169.254.0.0/16",
"fc00::/7",
"fe80::/10"
]Purpose: Any DNS response containing IP addresses within these ranges will be filtered unless the domain is listed in privateDomains or the client is in bypassNetworks.
Use case: Organizations may customize this list to include additional private address space (e.g., Carrier-Grade NAT 100.64.0.0/10) or remove ranges not used in their environment.
Private Domains Configuration
The privateDomains array specifies domain names that are exempt from filtering and may legitimately resolve to private IP addresses.
Format conventions:
- Domain names are case-insensitive
- Parent zone matching is supported (e.g.,
internal.localalso permitsserver.internal.local) - Do not include wildcards; subdomain matching is automatic
Example:
"privateDomains": [
"home.arpa",
"internal.local",
"corp.example.com"
]Bypass Networks Configuration
The bypassNetworks array defines client IP ranges that completely bypass rebinding protection.
Purpose: Trusted networks (e.g., administrative subnets) can receive unfiltered DNS responses.
Use case: Internal management networks or developer workstations requiring access to split-horizon DNS configurations.
Example:
"bypassNetworks": [
"10.50.0.0/24",
"192.168.100.0/24"
]Example Configuration
{
"enableProtection": true,
"bypassNetworks": [
"10.50.0.0/24"
],
"privateNetworks": [
"10.0.0.0/8",
"127.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16",
"169.254.0.0/16",
"fc00::/7",
"fe80::/10"
],
"privateDomains": [
"home.arpa",
"internal.local",
"corp.example.com",
"lab.local"
]
}This configuration:
- Enables protection globally
- Exempts clients in
10.50.0.0/24from all filtering - Filters all standard RFC 1918/4193 private IP addresses
- Permits private IPs for
*.home.arpa,*.internal.local,*.corp.example.com, and*.lab.local
Supported Network Address Formats
The app supports standard CIDR notation for both IPv4 and IPv6 networks:
IPv4 CIDR notation:
192.168.1.0/24
10.0.0.0/8IPv6 CIDR notation:
fc00::/7
fe80::/10
2001:db8::/32Single host addresses:
192.168.1.1/32
::1/128How Rebinding Protection Works
The app applies the following processing pipeline to each DNS response:
Bypass check: If
enableProtectionisfalseor the response has theAuthoritativeAnswerflag set, return the response unmodifiedClient network check: Compare the client IP address against each entry in
bypassNetworks; if matched, return the response unmodifiedRecord inspection: For each A or AAAA record in the answer section:
- Extract the domain name and IP address
- Check if the domain matches any entry in
privateDomains(including parent zones) - If the domain is private, skip to the next record
- If the domain is public, check if the IP address falls within any
privateNetworksrange - If the IP is private, mark the record for removal
Response modification: If any records were marked for removal, create a new response with only the allowed records
Client delivery: Return either the original response (if no rebinding detected) or the filtered response
Use Cases
Enterprise split-horizon DNS deployment: Allow internal domain names like intranet.corp.local to resolve to 10.x.x.x addresses while blocking external domains from returning private IPs.
ISP customer protection: Prevent DNS rebinding attacks against residential gateway devices (typically at 192.168.x.x) by filtering private IP responses for all public domain queries.
Home network security: Protect IoT devices and home servers from cross-site request forgery attacks leveraging DNS rebinding against 192.168.1.x addresses.
Development environment isolation: Use bypassNetworks to allow developer machines unrestricted DNS access while protecting production client networks.
Multi-site organization: Configure different privateDomains lists for each site's internal naming conventions (e.g., site1.internal, site2.internal).
IPv6 dual-stack protection: Prevent rebinding attacks targeting unique local addresses (fc00::/7) and link-local addresses (fe80::/10) in IPv6-enabled networks.
Troubleshooting
Internal domain names not resolving
Symptoms: Queries for internal domain names return empty responses or SERVFAIL.
Diagnostic steps:
- Check the DNS server logs for rebinding protection activity
- Verify the domain name is listed in
privateDomainsconfiguration - Confirm parent zone matching is correct (e.g.,
example.localpermitshost.example.local)
Resolution: Add the affected domain to the privateDomains array in dnsApp.config.
Protection not activating for public domains
Symptoms: Public domain names are resolving to private IP addresses without filtering.
Diagnostic steps:
- Verify
enableProtectionis set totrue - Check if the client IP is listed in
bypassNetworks - Confirm the DNS response does not have the
AuthoritativeAnswerflag set - Verify the IP address is included in
privateNetworks
Resolution: Review the configuration for unintended bypass rules or missing private network definitions.
Legitimate private IP responses being filtered
Symptoms: Split-horizon DNS or internal services are inaccessible due to filtered responses.
Diagnostic steps:
- Identify the affected domain names
- Check if the domains are listed in
privateDomains - Verify parent zone matching is functioning
Resolution: Add the affected domains to privateDomains or add the client network to bypassNetworks.
Configuration changes not taking effect
Symptoms: Modifications to dnsApp.config do not change app behavior.
Diagnostic steps:
- Verify the
dnsApp.configfile is in the correct app directory - Check JSON syntax validity using a JSON validator
- Review DNS server logs for configuration parsing errors
Resolution: Reload the app through the web console by saving its config again.
File: Apps/DropRequestsApp/README.md
Drop Requests App
A DNS App for Technitium DNS Server that drops incoming DNS requests based on network source addresses and DNS question patterns.
This application extends the core DNS Server by intercepting requests at the entry point and applying configurable filtering rules before queries reach the resolution pipeline. It provides administrators with granular control over which DNS queries are processed, enabling network segmentation, abuse mitigation, and security enforcement.
Overview
The Drop Requests App provides pre-resolution request filtering for Technitium DNS Server, enabling administrators to:
- Block requests from specific networks using CIDR notation
- Allow requests only from trusted networks (allowlist mode)
- Drop malformed or invalid DNS packets to reduce parser load
- Filter DNS questions by name and record type to prevent abuse
- Implement zone-level blocking to drop all queries for a domain and its subdomains
This application is designed for system administrators, ISPs, and security-conscious organizations requiring traffic shaping, DDoS mitigation, or network policy enforcement at the DNS layer.
Installation
Open the Technitium DNS Server web console
Navigate to Apps section
Click App Store and find the Drop Requests App to install
Configure the app by clicking on the Config button
Configuration
The Drop Requests App is configured using the dnsApp.config file located in the application's installation directory. This file uses JSON format and supports network-based filtering, question-based filtering, and malformed packet detection.
All configuration options are documented below.
Root Configuration Options
| Property | Type | Default | Description |
|---|---|---|---|
enableBlocking |
boolean | true |
Master switch to enable or disable all blocking functionality. When set to false, all requests are allowed regardless of other rules. |
dropMalformedRequests |
boolean | false |
Silently drops DNS requests that fail to parse correctly. Useful for mitigating parser-based attacks or reducing log noise from malformed packets. |
allowedNetworks |
array of strings | [] |
List of network addresses (IP or CIDR) from which requests are always allowed. If specified, requests from networks not in this list are evaluated against blocked networks and questions. Empty array disables allowlist mode. |
blockedNetworks |
array of strings | [] |
List of network addresses (IP or CIDR) from which requests are always dropped. Processed after allowedNetworks. |
blockedQuestions |
array of objects | [] |
List of DNS question patterns to block. Each object defines name, type, and zone-blocking behavior. See Blocked Questions Configuration. |
Blocked Questions Configuration
Each entry in the blockedQuestions array is an object with the following properties:
| Property | Type | Required | Description |
|---|---|---|---|
name |
string | No | The fully qualified domain name (FQDN) to match. Trailing dot is automatically trimmed. If omitted, matches any domain. |
blockZone |
boolean | No | When true, blocks the specified name and all subdomains. When false, only exact matches are blocked. Default: false. Requires name to be specified. |
type |
string | No | The DNS record type to block (e.g., A, AAAA, ANY, RRSIG). Case-insensitive. If omitted, matches any record type. Must be a valid DNS RR type. |
Matching Behavior:
- If only
nameis specified: blocks queries for that exact domain, any record type - If only
typeis specified: blocks queries for that record type, any domain - If both
nameandtypeare specified: blocks queries matching both conditions - If
blockZoneistrue: blocks the domain and all subdomains matching the type filter
Example Blocked Question (Zone-Level Blocking):
{
"name": "malicious.com",
"blockZone": true
}This blocks malicious.com, www.malicious.com, api.subdomain.malicious.com, and all other subdomains, for all record types.
Example Blocked Question (Type-Only Blocking):
{
"type": "ANY"
}This blocks all ANY queries regardless of domain name.
Example Blocked Question (Exact Domain and Type):
{
"name": "pizzaseo.com",
"type": "RRSIG"
}This blocks only RRSIG queries for pizzaseo.com (exact match).
Network Address Formats
Network addresses in allowedNetworks and blockedNetworks support the following formats:
- Single IPv4 Address:
192.168.1.100 - Single IPv6 Address:
2001:db8::1or::1 - IPv4 CIDR Notation:
10.0.0.0/8,192.168.0.0/16 - IPv6 CIDR Notation:
fe80::/10,2001:db8::/32
Example Network List:
"allowedNetworks": [
"127.0.0.1",
"::1",
"10.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16",
"2001:db8::/32"
]Example Configuration
{
"enableBlocking": true,
"dropMalformedRequests": false,
"allowedNetworks": [
"127.0.0.1",
"::1",
"10.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16"
],
"blockedNetworks": [
"203.0.113.0/24",
"198.51.100.0/24"
],
"blockedQuestions": [
{
"name": "example.com",
"blockZone": true
},
{
"type": "ANY"
},
{
"name": "pizzaseo.com",
"type": "RRSIG"
},
{
"name": "sl",
"type": "ANY"
},
{
"name": "a.a.a.ooooops.space",
"type": "A"
}
]
}How Request Filtering Works
The Drop Requests App evaluates each incoming DNS request through the following pipeline:
Blocking Check: If
enableBlockingisfalse, allow the request immediately.Malformed Packet Check: If
dropMalformedRequestsistrueand the request contains a parsing exception, drop the request silently.Allowlist Evaluation: If
allowedNetworksis configured, check if the source IP address matches any allowed network. If matched, allow the request. IfallowedNetworksis empty, skip this step.Blocklist Evaluation: Check if the source IP address matches any network in
blockedNetworks. If matched, drop the request silently.Question Count Validation: If the request does not contain exactly one DNS question, drop the request silently.
Question Pattern Matching: Evaluate the DNS question against all entries in
blockedQuestions. If any entry matches, drop the request silently.Allow by Default: If no blocking rule matched, allow the request to proceed to the DNS resolution pipeline.
Important: The allowlist (allowedNetworks) takes precedence over the blocklist (blockedNetworks). If a network is in both lists, requests from that network are allowed.
Use Cases
- Restrict DNS Server to Private Networks: Configure
allowedNetworkswith RFC 1918 private address ranges to ensure only internal hosts can query the DNS server, preventing open resolver abuse. - Mitigate DNS Amplification Attacks: Block
ANYrecord queries using a type-based blocked question to reduce amplification attack surface. - Block Known Malicious Domains at Query Time: Use zone-level blocking to prevent any queries for known malicious domains and their subdomains, reducing the attack surface before resolution occurs.
- Enforce Regional or Organizational Network Policies: Block specific external networks from querying the DNS server using
blockedNetworks, useful for geofencing or compliance requirements. - Reduce Log Noise from Malformed Packets: Enable
dropMalformedRequeststo silently discard invalid DNS packets, reducing parser overhead and log volume during DDoS conditions. - Prevent Specific DNSSEC Query Abuse: Block
RRSIGor other DNSSEC-related queries for domains known to generate excessive traffic or abuse DNSSEC validation mechanisms.
Troubleshooting
Requests Are Not Being Blocked
Symptom: DNS queries that should match blocking rules are being resolved normally.
Diagnostic Steps:
Verify
enableBlockingis set totrueindnsApp.configCheck the DNS Server App Logs for any configuration parsing errors
Confirm the source IP address of the request is not in
allowedNetworks(allowlist overrides all blocks)Verify CIDR notation is correct (e.g.,
/24not/255.255.255.0)For question-based blocking, confirm the domain name matches the
namefield exactly (case-insensitive), or thatblockZoneis enabled for subdomain blockingReload the app through the web console by saving its config again.
Legitimate Requests Are Being Dropped
Symptom: Valid DNS queries from authorized clients are being silently dropped.
Diagnostic Steps:
Check if the client's IP address is included in
allowedNetworkswhen using allowlist modeIf
blockedNetworksis configured, verify the client's IP is not within a blocked CIDR rangeReview
blockedQuestionsfor overly broad patterns (e.g., blocking allArecords or usingblockZoneon a common TLD)If
dropMalformedRequestsis enabled, verify the client is sending well-formed DNS packets (usetcpdumpor Wireshark to inspect traffic)Temporarily set
enableBlockingtofalseto confirm the issue is related to this app
Malformed Requests Are Not Being Dropped
Symptom: Invalid DNS packets are still reaching the resolver or appearing in logs.
Diagnostic Steps:
Verify
dropMalformedRequestsis set totrueindnsApp.configConfirm the packets are actually malformed by checking for parsing exceptions in the DNS Server logs
Reload the app through the web console by saving its config again.
Some malformed packets may still be logged before being dropped; check the action taken in the logs (
DropSilently)
Zone Blocking Is Not Matching Subdomains
Symptom: Queries for subdomains are not being blocked when using blockZone: true.
Diagnostic Steps:
Verify the
namefield does not include a trailing dot in the configurationConfirm
blockZoneis set totruefor the ruleCheck the DNS question name format in the logs to ensure it matches the expected FQDN structure
Test with an exact domain match first (without
blockZone) to confirm basic name matching is working
Example Command to Test:
dig @<dns-server-ip> subdomain.blocked-domain.comExpected behavior: Request is dropped silently with no response.