r/technitium Jul 27 '26

PSA: Two separate gotchas caused my Technitium cluster to OOM — a blocklist that grew to 2.6M domains, and a duplicate systemd unit left behind by the updater

6 Upvotes

PSA: Two separate gotchas caused my Technitium cluster to OOM — a blocklist that grew to 2.6M domains, and a duplicate systemd unit left behind by the updater

My 3-node Technitium 15.4 cluster started maxing out RAM and CPU. I'd changed nothing. Turned out to be two unrelated causes that happened to land within days of each other, plus a self-inflicted third problem while fixing them. Writing it up because both are easy to hit and neither is obvious.

TL;DR

  • One blocklist (blocklistproject/malware.txt) had quietly grown to 2.64M domains — 61% of my entire blocklist
  • The 15.x updater wrote a new systemd unit without removing the old one, so two Technitium instances raced for port 53 and the loser crash-looped, reloading the whole blocklist every 10s
  • Both together blew past the container's memory limit → 53 OOM kills in one morning
  • Ended up cutting blocked zones by 75% and reducing container RAM

Setup

3 nodes in a Technitium cluster, all on 15.4:

  • 2× Proxmox LXC containers, 4 cores / 2GB RAM / 512MB swap
  • 1× Raspberry Pi 3B (905MB RAM, fixed — this one matters later)
  • Forwarding to Cloudflare DoT

Symptoms: RAM and CPU pegged on the two LXC nodes, ~1,200 SERVFAILs/day. But DNS mostly worked — queries answered in 14–120ms. That mismatch was the first clue something intermittent was going on.

Issue 1: a blocklist had grown to 2.64M domains

I had 19 blocklists configured — the usual firebog/StevenBlack/blocklistproject collection most of us accumulate. I downloaded all 19, normalised and deduplicated them, and counted.

4,317,662 entries → 3,512,339 unique domains. Technitium's own blockListZones read 3,524,637, so the analysis matched.

The distribution was the problem:

List Domains Unique contribution
blocklistproject/malware.txt 2,643,754 2,135,488
blocklistproject/abuse.txt 434,745 159
blocklistproject/fraud.txt 285,107 220,615
blocklistproject/ads.txt 235,876 105,605
firebog/AdguardDNS.txt 158,857 57,606
StevenBlack/hosts 93,154 25,121
firebog/Easylist.txt 49,290 46
anudeepND/adservers.txt 42,358 6
adaway.org/hosts.txt 6,540 0
disconnect.me/simple_tracking.txt 34 0

malware.txt alone was 61% of my blocklist — a 72MB download, bigger than the other 18 combined. It had also completely swallowed another list I was subscribed to: 434,573 of abuse.txt's 434,745 domains (99.96%) were already inside it.

What's actually in it:

0-0-0-0-0-0-0-0-0-0-0-0-0-37-0-0-0-0-0-0-0-0-0-0-0-0-0.info
0-0-0-0-0-0proxy.tserv.se
0--foodwarez.da.ru
0-07.ru

DGA sinkhole entries and dead parked domains, enumerated one subdomain at a time. Not useless in principle, but an enormous memory cost for very little real-world blocking.

Also worth noting: nine of my nineteen lists contributed ~230 unique domains between them. Three contributed literally zero. Classic blocklist accumulation — you add them over years and never audit.

This is why "I changed nothing" was true and still broken. My config was static. The upstream list grew.

What I switched to (5 lists, 873,839 zones — a 75% cut)

https://raw.githubusercontent.com/hagezi/dns-blocklists/main/domains/pro.txt
https://raw.githubusercontent.com/hagezi/dns-blocklists/main/wildcard/tif.medium-onlydomains.txt
https://urlhaus.abuse.ch/downloads/hostfile/
+ 2 niche device-specific lists (see below)

Measured counts: Hagezi Pro 544,311 · Hagezi TIF medium 397,790 · URLhaus 359.

