DNSSEC¶
DNS Security Extensions (DNSSEC) provides cryptographic authentication of DNS data.
Implementation Status¶
| Feature | Status | Notes |
|---|---|---|
| DNSSEC Validation | ✅ Implemented | Validate upstream responses via dnssec.validation |
| CRD Schema (Phase 1) | ✅ Implemented | DNSSECConfig, DNSSECSigningConfig, DNSSECKeySource types |
| Policy Configuration (Phase 2) | ✅ Implemented | dnssec-policy blocks generated in named.conf |
| Key Source Configuration (Phase 3) | ✅ Implemented | Secret-backed and auto-generated keys |
| Zone Signing Configuration (Phase 4) | ✅ Implemented | Per-zone dnssecPolicy field, inline signing via bindcar |
| DS Record Status Reporting (Phase 5) | 🚧 Planned | Status struct exists; extraction logic not yet implemented |
| Integration Tests (Phase 6) | 🚧 Planned | Unit tests exist; end-to-end suite pending |
DNSSEC Validation¶
When DNSSEC validation is enabled, BIND9 verifies cryptographic signatures on DNS responses from upstream nameservers. This protects against cache poisoning, man-in-the-middle tampering, and spoofed DNS responses.
Requirements: - Valid DNSSEC trust anchors (managed automatically by BIND9 via RFC 5011) - Network connectivity to root DNS servers - Accurate system time (NTP synchronization)
Configuration¶
Configure validation in the Bind9Cluster global configuration:
apiVersion: bindy.firestoned.io/v1beta1
kind: Bind9Cluster
metadata:
name: production-dns
namespace: bindy-system
spec:
global:
dnssec:
validation: true # Enable DNSSEC validation of upstream responses
Or override per-instance in Bind9Instance:
apiVersion: bindy.firestoned.io/v1beta1
kind: Bind9Instance
metadata:
name: primary-dns
namespace: bindy-system
spec:
clusterRef: production-dns
config:
dnssec:
validation: true
Verification¶
SERVICE_IP=$(kubectl get svc -n bindy-system production-dns-primary -o jsonpath='{.spec.clusterIP}')
# Query a DNSSEC-signed domain - look for 'ad' (authentic data) flag
dig @$SERVICE_IP cloudflare.com +dnssec
# flags: qr rd ra ad; QUERY: 1, ANSWER: 1, ...
# ^^-- successful DNSSEC validation
# Query a domain with broken DNSSEC - should FAIL with SERVFAIL
dig @$SERVICE_IP dnssec-failed.org
Troubleshooting Validation¶
# Check BIND9 logs for DNSSEC errors
kubectl logs -n bindy-system -l app.kubernetes.io/component=bind9 | grep -i dnssec
# Common errors:
# "broken trust chain" - Missing or invalid DS records in parent zone
# "no valid signature found" - Expired or missing RRSIG records
# "validation failed" - Signature verification failed
# Query without validation for debugging
dig @$SERVICE_IP example.com +cd # +cd = checking disabled
# Verify NTP sync - DNSSEC signatures have validity periods
kubectl exec -n bindy-system -l app.kubernetes.io/component=bind9 -- date
DNSSEC Zone Signing¶
Bindy supports declarative DNSSEC zone signing using BIND9's modern dnssec-policy mechanism. Configuration is via Bind9Cluster (global policy) and optionally overridden per DNSZone.
How It Works¶
- The operator generates a
dnssec-policyblock innamed.conffrom your CRD config - BIND9 handles key generation, signing, and automatic key rotation
- Each
DNSZonecan specify a policy viaspec.dnssecPolicy(or inherit the cluster default)
Cluster-Level Signing Configuration¶
apiVersion: bindy.firestoned.io/v1beta1
kind: Bind9Cluster
metadata:
name: production-dns
namespace: bindy-system
spec:
global:
dnssec:
validation: true
signing:
enabled: true
policy: "default" # Policy name referenced by zones
algorithm: "ECDSAP256SHA256" # Recommended: ECDSA P-256
kskLifetime: "365d" # Key Signing Key lifetime
zskLifetime: "90d" # Zone Signing Key lifetime
nsec3: true # Use NSEC3 (privacy-preserving)
nsec3Iterations: 0 # Per RFC 9276 recommendation
# Key management
autoGenerate: true # BIND9 generates keys automatically
exportToSecret: true # Back up generated keys to a Secret
This generates a dnssec-policy block in named.conf similar to:
dnssec-policy "default" {
keys {
ksk lifetime 365d algorithm ECDSAP256SHA256;
zsk lifetime 90d algorithm ECDSAP256SHA256;
};
nsec3param iterations 0 optout no salt-length 16;
signatures-refresh 5d;
signatures-validity 30d;
signatures-validity-dnskey 30d;
zone-propagation-delay 300;
parent-propagation-delay 3600;
max-zone-ttl 86400;
};
Per-Zone Policy Override¶
Each DNSZone inherits the cluster's DNSSEC signing policy by default. Override it with spec.dnssecPolicy:
apiVersion: bindy.firestoned.io/v1beta1
kind: DNSZone
metadata:
name: example-com
namespace: bindy-system
spec:
zoneName: example.com
clusterRef: production-dns
soaRecord:
primaryNs: ns1.example.com.
adminEmail: admin.example.com.
serial: 2026012801
refresh: 3600
retry: 600
expire: 604800
negativeTtl: 86400
ttl: 3600
# Override cluster default or disable signing for this zone:
# dnssecPolicy: "high-security" # Use a different named policy
# dnssecPolicy: "none" # Disable signing for this zone
When dnssecPolicy is set, inline-signing yes; is automatically added to the zone configuration.
Key Source Options¶
Option 1: Auto-Generated Keys (Recommended for Development)¶
signing:
enabled: true
policy: "default"
autoGenerate: true
exportToSecret: true # Back up keys to a Kubernetes Secret
BIND9 generates KSK and ZSK keys automatically. With exportToSecret: true, the operator exports the generated keys to a Secret for backup and recovery.
Option 2: User-Supplied Keys (Recommended for Production)¶
signing:
enabled: true
policy: "default"
keysFrom:
secretRef:
name: my-dnssec-keys
namespace: bindy-system
Supply pre-generated keys via a Kubernetes Secret. The Secret is mounted read-only at /var/cache/bind/keys. This is the recommended production approach as it gives full control over key material.
Algorithm Selection¶
| Algorithm | OID | Recommended Use |
|---|---|---|
ECDSAP256SHA256 |
13 | Default — modern, fast, small keys |
ECDSAP384SHA384 |
14 | Higher security margin, slightly larger |
RSASHA256 |
8 | Legacy compatibility only |
Use ECDSAP256SHA256 unless you have a specific compatibility requirement. Per RFC 8624, ECDSA algorithms are MUST implement for modern resolvers.
NSEC vs NSEC3¶
| Setting | Privacy | Notes |
|---|---|---|
nsec3: false |
❌ Zone enumerable | Simpler, lower overhead |
nsec3: true |
✅ Hashed names | Recommended; use nsec3Iterations: 0 per RFC 9276 |
Completing the Chain of Trust¶
After zones are signed, publish DS records in the parent zone to complete the DNSSEC chain of trust. The DS record links the child zone's KSK to the parent zone's trust.
Note: DS record extraction (Phase 5) is not yet automated. Extract DS records manually:
# Get DS records from signed zone
kubectl exec -n bindy-system -l app.kubernetes.io/component=bind9 -- \
dig @localhost example.com DNSKEY | dnssec-dsfromkey -f - example.com
# Or extract from BIND9's key directory
kubectl exec -n bindy-system -l app.kubernetes.io/component=bind9 -- \
cat /var/cache/bind/keys/dsset-example.com.
Publish the output DS records at your domain registrar or parent zone operator.
DNSSEC Record Types Reference¶
| Record | Purpose |
|---|---|
| DNSKEY | Public signing keys (KSK and ZSK) |
| RRSIG | Cryptographic signatures for each RRset |
| NSEC | Proof of non-existence (zone-enumerable) |
| NSEC3 | Privacy-preserving proof of non-existence (hashed names) |
| DS | Delegation signer — published in the parent zone |
Best Practices¶
- Test in staging first — Enable signing on non-critical zones before production
- Use NSEC3 — Set
nsec3: trueandnsec3Iterations: 0per RFC 9276 - Use ECDSAP256SHA256 — Modern, compact, widely supported
- Back up keys — Set
exportToSecret: trueor usekeysFrom.secretReffor user-managed keys - Publish DS records promptly — Signed zones without a parent DS record are signed but not validated by resolvers
- Monitor for expiry — Alert on RRSIG validity windows; BIND9 auto-renews but monitor for issues
- Plan DS rollovers — KSK rollovers require coordinating DS record updates with the parent zone
Reference¶
RFCs¶
- RFC 4033 - DNS Security Introduction and Requirements
- RFC 4034 - Resource Records for DNSSEC
- RFC 4035 - Protocol Modifications for DNSSEC
- RFC 5155 - NSEC3 (Hashed Authenticated Denial)
- RFC 8624 - Algorithm Requirements and Usage
- RFC 9276 - NSEC3 Parameter Guidance
BIND9 Documentation¶
External Tools¶
- DNSViz - DNSSEC chain visualization and debugging
- Verisign DNSSEC Analyzer - Full chain validation
- DNSSEC Debugger - Interactive DNSSEC testing