DNS over HTTPS servers

Related articles
DNS over HTTPS
This article or section needs expansion.
Reason:
While this article currently focuses on
python-doh-proxy
AUR
for the DoH proxy with
bind
for the DNS server and
stunnel
for the DoT implementation, the general setup is the same whichever software you choose to use. Stubs have been added and it is my hope that the other package maintainers will contribute for their preferred software. Additionally, the flow of this article is a bit confusing and I will be providing some clean-up (beyond the initial commit) to describe the various configurations in more detail. (Discuss in
Talk:DNS over HTTPS servers
)
DNS, since its inception, has been unencrypted on UDP/53, and later TCP/53, making it susceptible to snooping attacks. For additional information on the available protocols that can be used to address this vulnerability, see
Domain name resolution#Privacy and security
. This article covers two of the three available protocols for DNS servers with the necessary proxy configuration to provide both DNS over HTTPS (DoH) and DNS over TLS (DoT). Multiple DoH utilities are available in the AUR including
coredns
AUR
,
dns-over-https
,
doh-proxy
AUR
, and
python-doh-proxy
AUR
. Which of the available solutions is appropriate, depends on the needs of your network.
coredns
AUR
provides both a caching, non-authoritative DNS server, and DoH services (citation needed).
dns-over-https
,
doh-proxy
AUR
, and
python-doh-proxy
AUR
all provide an HTTP listener for proxying behind your existing HTTPS server, and a stub resolver to forward regular queries on UDP/53 to a secure DNS server. Additionally, both
doh-proxy
AUR
and
python-doh-proxy
AUR
provide a standalone HTTPS/2 server.
DoH server/proxy software configuration
coreDNS
This article or section is a candidate for merging with
CoreDNS#Configuration
.
Notes:
CoreDNS has a dedicated article. (Discuss in
Talk:DNS over HTTPS servers
)
Install
the
coredns
AUR
package.
You can use coreDNS as DoH/DoT/gRPC DNS server and/or DoT proxy. Default configuration file should be located at
/etc/coredns/Corefile
.
The example of simple configuration file looks like this:
/etc/coredns/Corefile
protocol://domain:port
{
    forward
domain
forward_to
tls_servername
domain_of_dot_server
tls
cert_path
key_path
}
First string is listener, you can use next protocols:
dns://
for plain DNS protocol,
http://
for DNS over HTTPS,
tls://
for DNS over TLS and
grpc://
for gRPC (see
[1]
). If you leave protocol empty (e.g. example.com:53), dns:// will be choosen as default. The
domain
is for matching queried domains, you can use specific one (e.g. dns: //example.com: 53) or use
.
(e.g. dns: //.: 53) to match all domains. And by
:port
you can set listening port, you can leave it empty and will be chosen 53 port.
forward
string is for where DNS query will be forward. Use
.
for
domain
to match all domains. In
forward_to
set upstream DNS server where to send queries, you can specify
tls://
protocol for DoT server. If you using upstream DoT server, you need to set
tls_servername
for TLS negotiation.
tls
string mandatory if you use DoH, DoT or gRPC protocols. Put here certificate and private key paths in given order.
Example of configuration simple DoT proxy listening 53 port and using Cloudflare DoT server
/etc/coredns/Corefile
. {
    forward . tls://1.1.1.1 {
        tls_servername cloudflare-dns.com 
    }
}
Also, you can use several instances and forward plugins:
/etc/coredns/Corefile
https://.:443 {
    forward . 127.0.0.1 {
    forward example1.com 8.8.8.8
    tls cert.pem key.pem
}

tls://example2.com:853 {
    tls cert.pem key.pem
    forward . tls://9.9.9.9 {
        tls_servername dns.quad9.net
    }
}
Start/enable
the
coredns.service
unit.
dns-over-https
This article or section is a candidate for merging with
DNS-over-HTTPS
.
Notes:
DNS-over-HTTPS has a dedicated article. (Discuss in
Talk:DNS over HTTPS servers
)
At first, install
dns-over-https
and after setting will not forget to enable and start needed service.
Stub resolver
You can start using it right after install with default settings. Defaults ports for listening is 53 and 5380, if one of them is already binded, it will be ignored.
Start/enable
doh-client.service
.
Configuration file locate at
/etc/dns-over-https/doh-client.conf
. You can change desired ports at section
listen
. There are many included third-parted DoH servers in configuration file, you need just uncomment one you needed or write unspecified. You can use several resolvers as well. One of them will be chosen randomly for each request. To force dns-over-https use resolvers in the required order set
upstream_selector
to
weighted_round_robin
or
lvs_weighted_round_robin
and change weight value at resolvers in use.
DoH proxy
Configuration file for use as doh server locate at
/etc/dns-over-https/doh-server.conf
. At
upstream
section can set desired upstream resolver and its protocol for use. You can use dns-over-https as standalone service or together with HTTPS services like nginx or apache.
For standalone use you need to set port to 443 and specify proper cert and key:
/etc/dns-over-https/doh-server.conf
listen = [
    "127.0.0.1:443",
]
...
cert = ""
key = ""
If you want use HTTP server for caching or using along with other HTTPS services leave empty cert and key strings in
doh-server.conf
and use next examples for configuration desired HTTP server. Note that there using default dns-over-https port.
nginx:
/etc/nginx/nginx/site-available/doh
server {
  listen       443 ssl http2 default_server;
  listen       [::]:443 ssl http2 default_server;
  server_name  MY_SERVER_NAME;

  ssl_certificate /path/to/your/server/certificates/fullchain.pem;
  ssl_certificate_key /path/to/your/server/certificates/privkey.pem;
  location /dns-query {
    proxy_pass       http://localhost:8053/dns-query; 
    proxy_set_header Host      $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
}
caddy:
/etc/caddy/Caddyfile
MY_SERVER_NAME {
        reverse_proxy * localhost:8053
        tls my@email.address
        try_files {path} {path}/index.php /index.php?{query}
}
apache:
/etc/httpd/conf/vhosts/doh.conf
<VirtualHost *:443>
    ServerName MY_SERVER_NAME
    Protocols h2 http/1.1
    ProxyPass /dns-query http://[::1]:8053/dns-query
    ProxyPassReverse /dns-query http://[::1]:8053/dns-query
</VirtualHost>
After setting up,
start/enable
doh-server.service
.
doh-proxy
This article or section needs expansion.
Reason:
please use the first argument of the template to provide a brief explanation.
(Discuss in
Talk:DNS over HTTPS servers
)
python-doh-proxy
This article or section is being considered for removal.
Reason:
The
project
is not maintained and has been archived since 2021-08-03. (Discuss in
Talk:DNS over HTTPS servers
)
Install
python-doh-proxy
AUR
.
Stub resolver
If you intend to provide encrypted queries to your local network for legacy applications, configure the stub resolver:
/etc/conf.d/doh-stub
LISTENPORT=54
ADDR=127.0.0.1
DOMAIN=mydomain.tld
NS=127.0.0.1
PORT=443
If you do not have a way to provide a secure forward DNS lookoup to your real DNS server, you should configure both DOMAIN and NS to use one of the upstream providers (CloudFlare, OpenDNS, etc., instead of localhost). If you only need to provide lookups to localhost, this is fine. If you need to provide them for the entire network, then you could listen on 53 directly if you do not have a local caching or authoritative DNS server - you would also want to use the real IP address instead of the loopback adapter in this case.
DoH proxy
If you have an existing HTTP server and wish to proxy DNS lookups with it, setup the HTTP proxy to listen on port 8080:
/etc/conf.d/doh-httpproxy
NS=127.0.0.1
PORT=8080
ADDR=127.0.0.1
Optionally, you can utilize either the doh-proxy service or an upstream DoH provider to forward queries.
DoH proxy
If you do not have an existing http server, you can configure the HTTPS/2 listener:
/etc/conf.d/doh-proxy
NS=127.0.0.1
UPSTREAMPORT=54
ADDR=127.0.0.1
LISTENPORT=443
CERT=/etc/ssl/private/fullchain.pem
KEY=/etc/ssl/private/privkey.pem
Again, adjust as necessary, but be certain that the upstream server has a way to perform secure queries, or you will be creating a loop.
Standalone DNS server configuration
BIND
This article or section is a candidate for merging with
BIND#Configuration
.
Notes:
BIND has a dedicated article. (Discuss in
Talk:DNS over HTTPS servers
)
BIND 9.18 natively supports serving both DNS over HTTPS and DNS over TLS. See
BIND#Configuration
for details.
As resolver, with TLS proxy
Typical: If using ISC bind as the current DNS provider, and you will be providing both forwarding services for legacy clients and DoH to modern clients, you will likely want to configure named to forward all non-local queries to your stub resolver, comment out any forwarding lines to forward to the stub resolver (omit forward only if you would like to fall back to roots):
/etc/named.conf
options {
...
    //forwarders { 8.8.8.8; 8.8.4.4; };
    forwarders { 127.0.0.1 port 54; };
    forward only;
...
};
...
This article or section is out of date.
Reason:
BIND supports forwarding using DNS over TLS. (Discuss in
Talk:DNS over HTTPS servers#stunnel
)
If you want to forward to an external TLS proxy (via
stunnel
), do the same but use only TCP/54 (see stunnel configuration below):
/etc/named.conf
options {
...
    //forwarders { 8.8.8.8; 8.8.4.4; };
    forwarders { 127.0.0.1 port 54; };
    forward only;
...
};
...
server 127.0.0.1 {
    tcp-only yes;
};
...
Optional: If using ISC bind as the current DNS provider, and you will be providing both forwarding services for legacy clients and DoH to modern clients, you might want to configure named to listen on an alternate port, for example TCP|UDP/54, rather than the default of 53 so that your stub resolver will listen on the standard port. Comment out any existing 'listen' lines and add the following (omit the v6 line if not needed):
/etc/named.conf
...
    //listen-on { any; };
    listen-on port 54 { any; };
    listen-on-v6 port 54 { any; };
...
Unbound
This article or section is a candidate for merging with
Unbound#Configuration
.
Notes:
Unbound has a dedicated article. (Discuss in
Talk:DNS over HTTPS servers
)
You can easily set up DoT server by adding to your configuration file port 853 to listening and specify certificate and key paths:
/etc/unbound/unbound.conf
server:
...
interface: 127.0.0.1@853
tls-service-pem: /etc/unbound/public.pem
tls-service-key: /etc/unbound/private.pem
...
DoH server setup is same as DoT, but needed port is 443:
/etc/unbound/unbound.conf
server:
...
interface: 127.0.0.1@443
tls-service-pem: /etc/unbound/public.pem
tls-service-key: /etc/unbound/private.pem
...
Web server configuration
Apache httpd proxy configuration
Configure a proxy in your primary httpd.conf or appropriate vhost listening on 443:
/etc/httpd/conf/vhosts/
yourhost
.conf
...
    ProxyPass /dns-query http://[127.0.0.1]:8080/dns-query
    ProxyPassReverse /dns-query http://[127.0.0.1]:8080/dns-query
...
nginx proxy configuration
DoT Proxy
With Nginx stream module you can setup proxy to upstream DNS. Note that you can use local dns as well as third parties.
/etc/nginx/nginx.conf
...
stream {
    upstream dns {
        zone dns 64k;
        server 8.8.8.8:53;
    }

    server {
        listen 853 ssl;
        ssl_certificate /etc/nginx/ssl/certs/public.pem;
        ssl_certificate_key /etc/nginx/ssl/private/private.pem;
        proxy_pass dns;
    }
}
...
DoH Proxy
For DoH implementation you need for use additional NJS scripts. You need to get it
from this GitHub's page
, put it to
/etc/nginx/njs.d/
and be sure package
nginx-mod-njs
is installed.
At first you need to setup stream service, which will be get DNS request from nginx's HTTP/2 service, process it with
js_filter
to find DNS packets and pass it to upstream DNS server.
/etc/nginx/nginx.conf
...
stream {
    upstream dns {
        zone dns 64k;
        server 1.1.1.1:53;

    server {
        listen 127.0.0.1:8053;
        js_filter doh_filter_request;
        proxy_ssl on;
        proxy_pass dns;
        }
}
...
Then, setup HTTP/2 service to listen DNS requests at URI /dns-query and relay them to stream service. Note that to a need change certificates to valid
/etc/nginx/nginx.conf
...
upstream dohloop {
   zone dohloop 64k;
   server 127.0.0.1:8053;
}

server {
    listen 443 ssl http2;
    ssl_certificate /etc/nginx/ssl/certs/public.pem;
    ssl_certificate_key /etc/nginx/ssl/private/private.pem;

    location /dns-query {
        proxy_http_version 1.0;
        proxy_pass http://dohloop;
   }
}
...
You can use both DoT and DoH services at same time, caching and multiple upstream DNS. For more examples see
these configuration files
DNS over TLS configuration via stunnel
This article or section is a candidate for merging with
stunnel#DNS over TLS
.
Notes:
Some info is provided on the main
stunnel
page. DNS over TLS is out of scope of this page. (Discuss in
Talk:DNS over HTTPS servers
)
Configure stunnel to listen on TCP/853 for TLS connections, and forward to your local DNS provider:
/etc/stunnel/conf.d/DoT.conf
[dns]
accept = 853
connect = 127.0.0.1:53
cert = /etc/ssl/private/fullchain.pem
key = /etc/ssl/private/privkey.pem
Configure stunnel to listen on TCP/54 and forward to an upstream secure provider:
/etc/stunnel/conf.d/DoT-Remote.conf
[dnsovertls]
client = yes
accept = 54
connect = 10.10.10.1:853
verifyChain = yes
CAPath = /etc/ssl/certs
checkHost = <your_host_name>
DNS over HTTPS server Docker images
See
https://hub.docker.com/r/satishweb/doh-server
.