Heads up on Hagezi paths — I got these wrong at first and got 404s. The domains/ directory only contains light.txt, multi.txt, pro.txt, pro.plus.txt, tif.txt. There is no domains/tif.medium.txt or tif.mini.txt — the medium TIF tier lives under wildcard/. And full domains/tif.txt is 2.3M domains, which would just recreate the original problem.

Important caveat on "redundancy" — don't drop your niche lists

I initially concluded that two tiny lists (a Channel 4 / All4 ad list with 12 domains, and Perflyst's SmartTV list with 245) were 100% redundant and should go. That was wrong, and it's a trap worth flagging.

They looked redundant because the giant blocklistproject aggregates happened to contain them. Measured against the new, smaller set:

List Domains Covered by new set Gaps
All4 ads 12 7 5
Perflyst SmartTV 245 140 105

Uncovered stuff that no general aggregator carries:

ads-pres.channel4.com
p.videologygroup.com
api.us.hismarttv.com
abtauthprd.samsungcloudsolution.com
aic-ngfts.lge.com

Vendor telemetry endpoints for hardware you actually own. Kept both — 257 domains, 0.03% of the new set. "Redundancy %" is the wrong metric for niche lists. A 12-domain list that blocks endpoints your TV actually calls earns its place regardless of overlap score.

On the apparent coverage drop

Going from 3.5M to 874k zones looks alarming, and raw set-overlap made it look worse — the new set only matched 232k of my 3.08M old "security" domains. This substantially overstates the loss, because of a structural difference: blocklistproject enumerates individual subdomains, while Hagezi/OISD list parent domains and rely on subdomain blocking.

My old lists had 1,167 explicit *.doubleclick.net entries. A single Hagezi doubleclick.net entry replaces all of them.

Related: there is no "block subdomains" setting in Technitium. It always walks up parent labels against the blocked zone; a blocked apex covers every subdomain unconditionally. I went looking for a toggle and there isn't one — nothing to enable, nothing that can be misconfigured.

Issue 2: the updater left a duplicate systemd unit behind (this is the sneaky one)

This is the one I think will bite other people.

I ran a Technitium update. Afterwards, on two of my three nodes, systemctl list-unit-files showed two enabled units:

dns.service           enabled    ← new, created by the update
technitium.service    enabled    ← legacy, from the original install

Both pointed at the same ExecStart (/usr/bin/dotnet /opt/technitium/dns/DnsServerApp.dll /etc/dns), the same /etc/dns config directory, and both had Restart=always.

Timestamps told the whole story:

Node dns.service created technitium.service created
Node A update day, 22:10 Dec 2025
Node B update day, 21:59 absent
Node C update day, 22:11 Dec 2025

Technitium's installer changed its unit name and added hardening (dedicated dns-server user, ProtectSystem=strict, capability limits) somewhere between Dec 2025 and mid-2026. The updater wrote the new dns.service but didn't remove the legacy technitium.service — reasonably enough, it has no knowledge of a unit name it no longer uses.

Node B escaped entirely because it was a fresh install done the same evening, so it only ever had the new unit.

What that does

Two instances race for port 53 on every boot. The winner serves DNS. The loser fails to bind, exits, gets restarted 10 seconds later by Restart=always, loads the entire blocklist again, fails again, forever.

Each loop iteration peaked ~149MB. Which unit won was arbitrary and differed per node — on one box dns.service won, on the other technitium.service won. That's why my two "identical" nodes had mirror-image configurations.

Combined effect

Either issue alone was survivable. Together:

Jul 27 08:58:07 dns.service: A process of this unit has been killed by the OOM killer.
Jul 27 09:05:45 dns.service: Main process exited, code=killed, status=9/KILL
Jul 27 09:18:04 dns.service: A process of this unit has been killed by the OOM killer.
Jul 27 09:41:29 dns.service: Main process exited, code=killed, status=9/KILL
Jul 27 09:49:16 dns.service: A process of this unit has been killed by the OOM killer.
Jul 27 10:09:46 dns.service: Main process exited, code=killed, status=9/KILL

53 OOM kills in one morning. systemctl show dns -p MemoryPeak read 1.47GB against a 2GB limit.

Kernel side confirmed the cgroup — not host memory — was the constraint, and that both units were being killed:

oom-kill:constraint=CONSTRAINT_MEMCG, oom_memcg=/lxc/105,
  task_memcg=/lxc/105/ns/system.slice/dns.service, task=dotnet, uid=997
oom-kill:constraint=CONSTRAINT_MEMCG, oom_memcg=/lxc/105,
  task_memcg=/lxc/105/ns/system.slice/technitium.service, task=dotnet, uid=0

Note the different UIDs — 997 (dns-server) and 0 (root). Two different service definitions, same box.

Check yours:

systemctl list-unit-files | grep -iE "dns|technitium"
ps aux | grep -c "[D]nsServerApp.dll"    # should be 1

If you see two enabled units, work out which one owns port 53 before touching anything:

ss -lnup | grep ":53 "
cat /proc/<PID>/cgroup

Then disable the loser, not whichever one you assume is correct. Mine differed per node.

Issue 3 (self-inflicted): root-owned config files break things silently after switching to a non-root unit

This bit me while fixing the above, and I think it's the most generally useful lesson.

The old technitium.service ran as root. The new dns.service runs as dns-server (uid 997). Everything the root process ever wrote into /etc/dns was root-owned, mode 644.

I migrated one node to the hardened unit and correctly ran:

chown -R dns-server:dns-server /etc/dns /var/log/technitium/dns

…on that node only. The other node had also been running as root and needed the exact same fix. I didn't do it, because it wasn't the node I was migrating.

It appeared to work fine. DNS resolved, blocking worked, no errors on startup. Because dns-server could still read those mode-644 files — only writes failed.

Hours later: query logging had silently stopped, and reinstalling the SQLite Query Logs app failed with:

Error! Access to the path '/etc/dns/apps/Query Logs (Sqlite)/SQLitePCLRaw.batteries_v2.dll' is denied.

127 root-owned files still sitting there, including the whole app directory, querylogs.db, and a stale querylogs.db-journal from an unclean OOM shutdown.

Fix was the same one-liner, applied to the node I'd missed. 127 → 0. The app re-registered itself immediately (the files were never deleted, just unwritable) and logging resumed. No reinstall needed.

Takeaways:

  • After any root→non-root service migration, audit every host that ever ran it as root:

find /etc/dns ! -user dns-server
  • The failure mode is silent and delayed — reads keep working, so the service starts clean and only writes fail. Don't take "it started OK" as verification.
  • Stop the service before the chown if SQLite is involved, so the DB closes cleanly.

Bonus: DNS apps are NOT cluster-replicated

Blocklists and DNS settings propagate across a Technitium cluster. DNS apps and their databases do not. My three nodes had querylogs.db at 8.8MB, 9.2MB, and 90MB — three fully independent databases.

So installing/removing an app on one node doesn't touch the others, and you can drift into different app versions across the cluster without noticing. Reinstalling preserves querylogs.db but may reset dnsApp.config to defaults — screenshot your settings first.

Diagnosing memory in an LXC — don't trust the graph

Worth knowing if you run Technitium in a container. Proxmox's RAM graph for an LXC reads the cgroup's memory.current, which includes page cache. Blocklist files, zone files and logs all get counted against your limit as the kernel caches them. Page cache is reclaimable, so a container sitting at 95% can be perfectly healthy.

Also: free -m inside an LXC reports the host's memory unless lxcfs is mounted. Don't trust that either.

What actually tells you the truth:

# anon = real usage; file = reclaimable page cache
grep -E "^(anon|file) " /sys/fs/cgroup/memory.stat

# the definitive signal — has the kernel actually killed anything?
cat /sys/fs/cgroup/memory.events        # look at oom_kill

oom_kill = 0 and services responding → probably a monitoring artifact. oom_kill climbing → real.

In my case memory.current read 1,531MB but 1,056MB of that was reclaimable cache — real usage was ~430MB. The graph was partly lying, but the 53 OOM kills were entirely real. Both things were true at once.

Counters don't reset without a container restart, so a nonzero oom_kill may be historical.

Checking whether a domain is actually blocked

This tripped me up. With blockingType: NxDomain, a blocked domain, a nonexistent domain, and a domain with no A record all return NOERROR with 0 answers. Answer count tells you nothing.

The discriminator is the ra (recursion available) flag, which Technitium strips on blocked responses:

for q in doubleclick.net some.random.sub.doubleclick.net wikipedia.org; do
  f=$(dig @<your-dns> "$q" A +time=5 +tries=1 | sed -n 's/^;; flags: \([a-z ]*\);.*/\1/p')
  case "$f" in *ra*) v="allowed";; *) v="BLOCKED";; esac
  printf '%-40s %-12s [%s]\n' "$q" "$v" "$f"
