Problems activating your account? Send notification email to:
Host4Fun Budget VPS Hosting
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to Set up Your Own DoH Server on CentOS 8
First off, I must confess that this HowTo is nothing but a poor man's way to deploy a fully functional DoH server. It's basically my way of utilizing the available resources at hand on @Neoon's NAT-VPS on his NanoKVM platform; thus if we forget about the transparent reverse-proxy (HAProxy) at the NAT-gate, this implementation is basically concerned to tight together 3 independent pieces of software:
  • A web server that will accept DoH's HTTPS requests. It will be the only one handling the SSL part of the communication (thus it's our SSL termination point,) while serving as a proxy for the DoH server over HTTP.
  • A DoH server, running in the background and doing the grunt work of translating Wireformats between HTTP and UDP, conforming to the IETF DNS-over-HTTPS (RFC 8484).
  • A DNS resolver, handling the name resolution part of this setup.

Systemd-resolved as the DNS resolver
Please refer to the 'A Case for systemd-resolved as the default DNS Resolver' thread for more details on this (I did specifically created it, because it deserved to be discussed thoroughly.) In here, I'll just publish systemd-resolved configuration file -located at /etc/systemd/resolved.conf- that's needed for this use case:
#  This file is part of systemd.
#  (..........)


Now, you're supposed to start the service and enable it permanently (if you choose to), then by running this command, you'll see the service current status:
[root@vps ~]# resolvectl   [OR  systemd-resolve --status]

      LLMNR setting: no
MulticastDNS setting: no
 DNSOverTLS setting: opportunistic
     DNSSEC setting: allow-downgrade
   DNSSEC supported: yes
        DNS Servers:
Fallback DNS Servers:
         DNSSEC NTA:

As a test:
[root@vps ~]# dig

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el8 <<>>
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45774
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

; EDNS: version: 0, flags:; udp: 65494
; IN A


;; Query time: 66 msec
;; WHEN: Sat Feb 08 13:33:49 +01 2020
;; MSG SIZE  rcvd: 55

# A second time, to test the caching feature:
[root@natty ~]# dig

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el8 <<>>
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 42439
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

; EDNS: version: 0, flags:; udp: 65494
; IN A


;; Query time: 0 msec
;; WHEN: Sat Feb 08 13:38:03 +01 2020
;; MSG SIZE  rcvd: 55

To get an idea on the resolver stats, run this:
[root@vps ~]# systemd-resolve --statistics
DNSSEC supported by current servers: yes

Current Transactions: 0
 Total Transactions: 11

 Current Cache Size: 7
         Cache Hits: 3
       Cache Misses: 8

DNSSEC Verdicts
             Secure: 4
           Insecure: 9
              Bogus: 0
      Indeterminate: 0

That should be all for the DNS resolver part (for more specifics on systemd-resolved, check the thread mentioned above.)

Setting up a DoH Server
if we run a search on Gihub public repositories on IETF-compliant DoH, three results are resturned, but m13253/DNS-over-HTTPS seems to be the most mature.

Thus we'll be using m13253/DNS-over-HTTPS as our DoH-server, which supports the following features:
  • IPv4 / IPv6
  • EDNS0 large UDP packet (4 KiB by default)
  • EDNS0-Client-Subnet (/24 for IPv4, /56 for IPv6 by default)

To use m13253/DNS-over-HTTPS, we have to first install Google's Golang. On Centos 8, we simply have to issue the following command as an admin:
dnf module -y install go-toolset

To verify that Go is installed and configured as it should, we run:
[root@natty ~]# go version
go version go1.12.12 linux/amd64

#go env

As a standard user, we'll compile m13253/DNS-over-HTTPS following these steps:
mkdir -p temp && cd temp
git clone --depth=1
cd dns-over-https
sudo make install

The binary should then be installed in the /usr/local/bin but the config file is located in the /etc/dns-over-https/ folder. The install also makes available the doh-server own systemd service file to control it in the standard way.

To undo the installation step, simply run:
sudo make uninstall

Now, to link our DoH-server to our DNS resolver listening on, we have to make just one edit to the '/etc/dns-over-https/doh-server.conf' file:
vi /etc/dns-over-https/doh-server.conf

