Quite some time ago, I wrote some documentation on how to stand up a DNS-over-TLS server using a Nginx reverse streams proxy to terminate the SSL.
However, since then (in fact, back in 1.6.7) Unbound released support for directly terminating TLS connections.
This documentation details the (simple) config changes necessary to configure Unbound to service DNS over TLS (RFC 7858) queries.
You will need to have a copy of Unbound >= 1.6.7 installed (and, of course, you should really be running the latest release)
Within the config file (normally
/etc/unbound/unbound.conf) you'll need to add the following within the
interface: 0.0.0.0@853 interface: ::0@853 tls-port: 853 tls-service-key: [path to your SSL Key] tls-service-pem: [path to your SSL cert] access-control: 0.0.0.0/0 allow
You then simply need to restart
unbound and can then confirm it's listening
systemctl restart unbound netstat -lnp | grep 853
As we only want to accept TCP connections (to reduce opportunity for us to be used in a reflection attack, we firewall UDP 853
iptables -I INPUT -p udp --dport 853 -j DROP
If, like me, you acquire the SSL cert via LetsEncrypt (or will otherwise automate it's deployment), unbound must be restarted - not reloaded - when the cert/key change. This is because it reads the key before dropping privileges, so reads do not happen during a simple config reload
Unbound itself contains various config keys to allow rate limiting, however, my preference is to also limit at the firewall.
iptables -N DOT-RATE-LIMIT iptables -A DOT-RATE-LIMIT -m hashlimit --hashlimit-mode srcip --hashlimit-upto 30/sec --hashlimit-burst 20 --hashlimit-name dot_conn_rate_limit --jump ACCEPT iptables -A DOT-RATE-LIMIT -m limit --limit 1/sec --jump LOG --log-prefix "IPTables-Ratelimited: " iptables -A RATE-LIMIT -j DROP iptables -I INPUT -p tcp --dport 853 -m conntrack --ctstate NEW -j DOT-RATE-LIMIT
This will limit new connections to 30 per sec, per client IP. Even this is probably set a little high.