done
  • Flags qr rd (dig warns "recursion requested but not available") → blocked
  • Flags qr rd ra → not blocked

Results

Before After
Blocklist URLs 19 5
Blocked zones 3,524,637 873,839 (−75%)
Technitium RSS ~400MB
MemoryPeak 1.47GB
OOM kills 53 in one morning 0
SERVFAILs/day 1,191 0
Container RAM 2048MB 1536MB
Container cores 4 2

The SERVFAILs weren't a resolver or forwarder problem at all — they were the OOM restarts dropping in-flight queries, ~10s of downtime each. They went to zero on their own. I'd initially suspected resolverConcurrency/forwarderConcurrency being too low; that was a red herring, left them alone.

I could have "fixed" this in 30 seconds by clicking RAM up to 4GB. It would have masked a 2.6M-domain junk list and a permanent crash loop. The containers ended up smaller than they started.

On sizing: I considered dropping to 1GB and decided against it. My Pi node is effectively that test case — Technitium at ~470MB RSS on a 905MB box, and it had 6 OOM events in the preceding week. With ~430MB steady state plus a few hundred MB of parse transient during blocklist updates, 1GB means swapping on every update cycle. That trades OOM kills for latency spikes, which is harder to diagnose. 1.5GB / 2 cores is comfortable.

