DnsServer Documentation

C# cross-platform & dhcp-server repository by @TechnitiumSoftware. Docker Compose & container deployment with 8.3k stars.

RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy DnsServer on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name dnsserver -p 5380:5380 --restart always docker.io/technitium/dns-server:latest
Configured Services & Ports
โš™๏ธ dns-server
image: docker.io/technitium/dns-server:latest
๐Ÿ”Œ Ports: 5380:5380/tcp, 53:53/udp, 53:53/tcp
docker-compose.yml
yaml (docker-compose.yml)
services:
  dns-server:
    container_name: dns-server
    hostname: dns-server
    image: docker.io/technitium/dns-server:latest
    # For DHCP deployments, use "host" network mode and remove all the port mappings, including the ports array by commenting them
    # network_mode: "host"
    ports:
      - "5380:5380/tcp" #DNS web console (HTTP)
      # - "53443:53443/tcp" #DNS web console (HTTPS)
      - "53:53/udp" #DNS service
      - "53:53/tcp" #DNS service
      # - "853:853/udp" #DNS-over-QUIC service
      # - "853:853/tcp" #DNS-over-TLS service
      # - "443:443/udp" #DNS-over-HTTPS service (HTTP/3)
      # - "443:443/tcp" #DNS-over-HTTPS service (HTTP/1.1, HTTP/2)
      # - "80:80/tcp" #DNS-over-HTTP service (use with reverse proxy or certbot certificate renewal)
      # - "8053:8053/tcp" #DNS-over-HTTP service (use with reverse proxy)
      # - "67:67/udp" #DHCP service
    environment:
      - DNS_SERVER_DOMAIN=dns-server #The primary fully qualified domain name used by this DNS Server to identify itself.
      # - DNS_SERVER_ADMIN_PASSWORD=password #DNS web console admin user password.
      # - DNS_SERVER_ADMIN_PASSWORD_FILE=password.txt #The path to a file that contains a plain text password for the DNS web console admin user.
      # - DNS_SERVER_PREFER_IPV6=false #DNS Server will use IPv6 for querying whenever possible with this option enabled.
      # - DNS_SERVER_WEB_SERVICE_LOCAL_ADDRESSES=172.17.0.1,127.0.0.1 #Comma separated list of network interface IP addresses that you want the web service to listen on for requests. The "172.17.0.1" address is the built-in Docker bridge. The "[::]" is the default value if not specified. Note! This must be used only with "host" network mode.
      # - DNS_SERVER_WEB_SERVICE_HTTP_PORT=5380 #The TCP port number for the DNS web console over HTTP protocol.
      # - DNS_SERVER_WEB_SERVICE_HTTPS_PORT=53443 #The TCP port number for the DNS web console over HTTPS protocol.
      # - DNS_SERVER_WEB_SERVICE_ENABLE_HTTPS=false #Enables HTTPS for the DNS web console.
      # - DNS_SERVER_WEB_SERVICE_USE_SELF_SIGNED_CERT=false #Enables self signed TLS certificate for the DNS web console.
      # - DNS_SERVER_WEB_SERVICE_TLS_CERTIFICATE_PATH=/etc/dns/tls/cert.pfx #The file path to the TLS certificate for the DNS web console.
      # - DNS_SERVER_WEB_SERVICE_TLS_CERTIFICATE_PASSWORD=password #The password for the TLS certificate for the DNS web console.
      # - DNS_SERVER_WEB_SERVICE_HTTP_TO_TLS_REDIRECT=false #Enables HTTP to HTTPS redirection for the DNS web console.
      # - DNS_SERVER_OPTIONAL_PROTOCOL_DNS_OVER_HTTP=false #Enables DNS server optional protocol DNS-over-HTTP on TCP port 8053 to be used with a TLS terminating reverse proxy like nginx.
      # - DNS_SERVER_RECURSION=AllowOnlyForPrivateNetworks #Recursion options: Allow, Deny, AllowOnlyForPrivateNetworks, UseSpecifiedNetworkACL.
      # - DNS_SERVER_RECURSION_NETWORK_ACL=192.168.10.0/24, !192.168.10.2 #Comma separated list of IP addresses or network addresses to allow access. Add ! character at the start to deny access, e.g. !192.168.10.0/24 will deny entire subnet. The ACL is processed in the same order its listed. If no networks match, the default policy is to deny all except loopback. Valid only for `UseSpecifiedNetworkACL` recursion option.
      # - DNS_SERVER_RECURSION_DENIED_NETWORKS=1.1.1.0/24 #Comma separated list of IP addresses or network addresses to deny recursion. Valid only for `UseSpecifiedNetworkACL` recursion option. This option is obsolete and DNS_SERVER_RECURSION_NETWORK_ACL should be used instead.
      # - DNS_SERVER_RECURSION_ALLOWED_NETWORKS=127.0.0.1, 192.168.1.0/24 #Comma separated list of IP addresses or network addresses to allow recursion. Valid only for `UseSpecifiedNetworkACL` recursion option.  This option is obsolete and DNS_SERVER_RECURSION_NETWORK_ACL should be used instead.
      # - DNS_SERVER_ENABLE_BLOCKING=false #Sets the DNS server to block domain names using Blocked Zone and Block List Zone.
      # - DNS_SERVER_ALLOW_TXT_BLOCKING_REPORT=false #Specifies if the DNS Server should respond with TXT records containing a blocked domain report for TXT type requests.
      # - DNS_SERVER_BLOCK_LIST_URLS= #A comma separated list of block list URLs.
      # - DNS_SERVER_FORWARDERS=1.1.1.1, 8.8.8.8 #Comma separated list of forwarder addresses.
      # - DNS_SERVER_FORWARDER_PROTOCOL=Tcp #Forwarder protocol options: Udp, Tcp, Tls, Https, Quic.
      # - DNS_SERVER_LOG_USING_LOCAL_TIME=true #Enable this option to use local time instead of UTC for logging.
      - DNS_SERVER_LOG_FOLDER_PATH=/var/log/technitium/dns #The folder path on the server where the log files should be saved.
      # - DNS_SERVER_LOG_MAX_LOG_FILE_DAYS=365 #Max number of days to keep the log files. Log files older than the specified number of days will be deleted automatically. Set 0 to disable auto delete.
      # - DNS_SERVER_STATS_ENABLE_IN_MEMORY_STATS=false #This option will enable in-memory stats and only Last Hour data will be available on Dashboard. No stats data will be stored on disk.
      # - DNS_SERVER_STATS_MAX_STAT_FILE_DAYS=365 #Max number of days to keep the dashboard stats. Stat files older than the specified number of days will be deleted automatically. Set 0 to disable auto delete.
    volumes:
      - config:/etc/dns
      - logs:/var/log/technitium/dns
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://127.0.0.1:5380/api/dnsClient/healthCheck | grep '\"status\":\"ok\"'"]
      #test: ["CMD", "dig", "+short", "+norecurse", "+retry=0", "@127.0.0.1", "localhost"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s
    restart: unless-stopped
    sysctls:
      - net.ipv4.ip_local_port_range=1024 65535 #remove when using "host" network mode

