arrow_upward

Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to Set up Your Own DoH Server on CentOS 8
#1
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.
#  (..........)

[Resolve]
DNS=9.9.9.9
FallbackDNS=1.1.1.1 8.8.8.8
#Domains=
LLMNR=no
#MulticastDNS=no
DNSSEC=allow-downgrade
DNSOverTLS=opportunistic
#DNSOverTLS=yes
Cache=yes
#DNSStubListener=udp

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]

Global
      LLMNR setting: no
MulticastDNS setting: no
 DNSOverTLS setting: opportunistic
     DNSSEC setting: allow-downgrade
   DNSSEC supported: yes
        DNS Servers: 9.9.9.9
Fallback DNS Servers: 1.1.1.1
                     8.8.8.8
         DNSSEC NTA: 10.in-addr.arpa
                     16.172.in-addr.arpa
                     168.192.in-addr.arpa
                     17.172.in-addr.arpa
                     18.172.in-addr.arpa
                     19.172.in-addr.arpa
                     20.172.in-addr.arpa
                     21.172.in-addr.arpa
                     22.172.in-addr.arpa
                     23.172.in-addr.arpa
                     24.172.in-addr.arpa
                     25.172.in-addr.arpa
                     26.172.in-addr.arpa
                     27.172.in-addr.arpa
                     28.172.in-addr.arpa
                     29.172.in-addr.arpa
                     30.172.in-addr.arpa
                     31.172.in-addr.arpa
                     corp
                     d.f.ip6.arpa
                     home
                     internal
                     intranet
                     lan
                     local
                     private
                     test
(...............)

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

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

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;google.com. IN A

;; ANSWER SECTION:
google.com. 299 IN A 172.217.22.14

;; Query time: 66 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Sat Feb 08 13:33:49 +01 2020
;; MSG SIZE  rcvd: 55

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

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

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;google.com. IN A

;; ANSWER SECTION:
google.com. 44 IN A 172.217.22.14

;; Query time: 0 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; 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

Transactions
Current Transactions: 0
 Total Transactions: 11

Cache
 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
GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/root/go"
GOPROXY=""
GORACE=""
GOROOT="/usr/lib/golang"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/golang/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="......................."

As a standard user, we'll compile m13253/DNS-over-HTTPS following these steps:
mkdir -p temp && cd temp
git clone https://github.com/m13253/dns-over-https.git --depth=1
cd dns-over-https
make
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 127.0.0.53:53/udp, 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 = [
   #"udp:1.1.1.1:53",
   #"udp:1.0.0.1:53",
   #"udp:8.8.8.8:53",
   #"udp:8.8.4.4:53",
   "udp:127.0.0.53:53"
]
(..................................)

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 127.0.0.1:8053          0.0.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 'doh.example.com' with the following config file:

<VirtualHost *:443>
  ServerName doh.example.com
  ServerAdmin [email protected]
  UseCanonicalName off

  <IfModule http2_module>
    Protocols h2 http/1.1
  </IfModule>

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

  ProxyRequests off
  # RequestHeader set X-Forwarded-Proto "https"
  ProxyPreserveHost On
  <Location />
     SSLRequireSSL
  </Location>
     ProxyPass /dns-query http://127.0.0.1:8053/dns-query
     ProxyPassReverse /dns-query http://127.0.0.1:8053/dns-query
</VirtualHost>

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

Now, if you send this query to your doh.example.com you'll get an answer in the json format:
curl -s "https://doh.example.com/dns-query?name=google.com&type=A" | python -m json.tool

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

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.custom_uri         https://doh.example.com/dns_query
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 :-)
VirMach's Buffalo_VPS-9 Holder (Dec. 20 - July 21)
microLXC's Container Holder (july 20 - ?)
VirMach's Phoenix_VPS-9 Holder (Apr. 20 - June 20)
NanoKVM's NAT-VPS Holder (jan. 20 - ?)


Messages In This Thread
How to Set up Your Own DoH Server on CentOS 8 - by fChk - 02-08-2020, 02:39 PM


person_pin_circle Users browsing this thread: 1 Guest(s)
Sponsors: VirMach - Host4Fun - CubeData - Evolution-Host - HostDare - Hyper Expert - Shadow Hosting - Bladenode - Hostlease - RackNerd - ReadyDedis - Limitless Hosting