E-mail & DNS Hardening
Privileges Down, Control Up
Attack paths become small once privileges, segments and management channels are consistently configured.
For E-mail & DNS Hardening the basis remains the same: less implicit trust and more visibility into anomalous behavior.
This way you not only reduce the chance of incidents, but especially the scope and duration when something goes wrong.
Immediate measures (15 minutes)
Why this matters
The core of E-mail & DNS Hardening is risk reduction in practice. Technical context supports the measure selection, but implementation and assurance are central.
SPF (Sender Policy Framework)
SPF is the first mechanism that prevents attackers from sending emails on behalf of your domain. It works simply: you publish a DNS TXT record that describes which mail servers are allowed to send on behalf of your domain. The receiving mail server checks whether the sending server is in that list.
How SPF works
The sender sends an email, the receiving server performs a DNS
TXT lookup on the domain of the envelope-from, and checks whether the
IP address of the sender is in the SPF record. Result:
pass, fail, softfail, or
neutral.
example.com. IN TXT "v=spf1 <mechanisms> <qualifier>all"
Mechanisms
| Mechanism | Description | Example |
|---|---|---|
ip4 |
IPv4 address or CIDR range | ip4:192.0.2.0/24 |
ip6 |
IPv6 address or CIDR range | ip6:2001:db8::/32 |
include |
Refers to SPF record of another domain | include:_spf.google.com |
a |
A record of the domain itself | a |
mx |
MX records of the domain | mx |
exists |
DNS A lookup on specified domain | exists:%{i}._spf.example.com |
redirect |
Replaces SPF record with that of another domain | redirect=_spf.example.com |
Qualifiers
| Qualifier | Meaning | Result |
|---|---|---|
+ (default) |
Pass – sender is authorized | Accept |
- |
Hard fail – sender is not authorized | Reject |
~ |
Soft fail – sender is probably not authorized | Accept but mark |
? |
Neutral – no statement | Accept |
~all vs -all
The difference is crucial:
# Soft fail -- suspicious mail is still delivered (often to spam)
example.com. IN TXT "v=spf1 include:_spf.google.com ~all"
# Hard fail -- unauthorized mail is rejected
example.com. IN TXT "v=spf1 include:_spf.google.com -all"
Always use -all in production.
~all is intended as a temporary setting during
rollout, not as a permanent policy. Yet most organizations
run on ~all for years because "it works" and nobody ever
adjusts it.
Examples for commonly used setups
Office 365:
example.com. IN TXT "v=spf1 include:spf.protection.outlook.com -all"
Google Workspace:
example.com. IN TXT "v=spf1 include:_spf.google.com -all"
Self-hosted (Postfix on 203.0.113.25):
example.com. IN TXT "v=spf1 ip4:203.0.113.25 mx -all"
Combined (O365 + marketing tool + own server):
example.com. IN TXT "v=spf1 include:spf.protection.outlook.com include:mail.marketingtool.com ip4:203.0.113.25 -all"
Common mistakes
- Too many DNS lookups: SPF allows a maximum of 10 lookups
(
include,a,mx,exists,redirect). If you exceed this, the entire SPF check fails. Useip4/ip6where possible. - Too permissive:
v=spf1 +allauthorizes the entire world to send mail on behalf of your domain. - No SPF for subdomains: Attackers use subdomains without SPF records for phishing.
DKIM (DomainKeys Identified Mail)
DKIM adds a cryptographic signature to outgoing emails. The receiving server verifies the signature with a public key stored in DNS. This allows the recipient to establish that the message actually originates from the claimed domain and was not modified in transit.
How DKIM works
- The sending mail server calculates a hash of specific headers and the body
- The hash is signed with a private key
- The signature is added as a
DKIM-Signatureheader - The recipient retrieves the public key from DNS:
selector._domainkey.example.com - The recipient verifies the signature
DNS record
selector1._domainkey.example.com. IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqh..."
The selector is a freely chosen name (e.g.
s1, google, selector1) that allows you to
use multiple DKIM keys – useful for key rotation.
Key length
Use at least 2048 bits. RSA 1024-bit keys are
considered insecure. Some organizations are transitioning to Ed25519
(k=ed25519), but support for this is still
limited.
This produces two files: - selector1.private – the
private key (on the mail server) - selector1.txt – the DNS
TXT record (publish in DNS)
Key rotation
Rotate your DKIM keys at least annually: generate a new keypair with a new selector, publish the DNS record, wait for propagation, switch the mail server over, and remove the old record after 48 hours.
OpenDKIM configuration
# /etc/opendkim.conf
Syslog yes
Domain example.com
KeyFile /etc/opendkim/keys/selector1.private
Selector selector1
Socket inet:8891@localhost
Canonicalization relaxed/simple
Mode sv
SubDomains yes
AutoRestart yes
MinimumKeyBits 2048DMARC (Domain-based Message Authentication)
DMARC builds on SPF and DKIM. It tells receiving mail servers what to do when a message fails both SPF and DKIM, and where to send reports.
How DMARC combines SPF and DKIM
DMARC requires alignment – the domain in the
From: header must match: - The domain validated by
SPF (envelope-from), or - The domain
for which DKIM signed (d= parameter)
If neither is aligned, DMARC fails – regardless of whether SPF and DKIM individually pass.
Policy levels
| Policy | Action | Usage |
|---|---|---|
p=none |
Do nothing, only send reports | Phase 1: monitoring |
p=quarantine |
Place in spam/quarantine | Phase 2: testing |
p=reject |
Reject the message | Phase 3: production |
Rollout strategy
Roll out DMARC in phases. Do not go directly to
p=reject, unless you enjoy discovering which systems
are all sending mail on behalf of your domain.
Phase 1 – Monitoring (2-4 weeks):
_dmarc.example.com. IN TXT "v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com; ruf=mailto:dmarc-forensic@example.com; fo=1"
Phase 2 – Quarantine with percentage (2-4 weeks):
_dmarc.example.com. IN TXT "v=DMARC1; p=quarantine; pct=25; rua=mailto:dmarc-reports@example.com"
Phase 3 – Quarantine 100% (2 weeks):
_dmarc.example.com. IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@example.com"
Phase 4 – Reject (end goal):
_dmarc.example.com. IN TXT "v=DMARC1; p=reject; sp=reject; rua=mailto:dmarc-reports@example.com; ruf=mailto:dmarc-forensic@example.com; fo=1"
Reports
| Tag | Type | Description |
|---|---|---|
rua |
Aggregate | Daily XML reports with statistics on all mail traffic |
ruf |
Forensic | Detailed notifications per failed message (not all providers send these) |
fo=1 |
Failure options | Send forensic report when SPF or DKIM fails (not only when both fail) |
Subdomain policy
Do not forget subdomains. Without sp=reject a
subdomain inherits the main policy, but an attacker can use subdomains
that are not in your SPF record:
_dmarc.example.com. IN TXT "v=DMARC1; p=reject; sp=reject; rua=mailto:dmarc-reports@example.com"
DMARC reporting tools
Manually parsing XML reports is an impossible task. Use a tool such as parsedmarc (open source, run locally), dmarcian (SaaS, free tier), DMARC Analyzer, or Postmark DMARC (free weekly summaries).
DNSSEC
DNSSEC protects against DNS spoofing and cache poisoning by cryptographically signing DNS responses. Without DNSSEC an attacker can inject forged DNS responses and redirect traffic to a malicious server – including your MX records.
How DNSSEC works
| Record type | Function |
|---|---|
RRSIG |
Digital signature over a DNS record set |
DNSKEY |
Public key used to verify RRSIG records |
DS |
Hash of the DNSKEY, published in the parent zone (delegation signer) |
NSEC/NSEC3 |
Proves that a domain does not exist (authenticated denial of existence) |
The chain of trust runs from the root zone (.) via the
TLD (.nl, .com) to your domain. Each layer
contains a DS record that refers to the DNSKEY of the underlying
zone.
How to activate
At your DNS provider/registrar: Most major registrars (TransIP, Cloudflare, Route 53) support DNSSEC with a single button. Activate it and the provider automatically handles the DS record at the TLD.
Self-hosted (BIND): Generate a ZSK and KSK with
dnssec-keygen, sign the zone withdnssec-signzone, and publish the DS record at your registrar.
dnssec-keygen -a ECDSAP256SHA256 -n ZONE example.com # ZSK
dnssec-keygen -a ECDSAP256SHA256 -n ZONE -f KSK example.com # KSK
dnssec-signzone -A -3 $(head -c 1000 /dev/random | sha1sum | cut -b 1-16) \
-N INCREMENT -o example.com -t db.example.comValidation testing
# Check if DNSSEC signatures are present
dig +dnssec example.com A
# Look for the 'ad' (Authenticated Data) flag in the response
dig +dnssec +multi example.com SOA
# Extended DNSSEC validation
delv @1.1.1.1 example.com A +rtrace
# Online test
# https://dnssec-analyzer.verisignlabs.com/Note: a misconfigured DNSSEC makes your domain completely unreachable. Test thoroughly in a staging environment.
DNS filtering and sinkholing
DNS filtering blocks connections to known malware and phishing domains by manipulating the DNS response. Instead of returning the real IP address, the client receives a blocked page or an NXDOMAIN.
Response Policy Zone (RPZ)
RPZ is a standard for DNS firewalling. You load a list of malicious domains into your DNS resolver, and every query for those domains is blocked:
# /etc/bind/rpz.db
$TTL 300
@ IN SOA localhost. admin.localhost. (
2024010101 3600 600 86400 300 )
IN NS localhost.
; Block specific domain
malware-c2.evil.com CNAME . ; NXDOMAIN
*.malware-c2.evil.com CNAME . ; including subdomains
; Redirect to sinkhole
phishing.example.com A 127.0.0.1
Solutions for organizations
| Solution | Type | Suitable for |
|---|---|---|
| Pi-hole | Self-hosted (blocklists) | Small network, lab |
| NextDNS | SaaS (AI + lists) | SMB |
| Quad9 (9.9.9.9) | Free resolver (threat intel) | Everyone |
| Cloudflare Gateway | SaaS (zero trust) | Enterprise |
| Cisco Umbrella | SaaS (comprehensive) | Enterprise |
Sinkholing
With sinkholing you point malicious domains to an internal server that logs the request. Every system that tries to resolve a C2 domain appears in your logs – ideal for detecting infected hosts:
# Unbound sinkhole configuration
local-zone: "malware-c2.evil.com" redirect
local-data: "malware-c2.evil.com A 10.0.0.100"Additional DNS hardening
DoH (DNS over HTTPS) and DoT (DNS over TLS)
Standard DNS traffic is unencrypted (port 53/UDP). Anyone on the network can eavesdrop. DoH and DoT encrypt DNS queries:
| Protocol | Port | Advantage | Disadvantage |
|---|---|---|---|
| DoT | 853/TCP | Easy to filter at network level | Visible as DoT traffic |
| DoH | 443/TCP | Indistinguishable from HTTPS traffic | Difficult to monitor/block |
For internal networks DoT is often the better choice – you can still monitor it via the network layer. DoH is more difficult because it runs over port 443, the same port as all other HTTPS traffic.
# Unbound DoT configuration (as forwarder)
server:
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: 9.9.9.9@853#dns.quad9.netRestrict zone transfers (AXFR)
An open zone transfer leaks your entire DNS zone – all hostnames, IP addresses, MX records. Restrict AXFR to your secondary nameservers:
# BIND - named.conf
zone "example.com" {
type master;
file "db.example.com";
allow-transfer { 198.51.100.10; 198.51.100.11; }; # Secondary NS only
also-notify { 198.51.100.10; 198.51.100.11; };
};
Test whether your zone transfer is actually blocked:
Disable DNS recursion on authoritative servers
Authoritative nameservers should not allow recursion. Only allow recursion on your internal resolvers:
# BIND - on the authoritative server
options {
recursion no;
allow-query { any; };
};
# BIND - on the internal resolver
options {
recursion yes;
allow-recursion { 10.0.0.0/8; 172.16.0.0/12; 192.168.0.0/16; };
};
MTA-STS (Mail Transfer Agent Strict Transport Security)
MTA-STS enforces that incoming mail servers use TLS when delivering email, thereby preventing TLS downgrade attacks. Configuration requires a DNS TXT record and a policy file:
_mta-sts.example.com. IN TXT "v=STSv1; id=20240101T000000"
The policy file at
https://mta-sts.example.com/.well-known/mta-sts.txt:
version: STSv1
mode: enforce
mx: mail.example.com
max_age: 86400
DANE (DNS-based Authentication of Named Entities)
DANE uses DNSSEC to bind TLS certificates to DNS names via TLSA records. This allows you to specify which certificate a mail server must present:
_25._tcp.mail.example.com. IN TLSA 3 1 1 a]b]c]d]e]f]... (SHA-256 hash of certificate)
DANE requires a working DNSSEC configuration. Without DNSSEC, DANE has no value whatsoever.
TLS-RPT (SMTP TLS Reporting)
Similar to DMARC reports, but for TLS failures during
mail delivery. Publish a _smtp._tls TXT record with a
rua address to receive notifications when
TLS connections fail.
_smtp._tls.example.com. IN TXT "v=TLSRPTv1; rua=mailto:tls-reports@example.com"
The cynical note
Phishing has been the number-1 attack vector for ten years. Not number two. Not "one of the" vectors. Number. One. Every pentest, every red team exercise, every breach analysis – phishing is at the top. And the technology to stop it exists. SPF has been around since 2006. DKIM since 2007. DMARC since 2012. More than ten years ago.
And yet at least half of all organizations run without
a proper DMARC record. Or they have p=none and think that
they are protected. p=none literally does nothing. It is the
equivalent of a security camera that records but that nobody
watches.
The best are the organizations that buy an email security gateway for two hundred thousand euros – with sandboxing, AI detection, URL rewriting, and a dashboard that looks like NASA mission control – but forget to set up a DMARC record. That is like buying an armored door for your house but leaving the kitchen window open. The technology that is free and consists of three DNS records is too difficult. But an appliance that needs its own rack, that we do want.
The truth is simple: everything that does not have a vendor demo, does not
generate a sales lunch, and does not have a nice dashboard, does not get
implemented. SPF/DKIM/DMARC is free, so it is nobody's project.
DNSSEC is a DNS setting, so it falls between operations and security in
the no-man's land of "the other team will handle that." And meanwhile an
attacker sends emails from any IP address on behalf of your CEO, because
your domain has ~all instead of -all and
your DMARC policy is set to none. But hey, that email gateway
did detect the phish – in the demo.
Common mistakes
| # | Mistake | Risk | Solution |
|---|---|---|---|
| 1 | No SPF record | Anyone can send mail on behalf of your domain | Publish SPF with -all |
| 2 | SPF with ~all in production |
Spoofed mail is delivered (as spam) | Change to -all |
| 3 | More than 10 DNS lookups in SPF | SPF check fails completely (PermError) | Use ip4/ip6, flatten includes |
| 4 | DKIM with 1024-bit key | Key can be cracked | Generate 2048-bit (or higher) keypair |
| 5 | DMARC at p=none as end goal |
No protection, only monitoring | Roll out to p=reject |
| 6 | No DMARC record | No control over spoofing policy | Publish DMARC, start with p=none |
| 7 | Subdomains without SPF/DMARC | Attackers use subdomains for spoofing | sp=reject in DMARC, SPF per subdomain |
| 8 | Open zone transfer (AXFR) | Entire DNS zone leaks to attackers | Restrict allow-transfer |
| 9 | Recursion on authoritative DNS | DNS amplification attacks, cache poisoning | recursion no on authoritative servers |
| 10 | No DNSSEC | Vulnerable to DNS spoofing/cache poisoning | Activate DNSSEC at registrar |
| 11 | Never rotating DKIM keys | Increased risk upon key compromise | Annual key rotation |
| 12 | No MTA-STS | TLS downgrade attacks on mail traffic | Publish MTA-STS policy |
| 13 | No TLS-RPT | No visibility into TLS issues during mail delivery | Publish _smtp._tls TXT record |
| 14 | Not analyzing DMARC reports | No visibility into spoofing attempts | Use parsedmarc or SaaS tool |
| 15 | DNS over plain UDP internally | DNS queries can be eavesdropped on the network | Implement DoT for internal resolvers |
Checklist
| # | Measure | Priority | Complexity | Status |
|---|---|---|---|---|
| 1 | Publish SPF record with -all |
Critical | Low | ☐ |
| 2 | Enable DKIM (2048-bit) | Critical | Medium | ☐ |
| 3 | Roll out DMARC (none -> quarantine
-> reject) |
Critical | Medium | ☐ |
| 4 | DMARC sp=reject for subdomains |
High | Low | ☐ |
| 5 | Monitor DMARC reports | High | Medium | ☐ |
| 6 | Activate DNSSEC | High | Low-Medium | ☐ |
| 7 | Restrict zone transfers (AXFR) | High | Low | ☐ |
| 8 | Disable recursion on authoritative servers | High | Low | ☐ |
| 9 | Implement DNS filtering (RPZ/Quad9/NextDNS) | High | Medium | ☐ |
| 10 | Configure MTA-STS | Medium | Medium | ☐ |
| 11 | Publish DANE/TLSA records | Medium | High | ☐ |
| 12 | DoT/DoH for internal resolvers | Medium | Medium | ☐ |
| 13 | Enable TLS-RPT | Medium | Low | ☐ |
| 14 | DKIM key rotation procedure | Medium | Medium | ☐ |
| 15 | DNS sinkholing for C2 detection | Medium | Medium | ☐ |
| 16 | Validate SPF record (< 10 lookups) | High | Low | ☐ |
Summary
Email and DNS together form the foundation of virtually all business
communication, and thereby also the primary attack surface for
phishing, spoofing and man-in-the-middle attacks. The defense
consists of layers: SPF tells who is allowed to send mail, DKIM proves that the
message is authentic, and DMARC combines both and defines the
enforcement policy. DNSSEC protects the DNS infrastructure itself against
manipulation. Additional measures such as MTA-STS, DANE, DNS filtering and
sinkholing complete the chain. None of these technologies is
new, none is particularly complex, and most are free. The only
thing missing is the discipline to set them up, test them, and push
through to p=reject. Three DNS records separate your domain
from a phishing paradise and a well-protected mail infrastructure. The
choice is not difficult – the execution apparently is.
In the next chapter we cover MSSQL hardening: how to secure SQL Server instances against abuse of xp_cmdshell, linked servers, and credential harvesting via UNC path injection.
Further reading in the knowledge base
These articles in the portal give you more background and practical context:
- Firewalls — the bouncer that doesn't stop everything
- Network segmentation — why you shouldn't connect everything to everything
- DNS — the phone book that holds the internet together
- Logging and monitoring — the security cameras of your IT environment
- Zero Trust — trust no one, not even yourself
You need an account to access the knowledge base. Log in or register.
Related security measures
These articles provide additional context and depth: