Skip to content

Last updated: 2026-05-15

Unbound DNS over TLS/HTTPS Configuration Guide

This guide provides recommended DNS over TLS (DoT) and DNS over HTTPS (DoH) settings for Unbound recursive resolver. Encrypting DNS traffic prevents eavesdropping and tampering with DNS queries and responses.

Prerequisites

  • Unbound 1.18 or later (for DoH support; 1.7.3+ for DoT)
  • OpenSSL 1.1.1 or later
  • SSL certificates (for serving DoT/DoH to clients)

RHEL/CentOS: Install with dnf install unbound.

Debian/Ubuntu: Install with apt install unbound.

Certificate Setup

Place your certificates in a dedicated directory:

mkdir -p /etc/unbound/ssl
chmod 750 /etc/unbound/ssl
chown unbound:unbound /etc/unbound/ssl

cp server.crt /etc/unbound/ssl/server-cert.pem
cp server.key /etc/unbound/ssl/server-key.pem
cp ca.crt /etc/unbound/ssl/ca.pem

chmod 640 /etc/unbound/ssl/*.pem
chown unbound:unbound /etc/unbound/ssl/*.pem

Serving DNS over TLS (DoT)

Configure Unbound to accept DoT connections from clients on port 853.

DoT Server Configuration

Add to unbound.conf:

server:
    # Standard DNS listener
    interface: 0.0.0.0@53
    interface: ::0@53

    # DNS over TLS listener
    interface: 0.0.0.0@853
    interface: ::0@853

    # TLS certificate and key
    tls-service-key: /etc/unbound/ssl/server-key.pem
    tls-service-pem: /etc/unbound/ssl/server-cert.pem

    # TLS protocol settings
    tls-ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305"
    tls-ciphersuites: "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256"

    # Require TLS on port 853
    tls-port: 853

Serving DNS over HTTPS (DoH)

Unbound 1.18+ can natively serve DNS over HTTPS:

server:
    # DNS over HTTPS listener
    interface: 0.0.0.0@443
    interface: ::0@443

    tls-service-key: /etc/unbound/ssl/server-key.pem
    tls-service-pem: /etc/unbound/ssl/server-cert.pem

    tls-ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305"
    tls-ciphersuites: "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256"

    https-port: 443
    http-endpoint: "/dns-query"

Forwarding over TLS (Upstream DoT)

Configure Unbound to forward queries to an upstream resolver over TLS. This encrypts the connection between Unbound and the upstream resolver:

server:
    # Enable TLS for upstream connections
    tls-cert-bundle: /etc/ssl/certs/ca-certificates.crt

forward-zone:
    name: "."
    forward-tls-upstream: yes
    forward-addr: 1.1.1.1@853#cloudflare-dns.com
    forward-addr: 1.0.0.1@853#cloudflare-dns.com
    forward-addr: 8.8.8.8@853#dns.google
    forward-addr: 8.8.4.4@853#dns.google

Configuration Explained

  • forward-tls-upstream: yes -- Sends queries to upstream servers over TLS instead of plaintext UDP/TCP.
  • forward-addr -- Upstream resolver address with the TLS port (853) and authentication name after #.
  • tls-cert-bundle -- Path to the system CA bundle used to verify upstream server certificates.

RHEL/CentOS: The CA bundle path is /etc/pki/tls/certs/ca-bundle.crt.

Debian/Ubuntu: The CA bundle path is /etc/ssl/certs/ca-certificates.crt.

DNSSEC Validation

Unbound supports DNSSEC validation by default. Ensure it is enabled alongside DoT/DoH:

server:
    # DNSSEC validation
    auto-trust-anchor-file: /var/lib/unbound/root.key
    val-clean-additional: yes

Complete Configuration

server:
    # Network
    interface: 0.0.0.0@53
    interface: ::0@53
    interface: 0.0.0.0@853
    interface: ::0@853

    # Access control
    access-control: 127.0.0.0/8 allow
    access-control: 10.0.0.0/8 allow
    access-control: ::1/128 allow

    # TLS certificates
    tls-service-key: /etc/unbound/ssl/server-key.pem
    tls-service-pem: /etc/unbound/ssl/server-cert.pem

    # TLS protocol settings
    tls-ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305"
    tls-ciphersuites: "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256"
    tls-port: 853

    # System CA bundle for upstream TLS verification
    tls-cert-bundle: /etc/ssl/certs/ca-certificates.crt

    # DNSSEC
    auto-trust-anchor-file: /var/lib/unbound/root.key
    val-clean-additional: yes

# Forward all queries upstream over TLS
forward-zone:
    name: "."
    forward-tls-upstream: yes
    forward-addr: 1.1.1.1@853#cloudflare-dns.com
    forward-addr: 1.0.0.1@853#cloudflare-dns.com
    forward-addr: 8.8.8.8@853#dns.google
    forward-addr: 8.8.4.4@853#dns.google

Client Configuration

systemd-resolved

Configure systemd-resolved to use your Unbound server over DoT:

[Resolve]
DNS=192.168.1.1
DNSOverTLS=yes

Android / iOS

Modern Android (9+) and iOS (14+) support DoT and DoH natively. Configure your Unbound server's hostname as the private DNS provider in the device settings.

Security Notes

The cipher suite and protocol configuration in this guide addresses the following known TLS vulnerabilities:

  • POODLE (CVE-2014-3566, 2014): SSL 3.0 is disabled. TLS_FALLBACK_SCSV was added in OpenSSL 1.0.1j / 1.0.2 (October 2014); SSL 3.0 disabled by default in OpenSSL 1.1.0 (August 2016).
  • BEAST (CVE-2011-3389, 2011): Mitigated by recommending TLS 1.2 as the minimum; AEAD-only ciphers eliminate the CBC padding oracle.
  • CRIME (CVE-2012-4929, 2012): TLS compression is off by default in OpenSSL 1.1.0+; do not enable it.
  • Lucky13 (2013): AEAD-only cipher list eliminates CBC padding timing side-channels entirely.
  • FREAK (CVE-2015-0204, 2015): EXPORT-grade ciphers are excluded. Removed from OpenSSL 1.1.0 (August 2016).
  • LOGJAM (CVE-2015-4000, 2015): Short-key DHE is excluded; only ECDHE key exchange is recommended.
  • Sweet32 (CVE-2016-2183, 2016): 3DES is excluded from the cipher string. Disabled by default in OpenSSL 3.0 (September 2021).
  • ROBOT (CVE-2017-13099, 2017): Static RSA key exchange is excluded; only ECDHE is recommended. Fixed in OpenSSL 1.0.2m / 1.0.1v (November 2017).
  • Downgrade attacks: TLS_FALLBACK_SCSV prevents protocol version rollback.

The following are not addressable through TLS configuration alone:

  • Heartbleed (CVE-2014-0160, 2014): A memory disclosure bug in OpenSSL 1.0.1 through 1.0.1f. Fixed in OpenSSL 1.0.1g (April 7, 2014). Addressed by patching OpenSSL, not by TLS configuration.
  • BREACH (CVE-2013-3587, 2013): Not applicable. BREACH targets HTTP-level response compression; DNS-over-TLS does not involve HTTP. DNS-over-HTTPS uses HTTP but typically without compressible secret data.
  • DROWN (CVE-2016-0800, 2016): Requires SSLv2 to be enabled on any server sharing the same private key. Ensure SSLv2 is disabled on all services that use the same certificate and key pair.

Verification

Check the configuration for errors:

unbound-checkconf /etc/unbound/unbound.conf

Test the DoT listener:

openssl s_client -connect dns.example.com:853

Test DNS resolution over TLS using kdig (from knot-dnsutils):

kdig @dns.example.com +tls example.com A

Test DNS resolution over standard port to verify Unbound is running:

dig @dns.example.com example.com A

Check Unbound logs:

journalctl -u unbound | grep -i tls

Confirm the DoT certificate and chain externally with the Mr.DNS SSL/TLS Certificate Check (port 853).


Related Guides

View all DNS guides →

Configured TLS? Now Monitor It.

Generator Labs alerts you before certificates expire, get revoked, or fail chain validation — across HTTPS, SMTPS, IMAPS, LDAPS, and more.

Certificate Monitoring →