Apps/DropRequestsApp/README.md
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.
The Drop Requests App provides pre-resolution request filtering for Technitium DNS Server, enabling administrators to:
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.
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
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.
| 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. |
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:
name is specified: blocks queries for that exact domain, any record typetype is specified: blocks queries for that record type, any domainname and type are specified: blocks queries matching both conditionsblockZone is true: blocks the domain and all subdomains matching the type filterExample 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 addresses in allowedNetworks and blockedNetworks support the following formats:
192.168.1.1002001:db8::1 or ::110.0.0.0/8, 192.168.0.0/16fe80::/10, 2001:db8::/32Example 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"
]
{
"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"
}
]
}
The Drop Requests App evaluates each incoming DNS request through the following pipeline:
Blocking Check: If enableBlocking is false, allow the request immediately.
Malformed Packet Check: If dropMalformedRequests is true and the request contains a parsing exception, drop the request silently.
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.
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.
allowedNetworks with RFC 1918 private address ranges to ensure only internal hosts can query the DNS server, preventing open resolver abuse.ANY record queries using a type-based blocked question to reduce amplification attack surface.blockedNetworks, useful for geofencing or compliance requirements.dropMalformedRequests to silently discard invalid DNS packets, reducing parser overhead and log volume during DDoS conditions.RRSIG or other DNSSEC-related queries for domains known to generate excessive traffic or abuse DNSSEC validation mechanisms.Symptom: DNS queries that should match blocking rules are being resolved normally.
Diagnostic Steps:
Verify enableBlocking is set to true in dnsApp.config
Check 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., /24 not /255.255.255.0)
For question-based blocking, confirm the domain name matches the name field exactly (case-insensitive), or that blockZone is enabled for subdomain blocking
Reload the app through the web console by saving its config again.
Symptom: Valid DNS queries from authorized clients are being silently dropped.
Diagnostic Steps:
Check if the client's IP address is included in allowedNetworks when using allowlist mode
If blockedNetworks is configured, verify the client's IP is not within a blocked CIDR range
Review blockedQuestions for overly broad patterns (e.g., blocking all A records or using blockZone on a common TLD)
If dropMalformedRequests is enabled, verify the client is sending well-formed DNS packets (use tcpdump or Wireshark to inspect traffic)
Temporarily set enableBlocking to false to confirm the issue is related to this app
Symptom: Invalid DNS packets are still reaching the resolver or appearing in logs.
Diagnostic Steps:
Verify dropMalformedRequests is set to true in dnsApp.config
Confirm 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)
Symptom: Queries for subdomains are not being blocked when using blockZone: true.
Diagnostic Steps:
Verify the name field does not include a trailing dot in the configuration
Confirm blockZone is set to true for the rule
Check 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.com
Expected behavior: Request is dropped silently with no response.