Technitium DNS (and DHCP)

I actually installed and successfully use Technitium on a docker container I use in my unRAID server. where Nethserver is a VM.

But if you ask me, this is a “hit” to what Nethserver supposedly is.
Right now the only part of NS I actively use is the mail server, antispam (and similar) and webtop.
All the rest where taken over by stand-alone containers on my host machine.
But that of course is my own case scenario. Your mileage may vary.
That said, NS needs a real update, but that is a different topic.

Have you been unable to isntall technitium on NEthserver using the available Nethserver-docker?

I haven’t tried.
There is no point enabling NS docker module, when NS in itself is a VM running on a host that in turn already runs other containers.
My point is that NS should have an integrated full DNS solution (like Technetium) instead of the one they integrate now.

1 Like

and as you have been informed before, Nethserver in its current form, is tightly intertwined with dnsmasq so doing a direct integration of technitium would be next to impossible, if not pseudo-engeneering.

In that case, if you yourself, who is the user of the software solution you are proposing are not willing to get it working, or even try to get it working using the available method, so that other implementation scenario s can be looked into.

Why should anyone else be bothered in this community?

2 Likes

how really does sone create a vm using cockpit machines, especially loading iso images or

EDIT:

i get this erro:

ERROR internal error: process exited while connecting to monitor: 2021-10-22T14:48:53.915662Z qemu-kvm: -drive file=/home/vboxweb/CentOS-7-x86_64-DVD-2009.iso,format=raw,if=none,id=drive-ide0-0-0,readonly=on: could not open disk image /home/vboxweb/CentOS-7-x86_64-DVD-2009.iso: Could not open '/home/vboxweb/CentOS-7-x86_64-DVD-2009.iso': Permission denied Domain installation does not appear to have been successful. If it was, you can restart your domain by running: virsh --connect qemu:///system start tcc otherwise, please restart your installation.

edit fixed by chmod =rwx /home/vboxweb/CentOS-7-x86_64-DVD-2009.iso

I wonder if this might be easier to integrate with NS8, given its all-container architecture. I’m seeing more value in it than I once did (see Full, public, authoritative DNS support), but with the current architecture, I think it’d be near-impossible to replace dnsmasq in NS7. But it’d sure be nice for NS to be able to automagically handle all the dozens of DNS records that are used for email…

4 Likes

But they really aren’t. Technitium states as their headline feature that it’s DNS-based ad blocking, but it’s apparently a full-featured DNS server. Pi-Hole has improved since this topic was started; it now allows local DNS entries (so I can configure local hostnames on my LAN–which I can also do with NS, of course), but I’m not aware of any supported way for it to handle, say, TXT or SRV records.

4 Likes

While we are on the subject of “make a wish”… I would also very much appreciate a full DNS server. But for me it would only be full-fledged if the integration with Nethserver would allow to automatically generate and apply the current TLSA-Record at every LE-certificate renewal.
Currently, I have to manually generate a TLSA record every time I change my LE certificate, and then file it with my DNS provider. This is more than just annoying, but creates an interruption in the DANE state when the LE certificate is renewed automatically (certbot renew).

https://ssl-tools.net/mailservers/dargels.de

https://dane.sys4.de/smtp/dargels.de

But I’m not sure how many mail server administrators value DANE.

https://dane.sys4.de/smtp/nethesis.it

https://de.ssl-tools.net/mailservers/nethesis.it

Seems like there are two possible solutions to this:

  • Since the TLSA record is tied to the public key, not the certificate, instruct whichever ACME client you’re using to reuse the keys. For acme.sh, that’s the default behavior; for certbot, you’d use the --reuse-key flag. If the public key doesn’t change, the TLSA record doesn’t need to change.
  • If your DNS host supports automation (and if it doesn’t, consider changing to one that does–I continue to like and recommend Cloudflare), automate the update to the DNS record. This script (and its comments) should point you in the right direction for Cloudflare: A bash script to update a Cloudflare DNS A record with the external IP of the source machine · GitHub
  • Edit: a possible third. In the day of HPKP, it was recommended to pin a CA cert, not the leaf cert. If TLSA also allows (or recommends) this, do so.

