Skip to content
Back to Blog
Security

DNS Security: DNSSEC, DoH, and DNS Filtering

Secure your DNS infrastructure with DNSSEC signing, DNS-over-HTTPS, DNS-over-TLS, and RPZ-based DNS filtering for threat blocking.

Dec 2025
12 min read

Introduction

DNS is one of the most critical yet often overlooked attack surfaces in infrastructure. DNS cache poisoning, DNS hijacking, and DNS-based data exfiltration are real threats in production environments. DNSSEC (DNS Security Extensions) adds cryptographic signatures to DNS records, preventing spoofing. This guide covers both DNS security threats and defenses, including DNSSEC deployment.

DNS Attack Types

Cache Poisoning (Kaminsky Attack):
TEXT
1. Attacker floods resolver with forged responses for bank.com
2. Attacker guesses the Query ID (16-bit number)
3. If attacker's response arrives before real response:
   Resolver caches attacker's fake IP for bank.com
4. All clients using this resolver now go to attacker's server

Mitigations:
- Source port randomization (RFC 5452) — increases attack space
- DNSSEC validation
- DNS-over-HTTPS or DNS-over-TLS
DNS Hijacking:
TEXT
Attacker compromises the authoritative nameserver or registry account
→ Changes A record for victim.com to attacker's IP
→ All traffic goes to attacker
DNS Exfiltration:
TEXT
Malware on compromised host encodes stolen data in DNS queries:
dns-query: data-chunk1.attacker-controlled-domain.com
dns-query: data-chunk2.attacker-controlled-domain.com
...
(firewall allows DNS, doesn't inspect content)

Detection: unusually long subdomain names, high query rates

DNSSEC: How It Works

TEXT
Without DNSSEC:
Client → DNS Resolver → "A record: 203.0.113.50" (could be spoofed)

With DNSSEC:
Zone owner signs records with private key
Client validates signature with zone's public key

DNS response with DNSSEC:
A record: 203.0.113.50
RRSIG: [cryptographic signature over the A record]
Client verifies: signature is valid → trust the A record

Signing a Zone with DNSSEC

BASH
# BIND: Sign a zone
cd /var/named/

# Generate Zone Signing Key (ZSK) - rotates frequently
dnssec-keygen -a RSASHA256 -b 2048 -n ZONE company.com
# Creates: Kcompany.com.+008+12345.key and .private

# Generate Key Signing Key (KSK) - long-lived
dnssec-keygen -a RSASHA256 -b 4096 -n ZONE -f KSK company.com
# Creates: Kcompany.com.+008+67890.key and .private

# Add keys to zone file
cat Kcompany.com.*.key >> /var/named/company.com.zone

# Sign the zone
dnssec-signzone -A -3 $(head -c 1000 /dev/urandom | sha1sum | cut -b 1-16)   -N increment -o company.com -t company.com.zone

# This creates: company.com.zone.signed

# Update BIND to use signed zone
# /etc/named.conf:
zone "company.com" {
    type master;
    file "company.com.zone.signed";
    auto-dnssec maintain;
    inline-signing yes;
};

Deploying DNSSEC with PowerDNS (Modern Approach)

BASH
# PowerDNS with SQLite backend
apt install pdns-server pdns-backend-sqlite3

# Enable DNSSEC
pdnsutil secure-zone company.com

# Check signing status
pdnsutil check-zone company.com

# Get DS record to provide to registrar
pdnsutil show-zone company.com | grep DS

# Rectify zone after changes
pdnsutil rectify-zone company.com

Configuring DNSSEC Validation on Resolvers

BASH
# BIND resolver: enable DNSSEC validation
# /etc/named.conf
options {
    dnssec-enable yes;
    dnssec-validation auto;  # Uses built-in trust anchors
    dnssec-lookaside auto;
};

# Test DNSSEC validation
dig +dnssec A sigfail.verteiltesysteme.net
# If you see "ad" flag in response: authentication done
# SERVFAIL response means signature validation failed

# Cloudflare DNS (1.1.1.1) validates DNSSEC by default
dig @1.1.1.1 +dnssec +short A company.com

DNS Filtering and RPZ (Response Policy Zones)

BASH
# Block malicious domains using RPZ
# /etc/named.conf
response-policy {
    zone "rpz.company.local";  # Your blacklist zone
    zone "rpz.surbl.org";      # External threat intelligence
};

# /var/named/rpz.company.local.zone
$TTL 60
@     SOA rpz.company.local. admin.company.local. 2024010101 3600 900 86400 60

; Block known malware domains
malware-site.com.rpz.company.local CNAME .    ; Return NXDOMAIN
phishing-bank.net.rpz.company.local CNAME .

DNS-over-HTTPS and DNS-over-TLS

BASH
# Set up unbound as DoT resolver
apt install unbound

# /etc/unbound/unbound.conf
server:
  interface: 127.0.0.1
  port: 53
  verbosity: 1

  # Validate DNSSEC
  val-clean-additional: yes
  dnssec-mode: "auto"

  # Forward to CloudFlare DoT
  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

# Test DoT
kdig @1.1.1.1 +tls company.com

Monitoring DNS for Threats

PYTHON
#!/usr/bin/env python3
# dns_monitor.py - Detect DNS exfiltration attempts
import subprocess
import re
from collections import defaultdict

def analyze_dns_log(logfile):
    query_counts = defaultdict(int)
    long_subdomains = []

    with open(logfile) as f:
        for line in f:
            # Parse BIND query log format
            match = re.search(r'query: (S+) IN', line)
            if match:
                domain = match.group(1)
                parts = domain.split('.')

                # Flag unusually long subdomains (exfiltration indicator)
                if parts and len(parts[0]) > 40:
                    long_subdomains.append(domain)

                # Count queries per base domain
                if len(parts) >= 2:
                    base = '.'.join(parts[-2:])
                    query_counts[base] += 1

    # Report anomalies
    print("=== High-frequency domains ===")
    for domain, count in sorted(query_counts.items(), key=lambda x: -x[1])[:10]:
        print(f"  {count:5d} queries: {domain}")

    if long_subdomains:
        print("
=== SUSPICIOUS: Long subdomains (possible exfiltration) ===")
        for domain in long_subdomains[:20]:
            print(f"  {domain}")

if __name__ == "__main__":
    analyze_dns_log("/var/log/named/query.log")

DNS security is a layered problem: DNSSEC prevents spoofing, DNS filtering blocks known-bad domains, DoT/DoH encrypts queries in transit, and log monitoring detects abuse. Each layer addresses different threat vectors.