volumes:
    config:
    logs:

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.

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

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.

Make contribution to Technitium and help making new software, updates, and features possible.

Donate Now!

Blog Posts


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

json
{
  "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

  1. The app selects a client group based on networkGroupMap.
  2. It checks whether forwarding is enabled for the selected group.
  3. It matches the queried domain against the group's forwarding rules.
  4. 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 domains entries.

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

  1. Open Technitium DNS Server web console
  2. Navigate to Apps section
  3. Click App Store and find the Advanced Blocking App to install
  4. 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.

json
"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.

json
"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:

json
"blockListUrls": [
  "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts"
]

Object format with custom options:

json
"blockListUrls": [
  {
    "url": "https://example.com/blocklist.txt",
    "blockAsNxDomain":  false,
    "blockingAddresses": ["192.168.10.2"]
  }
]

Example Configuration

text
/* Detailed source-code truncated for AI context efficiency. */

Supported Block List Formats

Domain Block Lists

Standard hosts-file format or plain domain lists:

syslog
# Comment line
0.0.0.0 ads.example.com
127.0.0.1 tracking.example.com
malware.example.com

Regex Block Lists

One regex pattern per line:

regex
# Block all subdomains starting with "ads"
^ads\. 
# Block tracking domains
.*tracking.*\.com$

AdBlock Lists

Supports a subset of AdBlock syntax:

regex
! Comment
||ads.example.com^
||tracking.example.com^$all
@@||safe.example.com^

How Blocking Works

  1. 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
  2. Allow Check: If the domain matches any allow list (static, URL-based, regex, or AdBlock whitelist), the request is NOT blocked.

  3. Block Check: If the domain matches any block list, the app returns:

    • NXDOMAIN if blockAsNxDomain is true
    • Configured blockingAddresses for A/AAAA queries
    • NO DATA response for other query types
  4. Blocking Report: When allowTxtBlockingReport is 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

  1. Parental Controls: Create a "kids" group with stricter blocking for children's devices
  2. Guest Network: Apply different policies to guest WiFi subnet
  3. IoT Isolation: Block telemetry for IoT devices on a specific VLAN
  4. Multi-tenant DNS: Different blocking policies for different clients sharing the same DNS server
  5. 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

  1. Verify the client IP maps to the correct group
  2. Check if the domain is in an allow list
  3. Confirm enableBlocking is true at both root and group level
  4. 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:

bash
dig TXT blocked-domain.com @your-dns-server

File: 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

  1. Open the Technitium DNS Server web console.

  2. Navigate to Apps section.

  3. Click App Store and find the Auto PTR app to install.

  4. 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 prefix and appends suffix

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 prefix and appends suffix

Example Configuration

Basic IPv4 Example

json
{
  "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

json
{
  "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

json
{
  "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:

  1. Query Reception: The app receives a DNS query for a name within the reverse DNS zone where the APP record is configured.

  2. 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).

  3. 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).
  4. Domain Name Generation: The IP address is formatted into a domain name using the configured prefix, ipSeparator, and suffix values.

  5. Response Construction: A DNS response is built containing a PTR record with the generated domain name and the APP record's configured TTL.

  6. Response Transmission: The authoritative response is returned to the client with the AA (Authoritative Answer) flag set.

Use Cases

  1. Automated reverse DNS for DHCP ranges: Generate consistent PTR records for dynamically assigned IP addresses without manual updates.
  2. 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).
  3. Internal network documentation: Create self-documenting reverse DNS where the PTR record contains the IP address in a readable format.
  4. IPv6 deployment support: Simplify reverse DNS management for large IPv6 allocations where manual PTR record creation is impractical.
  5. Multi-tenant hosting environments: Provide automatic reverse DNS for hosting infrastructure using tenant identifiers in the prefix.
  6. 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:

  1. Verify the APP record is configured in the correct reverse DNS zone (e.g., 168.192.in-addr.arpa for 192.168.0.0/16).
  2. Ensure the APP record name covers the IP range being queried (e.g., 0.168.192.in-addr.arpa for 192.168.0.0/24).
  3. Check that the AutoPtrApp is installed and enabled in the DNS Server Apps section.
  4. Review DNS query logs to confirm the query is reaching the zone.

Malformed PTR Response

Symptoms: PTR responses contain unexpected characters or formatting.

Resolution:

  1. Verify JSON configuration syntax in the APP record data field.
  2. Check ipSeparator value for unintended characters or escape sequences.
  3. Ensure prefix and suffix values do not contain invalid DNS label characters.
  4. 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:

  1. Verify the APP record is in the correct ip6.arpa zone (e.g., 8.b.d.0.1.0.0.2.ip6.arpa).
  2. Confirm the query is formatted as a valid IPv6 reverse DNS name.
  3. 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

json
[
  {
    "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

  1. The app starts one or more embedded web servers.
  2. If serveBlockPageFromWebServerRoot is false, it generates a page from the title/heading/message values.
  3. If serveBlockPageFromWebServerRoot is true, it serves static content from webServerRootPath.
  4. 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 webServerLocalAddresses match 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 NOERROR or NXDOMAIN codes
  • 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

  1. Open the Technitium DNS Server web console
  2. Navigate to Apps section
  3. Click App Store and find the Default Records App to install
  4. 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 .net zones)
  • Global wildcard ("*") applies to all zones not matched by more specific rules
  • Multiple sets can be assigned to a single zone

JSON Example:

json
"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:

json
"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:

bind
@ 3600 IN A 192.0.2.1
www 7200 IN CNAME @

Advanced Example:

bind
@ 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::10

Formatting 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, defaultTtl is applied
  • TXT records must be enclosed in double quotes

Example Configuration

json
{
  "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:

bind
@ 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.

  1. Response Interception: The app receives the DNS response generated by the server core
  2. Eligibility Validation: Processing occurs only if:
    • enableDefaultRecords is set to true
    • The response has the Authoritative Answer flag set
    • The operation code is StandardQuery
    • The response code is NOERROR or NXDOMAIN
  3. Zone Matching: The queried domain name is matched against zoneSetMap using hierarchical pattern matching
  4. Set Selection: Mapped set names are retrieved; only enabled sets are processed
  5. Record Parsing: Records from selected sets are parsed using the zone file parser with the resolved zone as origin
  6. 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)
  7. Response Construction: Matching records are appended to the answer section, and a new response datagram is returned
  8. 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

  1. Centralized Email Security Policies: Apply SPF, DKIM, and DMARC records to all zones under management without manual configuration per zone.
  2. Branding and Redirect Standardization: Automatically create www CNAME records pointing to the zone apex across all commercial domains.
  3. Testing and Staging Environments: Inject test-specific DNS records into staging zones without modifying production zone files.
  4. Multi-Tenant Hosting Platforms: Apply provider-specific MX, NS, or CAA records to all customer zones using wildcard mappings.
  5. Compliance and Audit Requirements: Ensure all zones contain mandatory TXT records for domain verification or security policies.
  6. 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:

  1. Verify enableDefaultRecords is set to true in dnsApp.config
  2. Confirm the queried zone matches a pattern in zoneSetMap
  3. Check that the referenced set exists and has enable: true
  4. Ensure the DNS server is returning an authoritative answer for the zone
  5. Verify the response code is NOERROR or NXDOMAIN

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:

  1. Review the zoneSetMap for overlapping patterns
  2. Verify wildcard patterns are correctly formatted (e.g., "*.com" not ".com")
  3. Test zone matching logic by querying domains and checking applied sets
  4. Ensure zone names in zoneSetMap are 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:

  1. Validate record syntax against RFC 1035 zone file format
  2. Check for missing trailing dots on FQDNs
  3. Verify TXT record content is enclosed in double quotes
  4. Ensure TTL values are positive integers
  5. Confirm record class is specified (usually IN)

Example Error:

yaml
Invalid zone file entry: missing TTL or class

Resolution:

Correct the record format:

json
"records": [
  "@ IN A 192.0.2.1"  // Missing TTL - uses defaultTtl
]

Should be:

json
"records": [
  "@ 3600 IN A 192.0.2.1"
]

Wildcard Zone Matching Not Resolving

Diagnostic Steps:

  1. Verify the DNS server has an SOA record for the queried zone
  2. Check that the zone is configured as authoritative
  3. Test SOA query independently: dig @server example.com SOA
  4. 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: false initially, 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

  1. Open the Technitium DNS Server web console

  2. Navigate to Apps section

  3. Click App Store and find the DNS64 App to install

  4. 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:

json
"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
  • null to 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:

json
"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::/96 prefix (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:

json
"excludedIpv6": [
  "::ffff:0:0/96",
  "2001:db8:exclude::/48"
]

Example Configuration

json
{
  "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)

  1. Request Validation: App checks if DNS64 is enabled globally and DNSSEC is not requested
  2. Response Analysis: App evaluates recursive resolver response for AAAA query
  3. Group Selection: Client source IP is matched against networkGroupMap using longest prefix match
  4. Exclusion Check: If AAAA records exist and fall outside excludedIpv6 ranges, no synthesis occurs
  5. A Record Query: If no valid AAAA records exist, app performs internal A record query
  6. Prefix Mapping: Each A record is matched against dns64PrefixMap using longest prefix match
  7. AAAA Synthesis: IPv4 addresses are embedded in IPv6 prefix to generate synthesized AAAA records
  8. Response Construction: Synthesized AAAA records are added to response with TTL capped by SOA minimum

PTR Query Processing (Authoritative Handler)

  1. Request Validation: App checks if query is PTR for .ip6.arpa domain
  2. Group Selection: Client source IP is matched against networkGroupMap
  3. Prefix Match: Reverse IPv6 address is matched against configured dns64PrefixMap values
  4. IPv4 Extraction: IPv4 address is extracted from synthesized IPv6 address
  5. CNAME Response: App returns authoritative CNAME record pointing to .in-addr.arpa domain
  6. Recursive Resolution: DNS server follows CNAME to resolve PTR from IPv4 reverse zone

Use Cases

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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:

  1. Verify enableDns64: true at both root and group level
  2. Confirm client source IP matches a network in networkGroupMap
  3. Check that target IPv4 address is not excluded via dns64PrefixMap: null mapping
  4. Verify DNSSEC is not requested by client (app bypasses DNSSEC queries)
  5. Confirm existing AAAA records are not present or are in excludedIpv6 ranges

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:

  1. Verify NAT64 gateway is operational and reachable from client network
  2. Confirm NAT64 prefix configuration matches DNS64 dns64PrefixMap prefixes
  3. Test NAT64 connectivity using ping6 to known IPv4 address: ping6 64:ff9b::8.8.8.8
  4. Check routing for DNS64 prefix range to NAT64 gateway
  5. 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:

json
"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:

  1. Verify synthesized IPv6 address falls within configured DNS64 prefix
  2. Confirm corresponding IPv4 reverse zone (.in-addr.arpa) exists and is resolvable
  3. Check DNS server logs for CNAME processing from .ip6.arpa to .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:

json
"dns64PrefixMap": {
  "0.0.0.0/0": "2001:db8::/80"  // Invalid - /80 is not one of the supported prefix lengths
}

Corrected Example:

json
"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

  1. Open the Technitium DNS Server web console
  2. Navigate to Apps section
  3. Click App Store and find the DNS Block List (DNSBL) App to install
  4. 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:

text
# 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 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:

text
# 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

json
{
  "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:

json
{
  "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:

  1. Query Reception: The DNS server receives a query for a subdomain under the APP record (e.g., 2.0.0.127.dnsbl.example.com)

  2. 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)
  3. Block List Lookup: The extracted address or domain is checked against each configured block list in order

  4. 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)
  5. 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:

xml
<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):

xml
<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:

xml
<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.2 for IP, test for domain)
  • Response format: Standard A record responses in the 127.0.0.0/8 range
  • TXT record support: Optional descriptive TXT records for blocked entries
  • NXDOMAIN semantics: Unlisted entries return NXDOMAIN as specified

Use Cases

  1. Spam Prevention: Deploy email server IP reputation lists to identify and block mail from known spam sources
  2. Threat Intelligence Integration: Load IP addresses and domains from threat feeds to prevent connections to malicious infrastructure
  3. Compliance Enforcement: Implement organizational policies blocking access to specific IP ranges or domain categories
  4. Network Abuse Mitigation: Maintain dynamic block lists of IPs exhibiting abusive behavior detected by intrusion prevention systems
  5. Content Filtering: Create domain block lists for categories requiring access restrictions (parental controls, workplace policies)
  6. 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:

  1. Entry-specific response (defined in block list file)
  2. Block list default response (defined in dnsApp.config)
  3. 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:

  1. Verify the blockListFile path in dnsApp.config
  2. Check file permissions (application must have read access)
  3. Review DNS Server logs for specific error messages
  4. Ensure file uses UTF-8 encoding without BOM
  5. 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:

  1. Verify block list enabled property is true
  2. Check APP record data includes correct block list name
  3. Confirm query format matches DNSBL reverse notation (for IPs)
  4. Review block list file for correct entry format
  5. Check logs for parsing errors during block list load
  6. Use DNS query logging to verify query name extraction

TXT Records Not Returned

Symptoms: A record queries succeed, but TXT queries return NODATA

Resolution:

  1. Verify responseTXT is configured in dnsApp.config or block list file
  2. Check that TXT queries target the same name as successful A queries
  3. Confirm entry-specific TXT response exists (if A response is entry-specific)
  4. Review placeholder syntax ({ip} or {domain})

IPv6 Queries Not Working

Symptoms: IPv6 address queries return NXDOMAIN; IPv4 queries work correctly

Resolution:

  1. Verify query name contains exactly 32 hex nibbles in reversed order
  2. Check block list file contains IPv6 addresses or networks
  3. Confirm network notation is correct (e.g., 2001:db8::/64)
  4. 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:

  1. sub.example.com (exact match)
  2. example.com (parent zone)
  3. com (parent zone)

Resolution:

  1. Add parent domain to block list if subdomain blocking is desired
  2. Verify domain in block list file is lowercase
  3. 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 privateDomains are 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 privateDomains array
  • Option B: Disable the app entirely if private IP responses are required for domains you cannot enumerate
  • Option C: Add trusted client networks to bypassNetworks to 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

  1. Open the Technitium DNS Server web console

  2. Navigate to Apps section

  3. Click App Store and find the DNS Rebinding Protection App to install

  4. 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:

json
"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.local also permits server.internal.local)
  • Do not include wildcards; subdomain matching is automatic

Example:

json
"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:

json
"bypassNetworks": [
  "10.50.0.0/24",
  "192.168.100.0/24"
]

Example Configuration

json
{
  "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/24 from 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:

text
192.168.1.0/24
10.0.0.0/8

IPv6 CIDR notation:

text
fc00::/7
fe80::/10
2001:db8::/32

Single host addresses:

text
192.168.1.1/32
::1/128

How Rebinding Protection Works

The app applies the following processing pipeline to each DNS response:

  1. Bypass check: If enableProtection is false or the response has the AuthoritativeAnswer flag set, return the response unmodified

  2. Client network check: Compare the client IP address against each entry in bypassNetworks; if matched, return the response unmodified

  3. Record 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 privateNetworks range
    • If the IP is private, mark the record for removal
  4. Response modification: If any records were marked for removal, create a new response with only the allowed records

  5. 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:

  1. Check the DNS server logs for rebinding protection activity
  2. Verify the domain name is listed in privateDomains configuration
  3. Confirm parent zone matching is correct (e.g., example.local permits host.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:

  1. Verify enableProtection is set to true
  2. Check if the client IP is listed in bypassNetworks
  3. Confirm the DNS response does not have the AuthoritativeAnswer flag set
  4. 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:

  1. Identify the affected domain names
  2. Check if the domains are listed in privateDomains
  3. 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:

  1. Verify the dnsApp.config file is in the correct app directory
  2. Check JSON syntax validity using a JSON validator
  3. 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

  1. Open the Technitium DNS Server web console

  2. Navigate to Apps section

  3. Click App Store and find the Drop Requests App to install

  4. 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 name is specified: blocks queries for that exact domain, any record type
  • If only type is specified: blocks queries for that record type, any domain
  • If both name and type are specified: blocks queries matching both conditions
  • If blockZone is true: blocks the domain and all subdomains matching the type filter

Example Blocked Question (Zone-Level Blocking):

json
{
  "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):

json
{
  "type": "ANY"
}

This blocks all ANY queries regardless of domain name.

Example Blocked Question (Exact Domain and Type):

json
{
  "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::1 or ::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:

json
"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

json
{
  "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:

  1. Blocking Check: If enableBlocking is false, allow the request immediately.

  2. Malformed Packet Check: If dropMalformedRequests is true and the request contains a parsing exception, drop the request silently.

  3. Allowlist Evaluation: If allowedNetworks is configured, check if the source IP address matches any allowed network. If matched, allow the request. If allowedNetworks is empty, skip this step.

  4. Blocklist Evaluation: Check if the source IP address matches any network in blockedNetworks. If matched, drop the request silently.

  5. Question Count Validation: If the request does not contain exactly one DNS question, drop the request silently.

  6. Question Pattern Matching: Evaluate the DNS question against all entries in blockedQuestions. If any entry matches, drop the request silently.

  7. 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

  1. Restrict DNS Server to Private Networks: Configure allowedNetworks with RFC 1918 private address ranges to ensure only internal hosts can query the DNS server, preventing open resolver abuse.
  2. Mitigate DNS Amplification Attacks: Block ANY record queries using a type-based blocked question to reduce amplification attack surface.
  3. 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.
  4. Enforce Regional or Organizational Network Policies: Block specific external networks from querying the DNS server using blockedNetworks, useful for geofencing or compliance requirements.
  5. Reduce Log Noise from Malformed Packets: Enable dropMalformedRequests to silently discard invalid DNS packets, reducing parser overhead and log volume during DDoS conditions.
  6. Prevent Specific DNSSEC Query Abuse: Block RRSIG or 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:

  1. Verify enableBlocking is set to true in dnsApp.config

  2. Check the DNS Server App Logs for any configuration parsing errors

  3. Confirm the source IP address of the request is not in allowedNetworks (allowlist overrides all blocks)

  4. Verify CIDR notation is correct (e.g., /24 not /255.255.255.0)

  5. For question-based blocking, confirm the domain name matches the name field exactly (case-insensitive), or that blockZone is enabled for subdomain blocking

  6. Reload 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:

  1. Check if the client's IP address is included in allowedNetworks when using allowlist mode

  2. If blockedNetworks is configured, verify the client's IP is not within a blocked CIDR range

  3. Review blockedQuestions for overly broad patterns (e.g., blocking all A records or using blockZone on a common TLD)

  4. If dropMalformedRequests is enabled, verify the client is sending well-formed DNS packets (use tcpdump or Wireshark to inspect traffic)

  5. Temporarily set enableBlocking to false to 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:

  1. Verify dropMalformedRequests is set to true in dnsApp.config

  2. Confirm the packets are actually malformed by checking for parsing exceptions in the DNS Server logs

  3. Reload the app through the web console by saving its config again.

  4. 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:

  1. Verify the name field does not include a trailing dot in the configuration

  2. Confirm blockZone is set to true for the rule

  3. Check the DNS question name format in the logs to ensure it matches the expected FQDN structure

  4. Test with an exact domain match first (without blockZone) to confirm basic name matching is working

Example Command to Test:

bash
dig @<dns-server-ip> subdomain.blocked-domain.com

Expected behavior: Request is dropped silently with no response.