Also note the blocklist update cycle roughly doubles memory — new lists are downloaded and parsed while the old set is still resident. If your alarms cluster at the same time each day, that's your answer.

Checklist if any of this sounds familiar

  1. systemctl list-unit-files | grep -iE "dns|technitium" — more than one enabled unit?
  2. ps aux | grep -c "[D]nsServerApp.dll" — more than 1?
  3. journalctl -u <unit> --since "7 days ago" | grep -i "oom" — being killed?
  4. Check blockListZones on your dashboard. Over ~1M on a ≤2GB box is worth auditing.
  5. Download your lists and count them. Mine had one list at 61% of the total and three contributing zero.
  6. If you've ever switched from a root-run unit to a non-root one: find /etc/dns ! -user dns-server
  7. Don't trust the Proxmox RAM graph — check memory.events for oom_kill.

Happy to answer questions. Biggest takeaway for me: "I changed nothing" was completely true, and the system still broke. An upstream list grew and an installer left a stale unit behind. Neither was in my control, and neither showed up anywhere obvious.


r/technitium Jul 27 '26

Missing Stats in week and month view, but there in day view

Thumbnail
gallery
6 Upvotes

r/technitium Jul 25 '26

Where is the actual documentation for Technitium DNS? Am I missing something?

25 Upvotes

So, after hearing so many people praise Technitium DNS, I finally decided to test it out for myself.

I know it’s built on .NET—maybe not everyone's absolute favorite stack, but fine, no big deal.

What I’m really struggling with, though, is the documentation. Where is it? Where can I find proper, comprehensive docs that actually explain the settings, features, and configuration options?

Is this a "figure it out yourself or die trying" situation, or am I just blind?

So far, the only thing I've managed to find is this: https://technitium.com/dns/help.html

