How to use a TLS proxy with a DNS nameserver
It is of course possible to configure a TLS proxy in front of a DNS nameserver to provide DNS-over-TLS. Example configurations for nginx and haproxy are given here.
A more comprehensive setup guide using Docker has been provided by Warren Kumari: dprive-nginx-bind (Thanks Warren!)
Nameserver config
To use the following with BIND to offer a TLS service, configure BIND based on the following named.conf snippet
- This assumes BIND 9.12 which supports response padding (comment that line out if you are using an earlier version)
- The rncd and logging config is used to capture traffic volume stats - statistics can be dumped periodically with the 'rndc stats' command
options { directory "/home/sinodun"; listen-on port 9999 { 127.0.0.1; }; allow-query { 127.0.0.1; }; tcp-clients 4000; statistics-file "/tmp/bind-stats"; dnssec-enable yes; dnssec-validation auto; response-padding { any; } block-size 468; }; # Use with the following in named.conf, adjusting the allow list as needed: key "rndc-key" { algorithm hmac-md5; secret "BIGSECRET"; }; controls { inet 127.0.0.1 port 9953 allow { 127.0.0.1; } keys { "rndc-key"; }; }; logging { category default { null; }; category unmatched { null; }; };
nginx.conf
user www-data; worker_processes auto; pid /run/nginx.pid; events { worker_connections 1024; # multi_accept on; } stream { upstream dns_tcp_servers { server 127.0.0.1:9999; } server { listen 853 ssl; proxy_pass dns_tcp_servers; ssl_certificate /etc/nginx/lego/certificates/<cert>.crt; ssl_certificate_key /etc/nginx/lego/certificates/<cert>.key; ssl_protocols TLSv1.2; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_session_tickets on; ssl_session_timeout 4h; ssl_handshake_timeout 30s; } }
haproxy.cfg
global log /dev/log local0 chroot /var/lib/haproxy user haproxy group haproxy maxconn 1024 pidfile /var/run/haproxy.pid tune.ssl.default-dh-param 2048 ssl-default-bind-ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 ssl-default-bind-options force-tlsv12 # Default SSL material locations ca-base /etc/ssl/certs crt-base /etc/ssl/private defaults balance roundrobin timeout http-request 10s timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout check 10s listen dns bind 145.100.185.15:853 ssl crt /etc/haproxy/lego/certificates/<cert>.pem mode tcp server server1 127.0.0.1:9999
If you use HA proxy and have generated your certificates from Let's encrypt then you need to combing the certificate chain and key into one file using a command similar to:
cat /etc/letsencrypt/certs/000<N>_chain.pem /etc/letsencrypt/keys/<my_key>.key > /etc/letsencrypt/certs/<cert>.pem