DNS: Transport Security (TLS)

DNS Transport Security

Nexus GSLB supports four DNS transports. UDP and TCP are always active when the DNS server starts. DNS over TLS (DoT, RFC 7858) and DNS over HTTPS (DoH, RFC 8484) are opt-in and require a TLS certificate.

License: DoT and DoH are available on all license tiers. A valid TLS certificate (manual or ACME-provisioned) is required. See Automated TLS Certificates for DNS-01 certificate provisioning.


Transport overview

Transport

Protocol

Default port

Config key

RFC

DNS/UDP

Plain UDP

5353

dns.port

RFC 1035

DNS/TCP

Plain TCP

5353

dns.port

RFC 7766

DoT

TLS-wrapped TCP

853

dns.dot

RFC 7858

DoH

HTTPS (HTTP/2)

443

dns.doh

RFC 8484

UDP and TCP share a port and are always started together. DoT and DoH each require their own port and certificate.


DNS/UDP and DNS/TCP

Standard DNS. UDP handles most queries; TCP is used automatically when a response exceeds the EDNS0 buffer size or for zone transfers (AXFR).

dns: listenAddr: "0.0.0.0" port: 53 # standard; use 5353 if running without root

No additional configuration is needed.


DNS over TLS (DoT)

Wraps the standard DNS wire format in a TLS connection on port 853 (RFC 7858). Resolvers like Quad9, Cloudflare 1.1.1.1, and Android Private DNS connect using DoT.

Configuration

dns: dot: enabled: true port: 853 # standard; omit to use the default certFile: "/etc/gslb/tls.crt" keyFile: "/etc/gslb/tls.key"

certFile and keyFile are required when enabled: true. TLS 1.2 is the minimum version; TLS 1.3 is preferred.

Testing DoT

# kdig (from knot-dnsutils)kdig -d @<nexus-server-ip> +tls-ca +tls-host=<hostname> gslb.cc SOA# or with opensslopenssl s_client -connect <nexus-server-ip>:853 -servername <hostname>

DNS over HTTPS (DoH)

Serves DNS queries over HTTPS at a configurable path (default /dns-query) per RFC 8484. Supports both GET (with base64url-encoded ?dns= parameter) and POST (with application/dns-message body). HTTP/2 is used automatically when the client supports it.

Configuration

dns: doh: enabled: true port: 443 # standard; omit to use the default certFile: "/etc/gslb/tls.crt" keyFile: "/etc/gslb/tls.key" path: "/dns-query" # optional; defaults to /dns-query

certFile and keyFile are required when enabled: true.

Testing DoH

# GET (base64url-encoded query)curl -s "https://<nexus-server-ip>/dns-query?dns=$(echo -n '\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x04gslb\x02cc\x00\x00\x01\x00\x01' | base64 -w0 | tr '+/' '-_' | tr -d '=')" \ -H "Accept: application/dns-message" --output - | hexdump -C# POST (recommended)curl -s -X POST "https://<nexus-server>/dns-query" \ -H "Content-Type: application/dns-message" \ --data-binary @query.bin \ -o response.bin

A simpler test with dog (a user-friendly DNS client):

dog gslb.cc SOA --https @https://<nexus-server>/dns-query

Browser / resolver configuration

To point Firefox or a system resolver at a Nexus DoH endpoint:

  • Firefox: Preferences → Network Settings → DNS over HTTPS → Custom → https://<nexus-server>/dns-query

  • Android: Private DNS → <nexus-server-hostname> (uses DoT; DoH is browser-level only)

  • Windows 11: Network adapter → DNS → "DNS over HTTPS" → https://<nexus-server>/dns-query


Sharing port 443 with the API or WebUI

The DoH listener is a separate http.Server instance from the API server. If both DoH and the API server need port 443, run the API on a different port and put a reverse proxy (Caddy/nginx) in front to route /dns-query to the DoH port.

Caddy example:

nexus.example.com {
# Route DoH queries to the DoH listener
handle /dns-query {
reverse_proxy 127.0.0.1:5443
}
# Everything else goes to the API/WebUI
handle {
reverse_proxy 127.0.0.1:8080
}
}

In this setup, configure DoH on a non-standard port (port: 5443) and bind it to 127.0.0.1.


Mutual TLS (mTLS) for DoT/DoH

Nexus does not currently enforce client certificate authentication on DoT or DoH endpoints. For intranet deployments that require mTLS, place a TLS-terminating proxy (Caddy with tls { client_auth { mode require_and_verify } }) in front of the DoT/DoH ports.


Cache-Control on DoH responses

Nexus sets Cache-Control: max-age=<min-ttl> on DoH responses, derived from the minimum TTL across all answer records. Responses with no answer records receive Cache-Control: no-cache, no-store. This allows RFC 8484-compliant clients to cache responses without a separate caching proxy.


Listener status

The cluster status page in the WebUI shows which DNS transports are active on each node, along with the ports they are listening on. The same information is available via the API:

curl https://nexus-api.example.com/api/v1/cluster/status \ -H "Authorization: Bearer $GSLB_API_KEY" | jq .dns

Response:

{ "udp": true, "tcp": true, "dot": true, "doh": false, "udpPort": 53, "tcpPort": 53, "dotPort": 853}

Related


Was this article helpful?