Not to say this wouldn’t be a nice feature to automate into Neth’s hypothetical built-in authoritative DNS server, but I think it can be handled now with less difficulty than what you’re doing.

2 Likes

Sorry for hijacking the thread…
I’ve thought about that, too. But I am not at all sure if I can manage the migration in such a way that I can guarantee an uninterrupted operation of my DNS zones and the server installations that depend on them.

I have not found a guide that I fully trust. So far I have only found this one and halfway understood it.

https://community.cloudflare.com/t/recommended-practice-for-migrating-dns/161092/4

I have the impression that all these guides assume that you are familiar with the specialties with Cloudflare.

I noticed when I migrated my last domain to Cloudflare that they’d greatly streamlined the process–they query your current authoritative servers and duplicate all the records. So the process really is as simple as “register for Cloudflare, add the domain, (confirm that the records are transferred properly, making any desired changes), change nameservers at your registrar.” But until you take that last step, that of changing the nameservers at your domain registrar, you can mess around with the DNS records all you want, with no impact to the rest of the world.

You don’t need to use the Cloudflare CDN at all. You can, of course, and use it (to a degree) for no cost too, but you don’t need to use that feature at all.

1 Like

I have tested the first steps, but it doesn’t look so simple. But I think discussing that is not the real place here. I will open a new thread for this once.

1 Like

Overall it would be interesting to see Technitium installed Via docker

Docker is a supported installation method for Technitium, so that would be straightforward enough–just install docker-compose, edit docker-compose.yml, docker-compose up -d, and you’re up and running. The problem on Neth is that there’s something else already using port 53, so you’d need to either remove that (and break the rest of the system) or have Technitium listen on some other port (and thus be pretty much useless).

Edit: I wonder how this would work: Go ahead and set up Technitium, but rather than listening on port 53, have it listen on, say 5335. Then tell the system its DNS server is 127.0.0.1#5335. This is pretty much how you set up Unbound on a Pi-Hole…

First draft:

Install Technitium on Nethserver 7

Starting from a clean, up-to-date Nethserver 7 installation.

Install Docker and docker-compose

  • yum install nethserver-docker
  • curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
  • chmod +x /usr/local/bin/docker-compose

Install Technitium

  • mkdir /opt/technitium
  • cd /opt/technitium
  • nano docker-compose.yml
version: "3"
services:
  dns-server:
    container_name: dns-server
    hostname: dns-server
    image: technitium/dns-server:latest
    # Use "host" network mode for DHCP deployments
    # network_mode: "host"
    ports:
      - "5380:5380/tcp" #DNS web console
      - "5335:53/udp" #DNS service
      - "5335:53/tcp" #DNS service
      # - "67:67/udp" #DHCP service
      # - "853:853/tcp" #DNS-over-TLS service
      # - "443:443/tcp" #DNS-over-HTTPS service
      # - "80:80/tcp" #DNS-over-HTTPS service certbot certificate renewal
      # - "8053:8053/tcp" #DNS-over-HTTPS using reverse proxy
    environment:
      - DNS_SERVER_DOMAIN=dns-server #The primary 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_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, UseSpecifiedNetworks.
      # - 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 `UseSpecifiedNetworks` recursion option.
      # - 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 `UseSpecifiedNetworks` recursion option.
      # - 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_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, HttpsJson.
    volumes:
      - config:/etc/dns/config    
    restart: unless-stopped
volumes:
    config:
  • docker-compose up -d
  • docker network connect aqua dns-server

Make sure Technitium is up and running

  • Browse to http://your_ip:5380
  • Change/set the admin password

Create a test record

  • In the Technitium UI, create a zone of example.com
  • Create a TXT record for test.example.com with a random value of your choice
  • From another computer on your network, run dig @neth_ip -p 5335 txt test.example.com. You should get output like this:
dan@Dan-MacBook-Pro-2013  ~  dig @192.168.1.218 -p 5335 txt test.example.com

; <<>> DiG 9.10.6 <<>> @192.168.1.218 -p 5335 txt test.example.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41308
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;test.example.com.		IN	TXT

;; ANSWER SECTION:
test.example.com.	3600	IN	TXT	"foo"

