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
  • No labels