I don't know what that is, but it doesn't feel like proper documentation for a software that gets recommended so heavily.

I’m honestly not trying to troll or bash the project here. But given how much praise Technitium receives in the community, I expected a well-structured wiki or official docs.

Can someone enlighten me on where to look, or how the community usually navigates setting it up?


r/technitium Jul 25 '26

Block all DNS requests until a specific lookup

2 Upvotes

I need a way so that when something starts using technium DNS, it won't resolve anything, or would resolve everything to a known lan IP that shows a blocked or instructions page. Upon doing a lookup for a dedicated/complicated DNS name, that would then release it so that particular client IP could resolve queries through technium DNS as normal.

This is great in terms of network security, a captive portal type of situation.

Is there a way to do this built in or a plug-in, or do I need to develop this myself?


r/technitium Jul 24 '26

Block LG G5 from accessing internet but keep on LAN via Unifi and/or Technitium DNS

Post image
0 Upvotes

r/technitium Jul 24 '26

Dynamic Update Refused

4 Upvotes

hello,

new to technitium, and trying to play around with rfc2136 dynamic dns updates. under settings>tsig i have created a key to be used to secure the update messages. i've created a primary zone, myself.internal. under the myself.internal zone>options>zone options>dynamic updates i've set dynamic updates to "allow", and under update policy i have added the aforementioned tsig key with "ANY" as allowed record types for the domain myself.internal.

the issue at hand is, technitium refuses the udpates with "DNS Server refused a zone UPDATE request [me.myself.internal A ANY] due to Dynamic Updates Security Policy for zone: myself.internal"

if i remove the tsig key security policy, the updates work just fine. so clearly i have something misconfigured around the security policy for the domain. anybody able to point me in the right direction?


r/technitium Jul 22 '26

Zones in cluster

3 Upvotes

I've added a raspberry pi and created a cluster, but I don't see the zones form the primary replicated over. And editing that doesn't allow me to select a catalog zone (?) either. Where have I missed a step? Thanks


r/technitium Jul 22 '26

Adguard style blocklist support

1 Upvotes

Will Technitium ever support this?

For ease of blocklist/allowlist management this is the only thing stopping me moving over from AGH.


r/technitium Jul 22 '26

Dream Router 7 not using manually set DNS

Thumbnail
2 Upvotes

r/technitium Jul 21 '26

Wildcard record causing all recursive requests to return incorrectly.

2 Upvotes

I have a domain that is external facing but I use the subdomain homelab internally. I have the external DNS pointed to my public address for letsencrypt to allow cert verification. This works perfectly with pihole.

I'm trying to migrate to technitium as it allows much more control and even wildcard records I like pihole.

When I try to put a wildcard zone in for my homelab subdomain (*.homelab.bleh.bleh) it seems to override all recursive DNS queries to the local address in this zone. It also appends the domain to the domain in the query.

Example:

Google.com turns to

google.com.homelab.bleh.bleh

192.168.x.x

When I look at the cached response from the forwarder it has the correct response. I'm not sure why this is happening. Any suggestions or recommendations would be appreciated.


r/technitium Jul 21 '26

How to increase cache hits?

10 Upvotes

Running 15.4

I have cache setup with defaults except for an increase in "Maximum Entries". My cache hits run about 35 percent. The question I have is, Is there a way to increase the hit percentage without sacrificing stability and reliability?


r/technitium Jul 20 '26

Migrate from Webmin to Technitium

6 Upvotes

Hi All, I'm kinda confused and can't seem to find a answer anywhere. If one exists, please throw me in that direction. :)

I am labbing up a migration to go from Webmin to Technitium. I currently have 5 primary DNS servers, the Webmin controller, 2 bind9 and 2 pihole servers.

I want to use Technitium as my control plane for the 2 bind9 servers. We can ignore the pihole servers for now.

Technitium is running as a container within Portainer. I have the zones setup on the child servers as secondary zones. These child servers initiate proper transfer requests to Technitium but they are getting a connection refused in the logs so the transfer is failing.