;; Query time: 74 msec
;; SERVER: 192.168.1.218#5335(192.168.1.218)
;; WHEN: Sat Oct 30 14:22:33 EDT 2021
;; MSG SIZE  rcvd: 50

Tell Neth to use Technitium

  • mkdir -p /etc/e-smith/templates-custom/etc/dnsmasq.conf
  • nano /etc/e-smith/templates-custom/etc/dnsmasq.conf/25NameServers
#
# 25NameServers
#

# Don't read /etc/resolv.conf. Get upstream servers only from the
# command line or the dnsmasq configuration file.
no-resolv

# Specify IP address of upstream servers directly. Setting this flag
# does not suppress reading of /etc/resolv.conf, use "no-resolv" to do
# that.
server=127.0.0.1#5335

# By  default,  dnsmasq  will  send queries to any of the upstream
# servers it knows about and tries to favour servers that are known
# to  be  up.  Uncommenting this forces dnsmasq to try each query
# with  each  server  strictly  in  the  order  they   appear   in
# /etc/resolv.conf
all-servers

  • signal-event nethserver-dnsmasq-update

Note

Unfortunately, it isn’t currently possible to set a custom port on the DNS server without creating a custom template fragment like this. I’d expected to have been able to set it with config setprop dns NameServers 127.0.0.1#5335, but that breaks the dnsmasq template expansion.

Test

Run the same test as before, but without specifying the port number: dig @192.168.1.218 txt test.example.com. The results should be the same as before:

 dan@Dan-MacBook-Pro-2013  ~  dig @192.168.1.218 txt test.example.com

; <<>> DiG 9.10.6 <<>> @192.168.1.218 txt test.example.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16410
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;test.example.com.		IN	TXT

;; ANSWER SECTION:
test.example.com.	3600	IN	TXT	"foo"

;; Query time: 7 msec
;; SERVER: 192.168.1.218#53(192.168.1.218)
;; WHEN: Sat Oct 30 14:29:27 EDT 2021
;; MSG SIZE  rcvd: 50

Conclusion

Technitium is now up and running on your Neth server, and DNSMasq on the Neth server is configured to use Technitium as its upstream DNS provider. From here, you’re on your own.

5 Likes

does it mean, also the DNS records can be setup inside Nethserver, and work as before, or they wont work as before and will rely on technitium

Haven’t tested that yet, but let’s see. Log in to the Neth server manager. Create a DNS record like this:

Query that server:

 dan@Dan-MacBook-Pro-2013  ~  dig @192.168.1.218 a foo.familybrown.org

; <<>> DiG 9.10.6 <<>> @192.168.1.218 a foo.familybrown.org
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25903
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;foo.familybrown.org.		IN	A

;; ANSWER SECTION:
foo.familybrown.org.	0	IN	A	12.34.56.78

;; Query time: 5 msec
;; SERVER: 192.168.1.218#53(192.168.1.218)
;; WHEN: Sat Oct 30 18:29:37 EDT 2021
;; MSG SIZE  rcvd: 64

I’d say it works.

3 Likes

Technitium does have a HTTP API, too. So let’s play with it a bit. In all the examples, I’m piping the output through jq just for the sake of readability. Here’s how you’d create a record. First, log in:

[root@neth-tech technitium]# curl -s http://localhost:5380/api/login\?user\=admin\&pass\=password | jq
{
  "token": "df43d4dc49f5665167ffc6bf311089bb0cf576843f3b8ec27e9df1804733cd20",
  "status": "ok"
}

You’ll now use that token in every following request. We’re going to create a record for example.com, so let’s make sure this server claims to be authoritative for example.com:

[root@neth-tech technitium]# curl -s "http://localhost:5380/api/listZones?token=df43d4dc49f5665167ffc6bf311089bb0cf576843f3b8ec27e9df1804733cd20" | jq
{
  "response": {
    "zones": [
(snip)
      {
        "name": "example.com",
        "type": "Primary",
        "internal": false,
        "disabled": false
      },
(snip)
    ]
  },
  "status": "ok"
}

Yep, it’s there. So now, create the record:

[root@neth-tech technitium]# curl -s "http://localhost:5380/api/addRecord?token=df43d4dc49f5665167ffc6bf311089bb0cf576843f3b8ec27e9df1804733cd20&domain=_acme-challenge.example.com&type=TXT&value=___validation_token_received_from_the_ca___" | jq
{
  "response": {},
  "status": "ok"
}

