Skip to content

Commit b58de99

Browse files
authored
Merge branch 'master' into feat/add-dns-cookie-support
2 parents d7f2b07 + aa9044d commit b58de99

216 files changed

Lines changed: 16241 additions & 5394 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

APIDOCS.md

Lines changed: 879 additions & 153 deletions
Large diffs are not rendered by default.

Apps/AdvancedBlockingApp/AdvancedBlockingApp.csproj

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net9.0</TargetFramework>
4+
<TargetFramework>net10.0</TargetFramework>
55
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
6-
<Version>10.0</Version>
6+
<Version>11.0</Version>
77
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
88
<Company>Technitium</Company>
99
<Product>Technitium DNS Server</Product>
@@ -39,6 +39,9 @@
3939
<None Update="dnsApp.config">
4040
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
4141
</None>
42+
<None Update="README.md">
43+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
44+
</None>
4245
</ItemGroup>
4346

4447
</Project>

Apps/AdvancedBlockingApp/App.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
Technitium DNS Server
3-
Copyright (C) 2025 Shreyas Zare (shreyas@technitium.com)
3+
Copyright (C) 2026 Shreyas Zare (shreyas@technitium.com)
44
55
This program is free software: you can redistribute it and/or modify
66
it under the terms of the GNU General Public License as published by
@@ -43,6 +43,8 @@ public sealed class App : IDnsApplication, IDnsRequestBlockingHandler
4343
{
4444
#region variables
4545

46+
readonly static JsonDocumentOptions _jsonParseOptions = new JsonDocumentOptions() { CommentHandling = JsonCommentHandling.Skip };
47+
4648
IDnsServer? _dnsServer;
4749

4850
DnsSOARecordData? _soaRecord;
@@ -341,12 +343,15 @@ private static bool IsMatchFound(Dictionary<Uri, ListZoneEntry<RegexList>> regex
341343

342344
#region public
343345

344-
public async Task InitializeAsync(IDnsServer dnsServer, string config)
346+
public async Task InitializeAsync(IDnsServer dnsServer, string? config)
345347
{
346348
_dnsServer = dnsServer;
347349

350+
if (config is null)
351+
throw new InvalidOperationException();
352+
348353
Directory.CreateDirectory(Path.Combine(_dnsServer.ApplicationFolder, "blocklists"));
349-
using JsonDocument jsonDocument = JsonDocument.Parse(config);
354+
using JsonDocument jsonDocument = JsonDocument.Parse(config, _jsonParseOptions);
350355
JsonElement jsonConfig = jsonDocument.RootElement;
351356

352357
_enableBlocking = jsonConfig.GetPropertyValue("enableBlocking", true);
@@ -1190,7 +1195,7 @@ private async Task<bool> DownloadListFileAsync()
11901195
{
11911196
HttpClientNetworkHandler handler = new HttpClientNetworkHandler();
11921197
handler.Proxy = _dnsServer.Proxy;
1193-
handler.NetworkType = _dnsServer.PreferIPv6 ? HttpClientNetworkType.PreferIPv6 : HttpClientNetworkType.Default;
1198+
handler.NetworkType = HttpClientNetworkHandler.GetNetworkType(_dnsServer.IPv6Mode);
11941199
handler.DnsClient = _dnsServer;
11951200

11961201
using (HttpClient http = new HttpClient(handler))

Apps/AdvancedBlockingApp/README.md

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
# Advanced Blocking App
2+
3+
A DNS App for [Technitium DNS Server](https://technitium.com/dns/) that provides advanced domain blocking capabilities with support for client-based group policies, multiple block list formats, and fine-grained control over blocking behavior.
4+
5+
## Overview
6+
7+
The Advanced Blocking App extends the DNS server's blocking capabilities by allowing administrators to:
8+
9+
- Create **client-based groups** with different blocking policies based on IP address, subnet, or local endpoint
10+
- Use multiple types of block lists: domain lists, regex patterns, and AdBlock-style lists
11+
- Configure custom blocking responses (NXDOMAIN or custom IP addresses)
12+
- Set up allow lists to whitelist specific domains
13+
- Map clients to groups using network addresses or DNS endpoint identifiers
14+
15+
## ⚠️ Important Warning: Overlap with Default Blocking
16+
17+
> **When this app is installed and enabled, it operates independently from the DNS server's built-in blocking feature.**
18+
>
19+
> 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.
20+
>
21+
> **You should choose one approach:**
22+
>
23+
> - **Option A:** Use the DNS server's built-in blocking (Settings > Blocking) and do NOT install this app
24+
> - **Option B:** Install this app and configure ALL your blocking rules here, ignoring the built-in blocking settings
25+
>
26+
> 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.
27+
28+
## Installation
29+
30+
1. Open Technitium DNS Server web console
31+
2. Navigate to **Apps** section
32+
3. Click **App Store** and find the Advanced Blocking App to install
33+
4. Configure the app by clicking on the **Config** button
34+
35+
## Configuration
36+
37+
The app is configured via a JSON configuration file (`dnsApp.config`). Below is a complete reference of all configuration options:
38+
39+
### Root Configuration Options
40+
41+
| Property | Type | Default | Description |
42+
| --- | --- | --- | --- |
43+
| `enableBlocking` | boolean | `true` | Master switch to enable or disable all blocking |
44+
| `blockingAnswerTtl` | integer | `30` | TTL (in seconds) for blocking responses |
45+
| `blockListUrlUpdateIntervalHours` | integer | `24` | Hours between automatic block list updates |
46+
| `blockListUrlUpdateIntervalMinutes` | integer | `0` | Additional minutes for update interval |
47+
| `localEndPointGroupMap` | object | `{}` | Maps local DNS endpoints to group names |
48+
| `networkGroupMap` | object | `{}` | Maps client networks/IPs to group names |
49+
| `groups` | array | `[]` | Array of group definitions |
50+
51+
### Local Endpoint Group Mapping
52+
53+
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.
54+
55+
```json
56+
"localEndPointGroupMap": {
57+
"127.0.0.1": "bypass",
58+
"192.168.10.2:53": "bypass",
59+
"user1.dot.example.com": "kids",
60+
"user2.doh.example.com:443": "bypass"
61+
}
62+
```
63+
64+
### Network Group Mapping
65+
66+
Maps client IP addresses or subnets to groups. More specific matches take precedence.
67+
68+
```json
69+
"networkGroupMap": {
70+
"192.168.10.20": "kids",
71+
"192.168.10.0/24": "standard",
72+
"0.0.0.0/0": "everyone",
73+
"::/0": "everyone"
74+
}
75+
```
76+
77+
### Group Configuration
78+
79+
Each group defines its own blocking policy:
80+
81+
| Property | Type | Default | Description |
82+
| --- | --- | --- | --- |
83+
| `name` | string | *required* | Unique group identifier |
84+
| `enableBlocking` | boolean | `true` | Enable blocking for this group |
85+
| `allowTxtBlockingReport` | boolean | `true` | Return blocking metadata in TXT queries and EDNS Extended DNS Error |
86+
| `blockAsNxDomain` | boolean | `false` | Return NXDOMAIN instead of custom IP for blocked domains |
87+
| `blockingAddresses` | array | `[]` | IP addresses to return for blocked A/AAAA queries |
88+
| `allowed` | array | `[]` | Domains explicitly allowed (whitelist) |
89+
| `blocked` | array | `[]` | Domains explicitly blocked |
90+
| `allowListUrls` | array | `[]` | URLs to domain allow lists |
91+
| `blockListUrls` | array | `[]` | URLs to domain block lists (string or object) |
92+
| `allowedRegex` | array | `[]` | Regex patterns for allowed domains |
93+
| `blockedRegex` | array | `[]` | Regex patterns for blocked domains |
94+
| `regexAllowListUrls` | array | `[]` | URLs to regex allow list files |
95+
| `regexBlockListUrls` | array | `[]` | URLs to regex block list files |
96+
| `adblockListUrls` | array | `[]` | URLs to AdBlock-format lists |
97+
98+
### Block List URL Formats
99+
100+
Block list URLs can be specified as simple strings or as objects with additional options:
101+
102+
**Simple format:**
103+
104+
```json
105+
"blockListUrls": [
106+
"https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts"
107+
]
108+
```
109+
110+
**Object format with custom options:**
111+
112+
```json
113+
"blockListUrls": [
114+
{
115+
"url": "https://example.com/blocklist.txt",
116+
"blockAsNxDomain": false,
117+
"blockingAddresses": ["192.168.10.2"]
118+
}
119+
]
120+
```
121+
122+
## Example Configuration
123+
124+
```json
125+
{
126+
"enableBlocking": true,
127+
"blockingAnswerTtl": 30,
128+
"blockListUrlUpdateIntervalHours": 24,
129+
"blockListUrlUpdateIntervalMinutes": 0,
130+
"localEndPointGroupMap": {
131+
"127.0.0.1": "bypass"
132+
},
133+
"networkGroupMap": {
134+
"192.168.10.0/24": "kids",
135+
"0.0.0.0/0": "everyone",
136+
"::/0": "everyone"
137+
},
138+
"groups": [
139+
{
140+
"name": "everyone",
141+
"enableBlocking": true,
142+
"allowTxtBlockingReport": true,
143+
"blockAsNxDomain": true,
144+
"blockingAddresses": ["0.0.0.0", "::"],
145+
"allowed": [],
146+
"blocked": ["example.com"],
147+
"allowListUrls": [],
148+
"blockListUrls": [
149+
"https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts"
150+
],
151+
"allowedRegex": [],
152+
"blockedRegex": ["^ads\\."],
153+
"regexAllowListUrls": [],
154+
"regexBlockListUrls": [],
155+
"adblockListUrls": []
156+
},
157+
{
158+
"name": "kids",
159+
"enableBlocking": true,
160+
"allowTxtBlockingReport": true,
161+
"blockAsNxDomain": false,
162+
"blockingAddresses": ["0.0.0.0", "::"],
163+
"allowed": [],
164+
"blocked": [],
165+
"allowListUrls": [],
166+
"blockListUrls": [
167+
{
168+
"url": "https://raw.githubusercontent.com/StevenBlack/hosts/master/alternates/social/hosts",
169+
"blockAsNxDomain": false,
170+
"blockingAddresses": ["192.168.10.2"]
171+
}
172+
],
173+
"allowedRegex": [],
174+
"blockedRegex": [],
175+
"regexAllowListUrls": [],
176+
"regexBlockListUrls": [],
177+
"adblockListUrls": []
178+
},
179+
{
180+
"name": "bypass",
181+
"enableBlocking": false,
182+
"allowTxtBlockingReport": true,
183+
"blockAsNxDomain": true,
184+
"blockingAddresses": ["0.0.0.0", "::"],
185+
"allowed": [],
186+
"blocked": [],
187+
"allowListUrls": [],
188+
"blockListUrls": [],
189+
"allowedRegex": [],
190+
"blockedRegex": [],
191+
"regexAllowListUrls": [],
192+
"regexBlockListUrls": [],
193+
"adblockListUrls": []
194+
}
195+
]
196+
}
197+
```
198+
199+
## Supported Block List Formats
200+
201+
### Domain Block Lists
202+
203+
Standard hosts-file format or plain domain lists:
204+
205+
```syslog
206+
# Comment line
207+
0.0.0.0 ads.example.com
208+
127.0.0.1 tracking.example.com
209+
malware.example.com
210+
```
211+
212+
### Regex Block Lists
213+
214+
One regex pattern per line:
215+
216+
```regex
217+
# Block all subdomains starting with "ads"
218+
^ads\.
219+
# Block tracking domains
220+
.*tracking.*\.com$
221+
```
222+
223+
### AdBlock Lists
224+
225+
Supports a subset of AdBlock syntax:
226+
227+
```regex
228+
! Comment
229+
||ads.example.com^
230+
||tracking.example.com^$all
231+
@@||safe.example.com^
232+
```
233+
234+
## How Blocking Works
235+
236+
1. **Group Selection**: When a DNS request arrives, the app determines which group applies based on:
237+
- First, local endpoint mapping (`localEndPointGroupMap`)
238+
- Then, client IP/network mapping (`networkGroupMap`)
239+
- More specific network matches take precedence
240+
241+
2. **Allow Check**: If the domain matches any allow list (static, URL-based, regex, or AdBlock whitelist), the request is NOT blocked.
242+
243+
3. **Block Check**: If the domain matches any block list, the app returns:
244+
- `NXDOMAIN` if `blockAsNxDomain` is `true`
245+
- Configured `blockingAddresses` for A/AAAA queries
246+
- NO DATA response for other query types
247+
248+
4. **Blocking Report**: When `allowTxtBlockingReport` is enabled:
249+
- TXT queries for blocked domains return metadata about why the domain was blocked
250+
- EDNS Extended DNS Error option is included in responses
251+
252+
## Use Cases
253+
254+
1. **Parental Controls**: Create a "kids" group with stricter blocking for children's devices
255+
2. **Guest Network**: Apply different policies to guest WiFi subnet
256+
3. **IoT Isolation**: Block telemetry for IoT devices on a specific VLAN
257+
4. **Multi-tenant DNS**: Different blocking policies for different clients sharing the same DNS server
258+
5. **DoH/DoT Differentiation**: Apply different policies based on DNS transport protocol
259+
260+
## Troubleshooting
261+
262+
### Block lists not updating
263+
264+
- Check the DNS server logs for download errors
265+
- Verify the URLs are accessible from the server
266+
- Ensure the server has internet connectivity (or proxy configured)
267+
268+
### Domains not being blocked
269+
270+
1. Verify the client IP maps to the correct group
271+
2. Check if the domain is in an allow list
272+
3. Confirm `enableBlocking` is `true` at both root and group level
273+
4. Review the group's block list configuration
274+
275+
### Testing blocking
276+
277+
Query a TXT record for a blocked domain from the client IP address to see the blocking report:
278+
279+
```bash
280+
dig TXT blocked-domain.com @your-dns-server
281+
```

Apps/AdvancedBlockingApp/dnsApp.config

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
},
1212
"networkGroupMap": {
1313
"192.168.10.20": "kids",
14-
"0.0.0.0/0": "everyone",
15-
"[::]/0": "everyone"
14+
"0.0.0.0/0": "everyone else",
15+
"[::]/0": "everyone else"
1616
},
1717
"groups": [
1818
{
19-
"name": "everyone",
19+
"name": "everyone else",
2020
"enableBlocking": true,
2121
"allowTxtBlockingReport": true,
2222
"blockAsNxDomain": true,

Apps/AdvancedForwardingApp/AdvancedForwardingApp.csproj

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net9.0</TargetFramework>
4+
<TargetFramework>net10.0</TargetFramework>
55
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
6-
<Version>4.0</Version>
7-
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
6+
<Version>5.0</Version>
7+
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
88
<Company>Technitium</Company>
99
<Product>Technitium DNS Server</Product>
1010
<Authors>Shreyas Zare</Authors>
@@ -41,6 +41,9 @@
4141
<None Update="dnsApp.config">
4242
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
4343
</None>
44+
<None Update="README.md">
45+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
46+
</None>
4447
</ItemGroup>
4548

4649
</Project>

0 commit comments

Comments
 (0)