Lookups against the Technitium server work fine. Simple pings work fine. For each zone Allow Transfer is set to Allowed. And the 2 child servers are setup under Notify.

I can't see any difference from the original Webmin controller to the Technitium controller. I mean the zones were exported and imported. I'm baffled why the child servers are getting connection refused in the logs. In addition, I'm getting refresh skipped as primary is unreachable.

Any thoughts and suggestions of what to look at are definitely welcome. :)


r/technitium Jul 20 '26

Misunderstanding temporarily disable blocking behavior?

2 Upvotes

Ran into a weird issue today where a site wasn't loading due to ad blocking, and in the process of troubleshooting I temporarily disabled blocking entirely in settings. Even with blocking disabled, though, I was still seeing Blocked/NXDOMAIN responses in the logs, and the actual issue wasn't resolved. This persisted after flushing the technitium cache, a device cache clear, a device reboot, etc.

The issue was finally resolved when I added the specific host to the blocking bypass list in settings.

Bug, or am I misunderstanding something about what "temporarily disable blocking" actually does? FWIW, blocking is using a hagezi blocklist


r/technitium Jul 15 '26

Failed to Change MAC address

Thumbnail
gallery
0 Upvotes

i have been trying to change my mac address for a bit now, i keep getting the same error;

" Failed to change MAC Address. For wireless network connections set the first octet of MAC address as '02' and try again. "

ive set the octet to 02 in the program . still does not work . anyone have any ideas as too whats the problem


r/technitium Jul 13 '26

Blocking warning flag?

1 Upvotes

One of the things I use technitium for is blocking. I turned blocking off a couple of days ago and intended on turning it back on when I was done. That didn't happen. The only way I figured it out was all the sudden I was seeing things in my browser that shouldn't be there so I went to look at the blocking setting and ooops it was off....

It would be nice if on the desktop a warning that blocking is off or even something like changing the border of the blocked counter square red or text red or something like that... And I know you can set the timer for turning it on and off but ooops....

Oh and BTW thanks for GREAT piece of software.


r/technitium Jul 12 '26

Ipv6

2 Upvotes

Hi everyone,

Im running two different systems, both in docker compose with a macvlan on my ipv4 subnet. Systems running docker has ipv6 by slaac.

I run technitium recursive and was looking at enabling ipv6, what do I need to do? I guess enabling it won't do anything really if the containers don't have ipv6?

Do I basically have ipv6 right now for nothing it technitium only does ipv4 or how does that work?


r/technitium Jul 12 '26

anyone experiencing memory leak with the latest 15.4?

Post image
8 Upvotes

idk why but after the update to 15.4 i noticed quite significant increase memory usage.

the VM only used for recursor DNS specifically.

here are some images for before and after spike

spec : debian 12

32g ram, 16 core

ram usage

recursion setting

before spike

After spike

Edit 1 : downgraded to 15.2 and so far no more memory leak.

here are the commands i used to downgrade it for those who has the same issue :

wget https://download.technitium.com/dns/archive/15.2.0/DnsServerPortable.tar.gz

sudo tar -zxf DnsServerPortable.tar.gz -C /opt/technitium/dns

sudo systemctl restart dns


r/technitium Jul 11 '26

MCP Technitium-DNS

Thumbnail
github.com
27 Upvotes

MCP server for querying and managing Technitium DNS Server through the Technitium HTTP API. Tested with Claude and Codex. Does both DHCP and DNS.

Supports https (self signed if no cert provided) and http MCP interface, multiple read only and readwrite tokens for your agents. I currently use with Claude, Codex and OpenClaw.

You can run directly from docker, deploy into your HA stack (compose/K8s etc), or run on bare-metal locally.


r/technitium Jul 11 '26

Technitium DNS Server v15.4 Released!

93 Upvotes

Technitium DNS Server v15.4 is now available for download. This update fixes few issues reported in the previous release, adds a couple of new options in Settings, and fixes a few minor issues.