It says OK, so we should be good. Let’s confirm. Note here that I’m querying the Neth server itself, not the Technitium instance directly.

 dan@Dan-Hack-Mini  ~  dig @192.168.1.218 txt _acme-challenge.example.com

; <<>> DiG 9.10.6 <<>> @192.168.1.218 txt _acme-challenge.example.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14089
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;_acme-challenge.example.com.	IN	TXT

;; ANSWER SECTION:
_acme-challenge.example.com. 3600 IN	TXT	"___validation_token_received_from_the_ca___"

;; Query time: 5 msec
;; SERVER: 192.168.1.218#53(192.168.1.218)
;; WHEN: Sun Oct 31 06:32:18 EDT 2021
;; MSG SIZE  rcvd: 101

OK, so (hypothetically) Let’s Encrypt was able to validate domain control, and we got the certificate. Let’s now delete the record, as it doesn’t serve any further purpose:

[root@neth-tech technitium]# curl -s "http://localhost:5380/api/deleteRecord?token=df43d4dc49f5665167ffc6bf311089bb0cf576843f3b8ec27e9df1804733cd20&domain=_acme-challenge.example.com&type=TXT&value=___validation_token_received_from_the_ca___" | jq
{
  "response": {},
  "status": "ok"
}

…and test:

 dan@Dan-Hack-Mini  ~  dig @192.168.1.218 txt _acme-challenge.example.com

; <<>> DiG 9.10.6 <<>> @192.168.1.218 txt _acme-challenge.example.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 57993
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 0

NXDOMAIN, just as it should be. OK, time to log out:

[root@neth-tech technitium]# curl -s "http://localhost:5380/api/logout?token=df43d4dc49f5665167ffc6bf311089bb0cf576843f3b8ec27e9df1804733cd20" | jq
{
  "status": "ok"
}

So given this, it’d be pretty simple for Nethserver (or any other application) to make any necessary changes to the DNS system–so, for example, Neth could automatically populate all the AD DNS records, or all the dozens of records that email can use. And certbot or acme.sh, with an appropriate hook script (acme.sh doesn’t include one, and I assume certbot doesn’t either), could automatically generate and remove the records used for domain validation.

A couple of major drawbacks, though:

  • AFAIK, there’s only one admin user, with full control. You need that user’s password to use the API–there are no API tokens.
  • As a result of the above, there are no limited privileges. Any application (or person) that has the admin password can do absolutely anything with it. Perhaps not the most secure arrangement.

Note also that the record types are case-sensitive. If you try to create a txt record, for example, rather than a TXT record, you’ll get an error like this:

{
  "status": "error",
  "errorMessage": "Requested value 'txt' was not found.",
  "stackTrace": "   at System.Enum.TryParseByName(RuntimeType enumType, String originalValueString, ReadOnlySpan`1 value, Boolean ignoreCase, Boolean throwOnFailure, UInt64& result)\n   at System.Enum.TryParseUInt32Enum(RuntimeType enumType, String originalValueString, ReadOnlySpan`1 value, UInt32 maxInclusive, Boolean ignoreCase, Boolean throwOnFailure, TypeCode type, UInt32& result)\n   at System.Enum.TryParse(Type enumType, String value, Boolean ignoreCase, Boolean throwOnFailure, Object& result)\n   at System.Enum.Parse(Type enumType, String value)\n   at DnsServerCore.WebServiceZonesApi.AddRecord(HttpListenerRequest request) in Z:\\Technitium\\Projects\\DnsServer\\DnsServerCore\\WebServiceZonesApi.cs:line 505\n   at DnsServerCore.DnsWebService.ProcessRequestAsync(HttpListenerRequest request, HttpListenerResponse response) in Z:\\Technitium\\Projects\\DnsServer\\DnsServerCore\\DnsWebService.cs:line 519"
}
5 Likes

Can Threatshield AND Pi-Hole used simultanoesly on Nethserver? Doesn’t Threatshield include the PI-Hole functionality?

AFAIK threatshield use the pihole FTL (daemon/backend)

When I did it I preferred to see the pihole UI

2 Likes