With Technitium DNS Server, you can not just consume DNS-over-HTTPS (DoH), DNS-over-TLS (DoT), or DNS-over-QUIC (DoQ) services using forwarders but you can also host these services yourself. There can be several reasons to host your own DoH, DoT, or DoQ service. You may wish to have better privacy by not sharing your data with public DNS providers. Or your network or ISP blocks popular DoQ, DoT, and DoH services and also interferes with unencrypted DNS traffic.
In this post, we will setup DoQ, DoT, and DoH services on a cloud server and configure a locally running Technitium DNS Server to use the DoH service as a forwarder bypassing any network restrictions that may be in place.
Home Network |
In the above home network diagram, the locally running Technitium DNS Server is installed on a desktop PC or a Raspberry Pi that is connected to your WiFi router. The Cloud Linux server will host the DoH service which will be configured as a forwarder in the locally running DNS server on your network.
Once the configuration is complete, all DNS traffic will be encrypted between your locally running DNS server and the DoH server running on the cloud server. This effectively means that all your local DNS traffic will exit from the cloud server and thus wont be visible to your network provider or your ISP.
Requirements
You need a domain name which you can get from any domain name registrar like
Name.com (referral link). If you already own a domain name then you can use a sub domain on it for
hosting these services. A domain name is required since both these services
run over TLS protocol which uses SSL/TLS certificate to work. A domain name
will usually cost around $13/yr which depends on the extension. You can check
for the
pricing here.
You need a Linux server which you can get from any cloud hosting provider like Digital Ocean (referral link). You can get a server for as low as $5/mo with 1GB RAM. I would recommend to create a server with Ubuntu Server as the OS since this blog post will be using the same.
Installation
We will be using Ubuntu server in this blog post but you can choose any distro of your choice and follow similar instructions.
You can install Technitium DNS Server using the single line installation command as shown:
curl -sSL https://download.technitium.com/dns/install.sh | sudo bash
If the above command fails since you do not have curl installed, install it as shown below and try the above command again:
sudo apt update sudo apt install curl
You can also manually install the DNS server by following the install instructions.
We will be using Let's Encrypt TLS certificate and will be using certbot which does automatic certificate renewal for Let's Encrypt. Run the commands below to install certbot:
sudo apt update sudo apt install certbot
Configuration
To proceed with the DNS configuration, login to the DNS server web console
using the server's IP address and port 5380. For example, if your server's IP
address is '1.2.3.4' open http://1.2.3.4:5380/
in your web
browser. Chrome, Firefox and Edge web browsers are supported well.
The first configuration to be done is to enable Optional DNS Server Protocol DNS-over-HTTP in the DNS server Settings as shown below. Save the settings by clicking Save Settings button at the bottom. This will start the DoH service on port 80 to allow renewing the TLS certificate with HTTP challenge.
Optional DNS Server Protocols |
Since, the DNS server requires the certificate in PKCS #12 (.pfx) format, we
need to convert the issued certificate using the openssl command. To do that,
we will create a small script file at
/etc/letsencrypt/renewal-hooks/post/pkcs12convert.sh
using
nano
editor.
sudo mkdir -p /etc/letsencrypt/renewal-hooks/post/ sudo nano /etc/letsencrypt/renewal-hooks/post/pkcs12convert.sh
Copy the commands as show below in the nano editor. Here, replace 'example.com' with your domain name and 'mypassword' with a password of your choice or keep it blank to generate the pfx file with no password.
#!/bin/sh openssl pkcs12 -export -out /etc/letsencrypt/live/example.com/example.com.pfx -inkey /etc/letsencrypt/live/example.com/privkey.pem -in /etc/letsencrypt/live/example.com/cert.pem -certfile /etc/letsencrypt/live/example.com/chain.pem -passout pass:mypassword echo "pkcs#12 generated!"
Save the script by exiting the editor using CTRL+X
keys. We need
to make this script excutable by using the following command:
sudo chmod +x /etc/letsencrypt/renewal-hooks/post/pkcs12convert.sh
This pkcs12convert.sh
script will be automatically executed by
certbot after renewing the certificate.
Now, we can run certbot command with the webroot plugin to issue the TLS certificate as shown below:
sudo certbot certonly --agree-tos --email admin@example.com --webroot -w /opt/technitium/dns/dohwww -d dns.example.com
Note: Here, replace 'example.com' with your domain name. In this example, we have used 'dns.example.com' in which the sub domain 'dns' gives a good idea that you may be running a DoH service. You may wish to avoid this by not using sub domain names like dns, doh or dot and instead use something which is very common like "mail", or "blog", etc. This will make it difficult for someone on your network to identify if you are using a DoH service by looking at the domain name.
Once the certbot command succeeds, you will see the path of the certificate
that was generated in the output which should be in the
/etc/letsencrypt/live/<your-domain>/
directory.
Below is the output that you should see if the certbot command succeeds.
Saving debug log to /var/log/letsencrypt/letsencrypt.log Plugins selected: Authenticator webroot, Installer None - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Would you be willing to share your email address with the Electronic Frontier Foundation, a founding partner of the Let's Encrypt project and the non-profit organization that develops Certbot? We'd like to send you email about our work encrypting the web, EFF news, campaigns, and ways to support digital freedom. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (Y)es/(N)o: N Obtaining a new certificate Performing the following challenges: http-01 challenge for dns.example.com Using the webroot path /opt/technitium/dns/dohwww for all unmatched domains. Waiting for verification... Cleaning up challenges IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/dns.example.com/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/dns.example.com/privkey.pem Your cert will expire on 2021-01-08. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew" - Your account credentials have been saved in your Certbot configuration directory at /etc/letsencrypt. You should make a secure backup of this folder now. This configuration directory will also contain certificates and private keys obtained by Certbot so making regular backups of this folder is ideal. - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le
Since the certificate has been issued for the first time, we need to manually
executed our pkcs12convert.sh
script once to generate the pfx
certificate.
sudo /etc/letsencrypt/renewal-hooks/post/pkcs12convert.sh
We can now configure the DNS server with the pfx certificate file path and enable the DNS-over-TLS, DNS-over-HTTPS, and DNS-over-QUIC protocols (as per your requirements) in the settings as shown below:
Optional DNS Server Protocols With TLS Certificate |
Type in the same password that you had used while generating the pkcs12
certificate for the TLS Certificate Password option.
Save the settings by clicking the Save Settings button at the bottom so that the DNS server can start the DoQ, DoT, and DoH services using the newly configured TLS certificate. You may want to check the DNS Server logs from the web console to find out if there were any errors while starting these services.
Testing The Service
For DoQ and DoT service, you need to use the domain name that was used to
generate the certificate with port 853. Thus your DoQ or DoT configuration for
clients will be
tls-certificate-domain:853.
For DoH service, you need to use the domain name that was used to generate the
certificate in a URL format. Thus you DoH configuration for clients will be
https://tls-certificate-domain/dns-query
.
You can test the DoH, DoT, and DoQ services using the
DNS Client tool. Put in
the DoQ/DoT address tls-certificate-domain:853
or the DoH url
https://tls-certificate-domain/dns-query
as the Server in the DNS
Client, type in a domain name, select an appropriate protocol either QUIC,
TLS, or HTTPS and click Resolve to test both the services.
Note: By default, the "Allow Recursion Only For Private Networks" recursive resolver option (as shown below) in the DNS server settings is enabled and thus the DNS server will refuse to respond with an answer (RCODE=Refused) when you test it with the DNS Client. You will need to enable the "Allow Recursion" option to be able to use these services from the public Internet.
Recursive Resolver Options |
Once the tests are successful, you can configure your locally running Technitium DNS Server to use these services as a forwarder. Once you have configured the service as a forwarder your local DNS traffic will bypassing all your network or ISP restrictions.
Technitium DNS Server Forwarder Configuration |
You can also configure your Firefox web browser directly with the custom DoH URL. This will work only for Firefox and all other applications on your computer will keep using the default DNS server configured in your network settings.
To configure Firefox with custom DoH, go to Options > General and scroll down to find Network Settings. Click on the Settings button and find the DoH option at the bottom as shown below:
Firefox Custom DoH Option |
Auto Renewing TLS Certificate
Since, the certificate obtained from Let's Encrypt expires in 90 days, certbot
automatically configures a cron job that renews the certificates before they
expire. Since we have already configured the
pkcs12convert.sh
script file earlier, it will get automatically
executed by certbot when the certificate is renewed. The Technitium DNS Server
will automatically reload the renewed certificate when it detects any changes
for the pfx file by looking at its date modified attribute.
To test the certbot renewal process, we can try the dry run command. If there are no errors reported then it means the renewal was successful.
sudo certbot renew --dry-run
Running DoH With Another Web Server
You may have a requirement to run both the DNS server with DoH service and another web server for hosting websites. In such cases since both the DoH service and the web server would require to use ports 80 and 443, it would create a conflict.
A solution in such a scenario is to use the web server as a reverse proxy to
the DoH service. You will need to configure the web server with TLS
certificate and virtual hosting to reverse proxy to
http://127.0.0.1:8053/dns-query
and enable only the DNS-over-HTTP
optional DNS server protocol with its port set to 8053 as shown below:
Optional DNS Server Protocols With TLS Certificate |
With this setup, your web server will terminate TLS and do reverse proxy
allowing the DoH service through it. If your web server supports TLS
termination for TCP streams then you can point it to
127.0.0.1:53
and also provide DoT service through it.
If you are using nginx as your web server, you can use the snippet below to configure a reverse proxy for the DoH service. For more details, you can refer to the blog post on using nginx as a DoT or DoH gateway.
server { listen 80; server_name dns.example.com; return 301 https://$http_host$request_uri; } server { listen 443 ssl http2; server_name dns.example.com; ssl_certificate /etc/letsencrypt/live/dns.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/dns.example.com/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/dns.example.com/chain.pem; access_log /var/log/nginx/dns.example.com-access.log; error_log /var/log/nginx/dns.example.com-error.log; location / { proxy_pass http://127.0.0.1:8053/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Nginx-Proxy true; proxy_redirect off; } }
Conclusion
Using Technitium DNS Server combined with certbot, you can setup DoH, DoT, and DoQ services with automatic TLS certificate renewal and bypass any network restriction on DNS traffic. If you already have a web server like nginx running, you can use it for TLS termination and provide DoH, DoT, and DoQ services on the same server.
If you have any queries do let me know in the comments below or send an email to support@technitium.com.
Hi, Shreyas and thank you for your work.
ReplyDeleteWhat about performance name resolution DoH and/or DoT in compared with traditional method (DNS over UDP (not encrypted))?
Hi. Thanks for the question. There is an overhead due to encryption and due to TCP head of the line blocking. But, in practice its not much noticeable especially if you are running a local DNS server that is doing DoH and does caching.
DeleteHi, Shreyas.
DeleteI understood. Thank you for your answer.
Hey, good job there.
ReplyDeleteI understood this step if used in linux system, but how we setup this on windows with already running webserver(apache) ??
Can you help me?
Thanks for the compliments. You can configure DoH similarly on Windows too. The DNS server configuration is exactly same with only difference of using different tool for certificate auto renewal.
DeleteJust install the DNS server using the windows installer and configure it for DoH and DoT similar to the instructions in the blog post. You will need to install openssl on Windows separately to convert the SSL certificate into pfx format using the same command shown.
On windows use tools like https://certifytheweb.com/ to do auto renewal of the certificate.
If you already have apache web server running then you can configure apache with SSL certificate + auto renewal and then just reverse proxy to the DNS server on 8053 port. With this setup, all your SSL config is done with apache only and you just need to enable DNS-over-HTTP protocol on the DNS server.
Hi, thank you for the great work!
ReplyDeleteI see the instruction here to install the DNS server on an Ubuntu, but is it possible to use it as a Docker container? Do you have an official docker image?
Thanks for the compliments. There is no official docker image as of now. But, you can use this one which is updated regularly: https://hub.docker.com/r/m400/technitium
DeleteHello, in the pkcs12convert.sh I had to add a
ReplyDelete"openssl rsa -in privkey.pem -out privkey.nokey.pem"
before the actual "openssl pkcs12 -export [...]", otherwise it would not work (unable to read the private key), even if my private key was generated using step-ca (a letsencrypt compatible CA software)
Alessandro I am having the same issues with pkcs12convert.sh could you explain a bit more on how you got this to work.
DeleteAll the best,
Alessandro Giorgio Togna can you explain this a bit more having the same issues
DeleteHow would I set up dns over https using https://nginxproxymanager.com/ ?
ReplyDeleteDo i still need to get my own tls certification if I already have my domain & all its subdomains ssl'ed?
Thanks for asking. Do read the "Running DoH With Another Web Server" section at the end of this blog post.
DeleteThank you my friend, I have configured http and used the reverse proxy to connect that way.
DeleteThank you friend, would DNS over quic also work with the nginxproxymanger or is the only option http?
DeleteWith nginx, you can configure it to forward UDP request using proxy protocol to DNS server's DNS-over-UDP Proxy port. Similarly you can do that for TCP requests too. For DoT, you can have nginx configured to use TCP stream with TLS termination and proxy protocol and forward to the same DNS-over-TCP proxy port. For DoH and DoH/3, you use the DNS-over-HTTP option. While nginx supports HTTP/3, it does not support the plain QUIC protocol stream and thus you wont be able to use DoQ with nginx as the reverse proxy.
Deletehi, thank you for the instruction. i successfuly installed a server in my cloud as per the guide without errors and installed working locally in my homelab. however, im confused to how they can talk to each other? how do i configure my local technitium to talk to my cloud technitium to qoute "Once the tests are successful, you can configure your locally running Technitium DNS Server to use these services as a forwarder. " thank you
ReplyDeleteThanks for asking. You just need to use your cloud DoH server's URL with your local DNS server as the forwarder. To do that, login to your local DNS server's web panel and go to Settings > Proxy & Forwarders section where you need to enter the DoH URL as the Forwarder and select DNS-over-HTTPS as the forwarder protocol.
DeleteYour cloud DoH server's URL will be in this format: "https://tls-certificate-domain/dns-query". Where "tls-certificate-domain" is the domain name that you have used for your SSL certificate that you have configured for enabling the DoH optional protocol.
Greetings, thank you for the instruction. I successfuly installed a server in my cloud as per the guide without errors and installed working locally in my homelab. However, im confused to how they can talk to each other? How do i configure my local technitium to talk to my cloud technitium to qoute "Once the tests are successful, you can configure your locally running Technitium DNS Server to use these services as a forwarder. " in which as per the guide i need to enter "https://tls-certificate-domain/dns-query" confused on how my local server can connect to my cloud.
ReplyDeleteThank you in advance.
Regards,
Daryl
Yes, it will work with wildcard cert. But, for wildcard cert, you need to configure DNS challenge for renewal since HTTP challenge is not accepted for wildcard certs.
ReplyDeleteThanks for asking. The Private DNS feature in Android phones use DNS-over-TLS protocol and thus its not working with your DNS-over-HTTPS setup. You need to setup DoT protocol on your DNS server to use this android feature.
ReplyDeleteSeems like they support DoH for Android 13 and above by default but since the Private DNS option allows entering only domain name or IP address, they are enabling DoH only for popularly known DoH services like Google/Cloudflare/Quad9. So when you enter your own domain name, it may not enable DoH support and would instead work only with DoT.
DeleteYou can test this by enabling Mobile Hotspot feature on your Laptop and connect your phone to the hotspot WiFi. Then install Wireshark and run it. On your phone, enable Private DNS and check Wireshark to see if you see a request on port 853 or 443.
For DoT config, you are forwarding port 853 traffic then your traefik server should handle TLS certificate task and then forward plain TCP requests to DNS server's TCP port 53.
Hi,
ReplyDeleteWhat's the advantage to doing this, vs just forwarding via DOT to Quad9 or Cloudflare? I understand Cloudflare/Quad9 will have the logs, but isn't the risk of setting up your own DNS, it being prone to amplification /DDOSing etc, plus the maintenance overhead AND the performance impact of slower DNS due to a slow server vs dedicated servers with the large providers, is it really worth it other than to just shield yourself from the off chance Cloudflare/Quad 9 'do stuff' with your logs?
Thanks for asking. This is to have privacy and more control, plus you get to see stats and logs.
DeleteAmplification attacks occur only over UDP transport so if you just firewall inbound UDP and TCP port 53 then you wont have any of these issues. You should also configure rate limiting QPM Limit options in the Settings to mitigate any abuse.
The performance impact that you are imagining is non-existent since DNS is not a CPU intensive task but a IO intensive task. A $5 VPS will be sufficient for many cases. The only thing that can have effect is the network delays between your VPS and your broadband connection. And since you will have a locally running DNS server too in this scenario, a lot of the requests would be answered from local cache itself.
From what I know, these public DNS providers do sell the anonymized data to threat intel companies and other researchers. Even if the data does not contain your IP address, it can still point at you if you are using a specific service that you host yourself or that the service has a user specific domain name.
Hi there,
ReplyDeleteHow can I run certbot if DNS server run from a docker container. I can't map /opt/technitium/dns/dohwww to a local folder.
Thanks for asking. You can mount a volume on that path in docker to do that. A better option is to use DNS challenge instead of HTTP challenge. Read this blog post which explains how to configure DNS Challenge with certbot: https://blog.technitium.com/2023/03/how-to-auto-renew-ssl-certificates-with.html
DeleteI found this!
ReplyDeletehttps://blog.technitium.com/2023/03/how-to-auto-renew-ssl-certificates-with.html
I'll try it!!!
This comment has been removed by the author.
ReplyDeletehi Shreyas, first of all thank you for the developing technitium i've been into technitium for a couple of months now and it working great. Started to use DNS-over-TLS now following the instructions on your blog and its working pretty well, so my query is that; i do have two WAN as my source of internet loadbalance through mikrotik and upon checking it in "Clients" tab on my VPS, its showing only the IP of my 1 WAN where all of the queries on my local can be seen. Is this correct? Or is it there should be 1 more IP as such for my other WAN? Thank you
ReplyDeleteThanks for the compliments. I am assuming that your clients are on your local LAN network. In that case, it seems that your clients are sending DNS requests to your router and the router is forwarding them to the local DNS server which is why you see your WAN IP in clients list. You need to configure your DHCP server and change the DNS server IP address to your local DNS server. This will cause the clients to directly send requests to your local DNS server and you will see individual IP address of the clients.
DeleteThank you for your prompt reply on this Shreyas bro. yes your assumption is correct its connected through lan network set with my local technitium as DNS. im confused though because in my local "Clients" all can be seen who are connected to the local network wherein it is exactly supposed to do while on my cloud theres is only 1 IP address that all of my queries accumulated from my local technitium. Isn't theres should be two IP as I do have two WAN? My understanding is that wherever the query is requested from either on the "WAN 1 or WAN 2" isn't supposed to be my cloud will have two IP addresses right because "WAN 1 public IP" is requested facebook.com while "WAN 2 public IP" requested google.com which is not the case on my cloud theres only 1 IP on the "Clients" tab. Thank you!
DeleteThanks for the details. It seems that the outbound DNS requests are always using WAN1 and are not getting load balanced by your setup for some unknown reasons. But, that should not matter since the domain may get resolved from one network and the client may connect to the website using the other network. So, your effective traffic is being load balanced anyways irrespective of your DNS resolution.
Deletethank you for your response. much appreciated
Deleteone more thing Shreyas bro, why is it my local have a 841,903 total queries while my cloud have 2,031,817 total queries taken from "Last Day"- to have the same data point.
DeleteYour DNS on cloud server probably is receiving requests from other sources too if it has UDP service open to the Internet. Also, it will be resolving the server's requests too. It could be any other reason too.
Delete