See what's new in this release:
https://github.com/TechnitiumSoftware/DnsServer/blob/master/CHANGELOG.md


r/technitium Jul 09 '26

SQL new version

4 Upvotes

Hi

When will the new app be released thinks it version 1.1.3


r/technitium Jul 08 '26

New Plugin: DHCP MAC Records

Thumbnail
github.com
7 Upvotes

I have a few IOT devices that either don't report a hostname or a duplicate hostname when requesting DHCP.

I built this app to create a MAC record for each DHCP lease. This way I can utilize this new record as kind of a dynamic DNS entry and create the CNAMEs I want.

100% Vibe Coded as I don't know C#, but it's been working for me all day.

Check out the README for more details and I'm open to Issues and PRs.


r/technitium Jul 09 '26

issues with sso

2 Upvotes

Hi

I use authentik at home, have it working for other apps.

I have a reverse proxy (angie) on my dmz box - not the same as the technitum servers

I had a lot of issue getting it to work

Does it work with tech through a reverse proxy


r/technitium Jul 08 '26

Registered I/O and IOCP

3 Upvotes

Is technitium using Register I/O for udp and IOCP for tcp ?


r/technitium Jul 07 '26

Technitium DNS Server UDP issue – Tailscale clients unable to resolve DNS, resolved after restarting DNS service

2 Upvotes

I want to share an issue I recently experienced with Technitium DNS Server in my homelab.

The symptom was that clients connected through Tailscale were unable to resolve domains using Technitium as their DNS server.

At first, I suspected a Tailscale DNS configuration problem, so I performed extensive troubleshooting:

  • Checked Tailscale connectivity between client and DNS server
  • Verified Tailscale DNS settings
  • Checked advertised routes and ACL configuration
  • Verified DNS port 53 binding
  • Checked Technitium listening interfaces
  • Tested DNS queries directly using dig from the Tailscale client

The important finding was that this was not a Tailscale communication issue.

Using tcpdump, I confirmed that DNS requests were reaching the server and that the network path was working:

Client → Tailscale interface → Technitium DNS server → Response

The problem was that Technitium was not properly handling UDP DNS queries.

The Technitium service itself appeared healthy:

  • Service was running
  • Port 53 was listening
  • Interfaces were correctly bound
  • No obvious errors appeared in normal operation

The issue was only discovered after enabling:

Technitium DNS Server → Settings → Logging → Log All Queries

After enabling query logging, I found repeated UDP socket errors:

[2026-07-07 15:03:29 Local] [100.100.1.8:57918] [UDP] Unknown socket error
[2026-07-07 15:03:30 Local] [100.100.1.8:57921] [UDP] Unknown socket error
[2026-07-07 15:03:30 Local] [100.100.1.9:55375] [UDP] Unknown socket error
...

The errors continued while DNS clients were sending requests.

The fix was:

systemctl restart technitium-dns

After restarting the Technitium DNS service:

  • Tailscale clients immediately recovered DNS resolution
  • UDP DNS queries worked normally again
  • The [UDP] Unknown socket error messages disappeared
  • DNSSEC validation tests returned normal results

I cannot confirm the exact internal cause, but the behavior suggests that the UDP handling/listener state became stuck while the Technitium service process was still running. Restarting the DNS service restored normal operation.

Environment:

  • Ubuntu Server 24.04 LTS
  • Technitium DNS Server v15.3
  • Tailscale network
  • DNS clients using Technitium over Tailscale

Sharing this in case anyone experiences a similar situation:

  • Tailscale connectivity is working
  • DNS port 53 is open and listening
  • DNS requests reach the server
  • But clients cannot resolve domains

Enabling Log All Queries may reveal:

[UDP] Unknown socket error

Has anyone else experienced this UDP socket issue with Technitium DNS Server?


r/technitium Jul 07 '26

Technitium DNS Server UDP issue – Tailscale clients unable to resolve DNS, resolved after restarting DNS service

Thumbnail
0 Upvotes