upstream = [

If you want to completely offload all the DNS resolution step to an external public DNS server, uncomment the addresses above.

Now, that we have our configuration as we wanted, time to start and enable the server:
systemctl start doh-server
systemctl enable doh-server

If we check, our running services, we would find that our doh-server is listening on port 8053, as set in its config file.
[root@natty ~]# netstat -tulpn|grep doh-server
tcp        0      0*               LISTEN      14825/doh-server    
tcp6       0      0 ::1:8053                :::*                    LISTEN      14825/doh-server

At this point, we're done with the DOH-server part.

Apache 2.4 as the Web Server of this Stack
Given that I'm already running Apache 2.4 as my Web server, I won't use Nginx although it's the best suited for this job.

HTTPD is is running in mod_event and has many virtual hosts among them our generic '' with the following config file:

<VirtualHost *:443>
  UseCanonicalName off

  <IfModule http2_module>
    Protocols h2 http/1.1

   SSLEngine on
   Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains;"

  ProxyRequests off
  # RequestHeader set X-Forwarded-Proto "https"
  ProxyPreserveHost On
  <Location />
     ProxyPass /dns-query
     ProxyPassReverse /dns-query

With this last step, check your httpd config ( httpd -t ) and reload your web server.

Now, if you send this query to your you'll get an answer in the json format:
curl -s "" | python -m json.tool

   "Status": 0,
   "TC": false,
   "RD": true,
   "RA": true,
   "AD": false,
   "CD": false,
   "Question": [
           "name": "",
           "type": 1
   "Answer": [
           "name": "",
           "type": 1,
           "TTL": 299,
           "Expires": "Sat, 08 Feb 2020 14:07:32 UTC",
           "data": ""

If you make it till this stage successfully, Congratulation, now you can test it with Firefox :-)

Testing your Custom DoH Server with Firefox
In the about:config tab, type: network.trr; a list of directives will show. We are interested in the 'network.trr.custom_uri' and 'network.trr.bootstrapAddress'(only relevant when network.trr.mode===3), which you'll set like this:
network.trr.bootstrapAddress  IP_address_Custom_DoH

That's ALL there is to it.

Now!... Why bother you may ask?... Privacy!.. I would say!.. No one can handle your data as faithfully and diligently as you would. At least that's the assumption of this HowTo :-)
You could add part on DoT .. by tls proxy (nginx, stubby can work) or server with direct support.

People can use their own private dns in Android pi 9 and above with that.
Sincere Thanks to Shadow Hosting and post4vps  for my awesome vps4. Also a big thanks to cubedata for the great experience on my previous vps, vps8.
(02-08-2020, 06:08 PM)rudra Wrote:  You could add part on DoT .. by tls proxy (nginx, stubby can work) or server with direct support.

I've exclusively reserved this thread for DoH -as the title suggests- because of the fact that my HowTos are reports of actual implementations of projects on live VPSes. As of today, the only personal live system I've got is the one on NanoKVM platform which , as you may know, is a NAT-VPS. That means I don't have access to port 853, thus standard DoT deployment is impossible there.

It's for that reason that I didn't switch Apache Web Server (2.4.41) with Nginx. Nginx can be set to proxy both DoH and DoT traffics in the same setup. In the DoT mode, nginx-mod-stream package is needed (libnginx-mod-stream package in Debian) to
proxy plain TCP over to your DNS resolver solution
(systemd-resolved, Unbound, Bind/named, etc....) In this situation too Nginx should handles SSL termination.

(02-08-2020, 06:08 PM)rudra Wrote:  People can use their own private dns in Android pi 9 and above with that.
Indeed, a private DoT server is ideal for people with devices supporting DoT natively (like Android Pie -9), or people in my situation with DNS issues with their ISP (check Heads-Up: Firefox rolling DNS-over-HTTPS (DoH) for the background story.)

Thanks for your input @rudra!

Possibly Related Threads...
Thread Author Replies Views Last Post
Thumbs Up How to optimize Apache web server? harry_v 11 1,313 01-14-2020, 11:36 AM
Last Post: youstable
  CentOS 7 with XFCE & VNC Hidden Refuge 5 1,261 12-16-2019, 06:52 AM
Last Post: youssefbasha
  Setting up a Ubuntu-CentOS Server from scratch: Introduction LightDestory 9 596 11-12-2019, 04:52 PM
Last Post: tryp4vps
  Setting up a Ubuntu-CentOS Server from scratch: Customize your shell LightDestory 4 254 11-06-2019, 08:03 PM
Last Post: LightDestory
  Setting up a Ubuntu-CentOS Server from scratch: Firewall & UFW LightDestory 3 335 09-17-2019, 03:48 AM
Last Post: humanpuff69

Forum Jump:

Users browsing this thread: 1 Guest(s)

Sponsors: VirMach - Host4Fun - CubeData - Evolution-Host - HostDare - SSDBlaze - Abc-Hosters - Hyper Expert - Shadow Hosting - Bladenode - Hostlease

About Post4VPS

Post4VPS is a forum/destiny where you can Delploy Your Free VPSs just by the Power of Posts.

We Provide VPSs of many locations like Germany,US,Canada,France,London,etc.

We also Provide VPSs of Both Linux and Windows OS.