DMARC (Domain-based Message Authentication, Reporting en Conformance) instructs receiving servers hoe to handle emails die fail SPF/DKIM checks, protecting domain against spoofing en waarbij visibility in email authentication failures.
Aanbeveling
IMPLEMENT
Risico zonder
High
Risk Score
8/10
Implementatie
5u (tech: 3u)
Van toepassing op:
β M365 β Email Security
SPF en DKIM alone zijn insufficient - receiving servers don't know wat to do bij authentication failures. DMARC provides: policy (quarantine/reject failed emails), reporting (receive daily reports of authentication failures), visibility (who's spoofing your domain?). Zonder DMARC: domain spoofing attacks succeed, geen zichtbaarheid in spoofing attempts, receiving servers Sta toe spoofed emails.
PowerShell Modules Vereist
Primary API: DNS Management Connection:N/A Required Modules:
Implementatie
DMARC DNS record configuration: _dmarc.yourdomain.com TXT record met policy. aanbevolen settings: p=quarantine (start) β p=reject (after monitoring), rua=mailto:dmarc@yourdomain.com (aggregate reports), ruf=mailto:dmarc@yourdomain.com (forensic reports), pct=100 (apply to 100% emails). Phased approach: monitoren β Quarantine β Reject.
FASE 1 - monitor: Add DNS TXT record: v=DMARC1; p=none; rua=mailto:dmarc@company.com; pct=100
monitor aggregate reports 30 days, identify legitimate vs spoofing sources
FASE 2 - Quarantine: Change to p=quarantine; (suspicious emails go to spam)
monitor voor false positives (legitimate emails quarantined)
FASE 3 - Reject: Change to p=reject; (spoofed emails completely blocked)
Gebruik PowerShell-script dmarc-records.ps1 (functie Invoke-Monitoring) β Controleren.
Remediatie
Gebruik PowerShell-script dmarc-records.ps1 (functie Invoke-Remediation) β Herstellen.
Compliance & Frameworks
CIS M365: Control 2.1.4 (L1) - Zorg ervoor dat DMARC geconfigureerd
BIO: 13.02 - BIO: Email authentication
ISO 27001:2022: A.13.2.1 - Email security
NIS2: Artikel - Email authentication
Automation
Gebruik het onderstaande PowerShell script om deze security control te monitoren en te implementeren. Het script bevat functies voor zowel monitoring (-Monitoring) als remediation (-Remediation).
PowerShell
<#
.SYNOPSIS
DMARC Records Configuration
.DESCRIPTION
Ensures DMARC (Domain-based Message Authentication, Reporting & Conformance) records exist.
DMARC prevents email spoofing and provides reports on authentication failures.
.NOTES
Filename: dmarc-records.ps1
Author: Nederlandse Baseline voor Veilige Cloud
.EXAMPLE
.\dmarc-records.ps1 -Monitoring
Check DMARC configuration for all domains
#>#Requires -Version 5.1#Requires -Modules ExchangeOnlineManagement, DnsClient
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[switch]$Monitoring,
[Parameter(Mandatory = $false)]
[switch]$Remediation,
[switch]$Revert,
[switch]$WhatIf
)
$ErrorActionPreference = 'Stop'
Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host "DMARC Records Configuration" -ForegroundColor Cyan
Write-Host "========================================`n" -ForegroundColor Cyan
function Invoke-Monitoring {
function Invoke-Revert {
Write-Host "`nReverting configuration..." -ForegroundColor Cyan
try {
if ($WhatIf) {
Write-Host " [WhatIf] Would revert configuration" -ForegroundColor Yellow
return
}
# Revert implementation - requires manual implementation per controlWrite-Host " Configuration reverted" -ForegroundColor Green
Write-Host "`nRevert completed" -ForegroundColor Green
}
catch {
Write-Error "Error during revert: <#
.SYNOPSIS
DMARC Records Configuration
.DESCRIPTION
Ensures DMARC (Domain-based Message Authentication, Reporting & Conformance) records exist.
DMARC prevents email spoofing and provides reports on authentication failures.
.NOTES
Filename: dmarc-records.ps1
Author: Nederlandse Baseline voor Veilige Cloud
.EXAMPLE
.\dmarc-records.ps1 -Monitoring
Check DMARC configuration for all domains
#>#Requires -Version 5.1#Requires -Modules ExchangeOnlineManagement, DnsClient
[CmdletBinding()]
param(
[Parameter(Mandatory=$false)]
[switch]$Monitoring,
[Parameter(Mandatory=$false)]
[switch]$Remediation,
[switch]$Revert,
[switch]$WhatIf
)
$ErrorActionPreference = 'Stop'
Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host "DMARC Records Configuration" -ForegroundColor Cyan
Write-Host "========================================`n" -ForegroundColor Cyan
function Invoke-Monitoring {
try {
Write-Host "Connecting to Exchange Online..." -ForegroundColor Gray
Connect-ExchangeOnline -ShowBanner:$false -ErrorAction Stop
Write-Host "Getting accepted domains..." -ForegroundColor Gray
$domains = Get-AcceptedDomain | Where-Object { $_.DomainType -ne 'InternalRelay' }
$result = @{
isCompliant = $true
totalDomains = $domains.Count
withDMARC = 0
withoutDMARC = 0
domainDetails = @()
}
Write-Host "Checking DMARC records for $($domains.Count) domains...`n" -ForegroundColor Cyan
foreach ($domain in $domains) {
try {
# Check for DMARC record (_dmarc.domain.com)$dmarcDomain = "_dmarc.$($domain.DomainName)"
$dmarcRecord = Resolve-DnsName -Name $dmarcDomain -Type TXT -ErrorAction SilentlyContinue
if ($dmarcRecord) {
$dmarcText = $dmarcRecord | Where-Object { $_.Strings -like "v=DMARC1*" } | Select-Object -First 1if ($dmarcText) {
$result.withDMARC++
# Parse DMARC policy$policy = if ($dmarcText.Strings -match 'p=(reject|quarantine|none)') { $matches[1] } else { "unknown" }
Write-Host " [OK] $($domain.DomainName): DMARC CONFIGURED" -ForegroundColor Green
Write-Host " Policy: $policy" -ForegroundColor Cyan
Write-Host " Record: $($dmarcText.Strings)" -ForegroundColor Gray
$result.domainDetails += @{
Domain = $domain.DomainName
HasDMARC = $true
Policy = $policy
}
}
else {
$result.withoutDMARC++
$result.isCompliant = $falseWrite-Host " [FAIL] $($domain.DomainName): NO DMARC RECORD" -ForegroundColor Red
}
}
else {
$result.withoutDMARC++
$result.isCompliant = $falseWrite-Host " [FAIL] $($domain.DomainName): NO DMARC RECORD" -ForegroundColor Red
}
}
catch {
Write-Host " β οΈ $($domain.DomainName): Could not check DNS" -ForegroundColor Yellow
}
}
Write-Host "`n Total domains: $($result.totalDomains)" -ForegroundColor Cyan
Write-Host " With DMARC: $($result.withDMARC)" -ForegroundColor Green
Write-Host " Without DMARC: $($result.withoutDMARC)" -ForegroundColor $(
if ($result.withoutDMARC -gt 0) { "Red" } else { "Green" }
)
if ($result.isCompliant) {
Write-Host "`n[OK] COMPLIANT - All domains have DMARC" -ForegroundColor Green
exit 0
}
else {
Write-Host "`n[FAIL] NON-COMPLIANT - Configure DMARC for all domains" -ForegroundColor Red
exit 1
}
}
catch {
Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red
exit 2
}
}
function Invoke-Remediation {
try {
Write-Host "β οΈ DMARC records must be configured in DNS" -ForegroundColor Yellow
Write-Host "`nSteps to configure DMARC:" -ForegroundColor Cyan
Write-Host " 1. For each domain, create a TXT record:" -ForegroundColor Gray
Write-Host " Name: _dmarc.yourdomain.com" -ForegroundColor Gray
Write-Host " Value: v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com" -ForegroundColor Gray
Write-Host "`n 2. DMARC Policy Options:" -ForegroundColor Cyan
Write-Host " β’ p=none - Monitor only (start here)" -ForegroundColor Gray
Write-Host " β’ p=quarantine - Suspicious mail to spam" -ForegroundColor Yellow
Write-Host " β’ p=reject - Block suspicious mail (strongest)" -ForegroundColor Green
Write-Host "`n 3. Additional recommended tags:" -ForegroundColor Cyan
Write-Host " β’ rua=mailto:... - Aggregate reports email" -ForegroundColor Gray
Write-Host " β’ ruf=mailto:... - Forensic reports email" -ForegroundColor Gray
Write-Host " β’ pct=100 - Apply to 100% of mail" -ForegroundColor Gray
Write-Host " β’ sp=quarantine - Subdomain policy" -ForegroundColor Gray
Write-Host "`n 4. Example DMARC record:" -ForegroundColor Cyan
Write-Host " v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@yourdomain.com; pct=100; sp=quarantine" -ForegroundColor Gray
Write-Host "`n 5. Verify with:" -ForegroundColor Cyan
Write-Host " Resolve-DnsName -Name _dmarc.yourdomain.com -Type TXT" -ForegroundColor Gray
Write-Host "`nπ Start with p=none, monitor reports, then move to p=quarantine, then p=reject" -ForegroundColor Cyan
exit 0
}
catch {
Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red
exit 2
}
}
try {
if ($Monitoring) {
Invoke-Monitoring
}
elseif ($Remediation) {
Invoke-Remediation
}
else {
Write-Host "Usage:" -ForegroundColor Yellow
Write-Host " -Monitoring Check DMARC records for all domains" -ForegroundColor Gray
Write-Host " -Remediation Show configuration steps" -ForegroundColor Gray
}
}
catch {
throw
}
finally {
Write-Host "`n========================================`n" -ForegroundColor Cyan
}
"
throw
}
}
try {
Write-Host "Connecting to Exchange Online..." -ForegroundColor Gray
Connect-ExchangeOnline -ShowBanner:$false -ErrorAction Stop
Write-Host "Getting accepted domains..." -ForegroundColor Gray
$domains = Get-AcceptedDomain | Where-Object { $_.DomainType -ne 'InternalRelay' }
$result = @{
isCompliant = $true
totalDomains = $domains.Count
withDMARC = 0
withoutDMARC = 0
domainDetails = @()
}
Write-Host "Checking DMARC records for $($domains.Count) domains...`n" -ForegroundColor Cyan
foreach ($domain in $domains) {
function Invoke-Revert {
Write-Host "`nReverting configuration..." -ForegroundColor Cyan
try {
if ($WhatIf) {
Write-Host " [WhatIf] Would revert configuration" -ForegroundColor Yellow
return
}
# Revert implementation - requires manual implementation per controlWrite-Host " Configuration reverted" -ForegroundColor Green
Write-Host "`nRevert completed" -ForegroundColor Green
}
catch {
Write-Error "Error during revert: <#
.SYNOPSIS
DMARC Records Configuration
.DESCRIPTION
Ensures DMARC (Domain-based Message Authentication, Reporting & Conformance) records exist.
DMARC prevents email spoofing and provides reports on authentication failures.
.NOTES
Filename: dmarc-records.ps1
Author: Nederlandse Baseline voor Veilige Cloud
.EXAMPLE
.\dmarc-records.ps1 -Monitoring
Check DMARC configuration for all domains
#>#Requires -Version 5.1#Requires -Modules ExchangeOnlineManagement, DnsClient
[CmdletBinding()]
param(
[Parameter(Mandatory=$false)]
[switch]$Monitoring,
[Parameter(Mandatory=$false)]
[switch]$Remediation,
[switch]$Revert,
[switch]$WhatIf
)
$ErrorActionPreference = 'Stop'
Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host "DMARC Records Configuration" -ForegroundColor Cyan
Write-Host "========================================`n" -ForegroundColor Cyan
function Invoke-Monitoring {
try {
Write-Host "Connecting to Exchange Online..." -ForegroundColor Gray
Connect-ExchangeOnline -ShowBanner:$false -ErrorAction Stop
Write-Host "Getting accepted domains..." -ForegroundColor Gray
$domains = Get-AcceptedDomain | Where-Object { $_.DomainType -ne 'InternalRelay' }
$result = @{
isCompliant = $true
totalDomains = $domains.Count
withDMARC = 0
withoutDMARC = 0
domainDetails = @()
}
Write-Host "Checking DMARC records for $($domains.Count) domains...`n" -ForegroundColor Cyan
foreach ($domain in $domains) {
try {
# Check for DMARC record (_dmarc.domain.com)$dmarcDomain = "_dmarc.$($domain.DomainName)"
$dmarcRecord = Resolve-DnsName -Name $dmarcDomain -Type TXT -ErrorAction SilentlyContinue
if ($dmarcRecord) {
$dmarcText = $dmarcRecord | Where-Object { $_.Strings -like "v=DMARC1*" } | Select-Object -First 1if ($dmarcText) {
$result.withDMARC++
# Parse DMARC policy$policy = if ($dmarcText.Strings -match 'p=(reject|quarantine|none)') { $matches[1] } else { "unknown" }
Write-Host " [OK] $($domain.DomainName): DMARC CONFIGURED" -ForegroundColor Green
Write-Host " Policy: $policy" -ForegroundColor Cyan
Write-Host " Record: $($dmarcText.Strings)" -ForegroundColor Gray
$result.domainDetails += @{
Domain = $domain.DomainName
HasDMARC = $true
Policy = $policy
}
}
else {
$result.withoutDMARC++
$result.isCompliant = $falseWrite-Host " [FAIL] $($domain.DomainName): NO DMARC RECORD" -ForegroundColor Red
}
}
else {
$result.withoutDMARC++
$result.isCompliant = $falseWrite-Host " [FAIL] $($domain.DomainName): NO DMARC RECORD" -ForegroundColor Red
}
}
catch {
Write-Host " β οΈ $($domain.DomainName): Could not check DNS" -ForegroundColor Yellow
}
}
Write-Host "`n Total domains: $($result.totalDomains)" -ForegroundColor Cyan
Write-Host " With DMARC: $($result.withDMARC)" -ForegroundColor Green
Write-Host " Without DMARC: $($result.withoutDMARC)" -ForegroundColor $(
if ($result.withoutDMARC -gt 0) { "Red" } else { "Green" }
)
if ($result.isCompliant) {
Write-Host "`n[OK] COMPLIANT - All domains have DMARC" -ForegroundColor Green
exit 0
}
else {
Write-Host "`n[FAIL] NON-COMPLIANT - Configure DMARC for all domains" -ForegroundColor Red
exit 1
}
}
catch {
Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red
exit 2
}
}
function Invoke-Remediation {
try {
Write-Host "β οΈ DMARC records must be configured in DNS" -ForegroundColor Yellow
Write-Host "`nSteps to configure DMARC:" -ForegroundColor Cyan
Write-Host " 1. For each domain, create a TXT record:" -ForegroundColor Gray
Write-Host " Name: _dmarc.yourdomain.com" -ForegroundColor Gray
Write-Host " Value: v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com" -ForegroundColor Gray
Write-Host "`n 2. DMARC Policy Options:" -ForegroundColor Cyan
Write-Host " β’ p=none - Monitor only (start here)" -ForegroundColor Gray
Write-Host " β’ p=quarantine - Suspicious mail to spam" -ForegroundColor Yellow
Write-Host " β’ p=reject - Block suspicious mail (strongest)" -ForegroundColor Green
Write-Host "`n 3. Additional recommended tags:" -ForegroundColor Cyan
Write-Host " β’ rua=mailto:... - Aggregate reports email" -ForegroundColor Gray
Write-Host " β’ ruf=mailto:... - Forensic reports email" -ForegroundColor Gray
Write-Host " β’ pct=100 - Apply to 100% of mail" -ForegroundColor Gray
Write-Host " β’ sp=quarantine - Subdomain policy" -ForegroundColor Gray
Write-Host "`n 4. Example DMARC record:" -ForegroundColor Cyan
Write-Host " v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@yourdomain.com; pct=100; sp=quarantine" -ForegroundColor Gray
Write-Host "`n 5. Verify with:" -ForegroundColor Cyan
Write-Host " Resolve-DnsName -Name _dmarc.yourdomain.com -Type TXT" -ForegroundColor Gray
Write-Host "`nπ Start with p=none, monitor reports, then move to p=quarantine, then p=reject" -ForegroundColor Cyan
exit 0
}
catch {
Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red
exit 2
}
}
try {
if ($Monitoring) {
Invoke-Monitoring
}
elseif ($Remediation) {
Invoke-Remediation
}
else {
Write-Host "Usage:" -ForegroundColor Yellow
Write-Host " -Monitoring Check DMARC records for all domains" -ForegroundColor Gray
Write-Host " -Remediation Show configuration steps" -ForegroundColor Gray
}
}
catch {
throw
}
finally {
Write-Host "`n========================================`n" -ForegroundColor Cyan
}
"
throw
}
}
try {
# Check for DMARC record (_dmarc.domain.com)$dmarcDomain = "_dmarc.$($domain.DomainName)"
$dmarcRecord = Resolve-DnsName -Name $dmarcDomain -Type TXT -ErrorAction SilentlyContinue
if ($dmarcRecord) {
$dmarcText = $dmarcRecord | Where-Object { $_.Strings -like "v=DMARC1*" } | Select-Object -First 1if ($dmarcText) {
$result.withDMARC++
# Parse DMARC policy$policy = if ($dmarcText.Strings -match 'p=(reject|quarantine|none)') { $matches[1] } else { "unknown" }
Write-Host " [OK] $($domain.DomainName): DMARC CONFIGURED" -ForegroundColor Green
Write-Host " Policy: $policy" -ForegroundColor Cyan
Write-Host " Record: $($dmarcText.Strings)" -ForegroundColor Gray
$result.domainDetails += @{
Domain = $domain.DomainName
HasDMARC = $true
Policy = $policy
}
}
else {
$result.withoutDMARC++
$result.isCompliant = $falseWrite-Host " [FAIL] $($domain.DomainName): NO DMARC RECORD" -ForegroundColor Red
}
}
else {
$result.withoutDMARC++
$result.isCompliant = $falseWrite-Host " [FAIL] $($domain.DomainName): NO DMARC RECORD" -ForegroundColor Red
}
}
catch {
Write-Host " β οΈ $($domain.DomainName): Could not check DNS" -ForegroundColor Yellow
}
}
Write-Host "`n Total domains: $($result.totalDomains)" -ForegroundColor Cyan
Write-Host " With DMARC: $($result.withDMARC)" -ForegroundColor Green
Write-Host " Without DMARC: $($result.withoutDMARC)" -ForegroundColor $(
if ($result.withoutDMARC -gt 0) { "Red" } else { "Green" }
)
if ($result.isCompliant) {
Write-Host "`n[OK] COMPLIANT - All domains have DMARC" -ForegroundColor Green
exit 0
}
else {
Write-Host "`n[FAIL] NON-COMPLIANT - Configure DMARC for all domains" -ForegroundColor Red
exit 1
}
}
catch {
Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red
exit 2
}
}
function Invoke-Remediation {
function Invoke-Revert {
Write-Host "`nReverting configuration..." -ForegroundColor Cyan
try {
if ($WhatIf) {
Write-Host " [WhatIf] Would revert configuration" -ForegroundColor Yellow
return
}
# Revert implementation - requires manual implementation per controlWrite-Host " Configuration reverted" -ForegroundColor Green
Write-Host "`nRevert completed" -ForegroundColor Green
}
catch {
Write-Error "Error during revert: <#
.SYNOPSIS
DMARC Records Configuration
.DESCRIPTION
Ensures DMARC (Domain-based Message Authentication, Reporting & Conformance) records exist.
DMARC prevents email spoofing and provides reports on authentication failures.
.NOTES
Filename: dmarc-records.ps1
Author: Nederlandse Baseline voor Veilige Cloud
.EXAMPLE
.\dmarc-records.ps1 -Monitoring
Check DMARC configuration for all domains
#>#Requires -Version 5.1#Requires -Modules ExchangeOnlineManagement, DnsClient
[CmdletBinding()]
param(
[Parameter(Mandatory=$false)]
[switch]$Monitoring,
[Parameter(Mandatory=$false)]
[switch]$Remediation,
[switch]$Revert,
[switch]$WhatIf
)
$ErrorActionPreference = 'Stop'
Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host "DMARC Records Configuration" -ForegroundColor Cyan
Write-Host "========================================`n" -ForegroundColor Cyan
function Invoke-Monitoring {
try {
Write-Host "Connecting to Exchange Online..." -ForegroundColor Gray
Connect-ExchangeOnline -ShowBanner:$false -ErrorAction Stop
Write-Host "Getting accepted domains..." -ForegroundColor Gray
$domains = Get-AcceptedDomain | Where-Object { $_.DomainType -ne 'InternalRelay' }
$result = @{
isCompliant = $true
totalDomains = $domains.Count
withDMARC = 0
withoutDMARC = 0
domainDetails = @()
}
Write-Host "Checking DMARC records for $($domains.Count) domains...`n" -ForegroundColor Cyan
foreach ($domain in $domains) {
try {
# Check for DMARC record (_dmarc.domain.com)$dmarcDomain = "_dmarc.$($domain.DomainName)"
$dmarcRecord = Resolve-DnsName -Name $dmarcDomain -Type TXT -ErrorAction SilentlyContinue
if ($dmarcRecord) {
$dmarcText = $dmarcRecord | Where-Object { $_.Strings -like "v=DMARC1*" } | Select-Object -First 1if ($dmarcText) {
$result.withDMARC++
# Parse DMARC policy$policy = if ($dmarcText.Strings -match 'p=(reject|quarantine|none)') { $matches[1] } else { "unknown" }
Write-Host " [OK] $($domain.DomainName): DMARC CONFIGURED" -ForegroundColor Green
Write-Host " Policy: $policy" -ForegroundColor Cyan
Write-Host " Record: $($dmarcText.Strings)" -ForegroundColor Gray
$result.domainDetails += @{
Domain = $domain.DomainName
HasDMARC = $true
Policy = $policy
}
}
else {
$result.withoutDMARC++
$result.isCompliant = $falseWrite-Host " [FAIL] $($domain.DomainName): NO DMARC RECORD" -ForegroundColor Red
}
}
else {
$result.withoutDMARC++
$result.isCompliant = $falseWrite-Host " [FAIL] $($domain.DomainName): NO DMARC RECORD" -ForegroundColor Red
}
}
catch {
Write-Host " β οΈ $($domain.DomainName): Could not check DNS" -ForegroundColor Yellow
}
}
Write-Host "`n Total domains: $($result.totalDomains)" -ForegroundColor Cyan
Write-Host " With DMARC: $($result.withDMARC)" -ForegroundColor Green
Write-Host " Without DMARC: $($result.withoutDMARC)" -ForegroundColor $(
if ($result.withoutDMARC -gt 0) { "Red" } else { "Green" }
)
if ($result.isCompliant) {
Write-Host "`n[OK] COMPLIANT - All domains have DMARC" -ForegroundColor Green
exit 0
}
else {
Write-Host "`n[FAIL] NON-COMPLIANT - Configure DMARC for all domains" -ForegroundColor Red
exit 1
}
}
catch {
Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red
exit 2
}
}
function Invoke-Remediation {
try {
Write-Host "β οΈ DMARC records must be configured in DNS" -ForegroundColor Yellow
Write-Host "`nSteps to configure DMARC:" -ForegroundColor Cyan
Write-Host " 1. For each domain, create a TXT record:" -ForegroundColor Gray
Write-Host " Name: _dmarc.yourdomain.com" -ForegroundColor Gray
Write-Host " Value: v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com" -ForegroundColor Gray
Write-Host "`n 2. DMARC Policy Options:" -ForegroundColor Cyan
Write-Host " β’ p=none - Monitor only (start here)" -ForegroundColor Gray
Write-Host " β’ p=quarantine - Suspicious mail to spam" -ForegroundColor Yellow
Write-Host " β’ p=reject - Block suspicious mail (strongest)" -ForegroundColor Green
Write-Host "`n 3. Additional recommended tags:" -ForegroundColor Cyan
Write-Host " β’ rua=mailto:... - Aggregate reports email" -ForegroundColor Gray
Write-Host " β’ ruf=mailto:... - Forensic reports email" -ForegroundColor Gray
Write-Host " β’ pct=100 - Apply to 100% of mail" -ForegroundColor Gray
Write-Host " β’ sp=quarantine - Subdomain policy" -ForegroundColor Gray
Write-Host "`n 4. Example DMARC record:" -ForegroundColor Cyan
Write-Host " v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@yourdomain.com; pct=100; sp=quarantine" -ForegroundColor Gray
Write-Host "`n 5. Verify with:" -ForegroundColor Cyan
Write-Host " Resolve-DnsName -Name _dmarc.yourdomain.com -Type TXT" -ForegroundColor Gray
Write-Host "`nπ Start with p=none, monitor reports, then move to p=quarantine, then p=reject" -ForegroundColor Cyan
exit 0
}
catch {
Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red
exit 2
}
}
try {
if ($Monitoring) {
Invoke-Monitoring
}
elseif ($Remediation) {
Invoke-Remediation
}
else {
Write-Host "Usage:" -ForegroundColor Yellow
Write-Host " -Monitoring Check DMARC records for all domains" -ForegroundColor Gray
Write-Host " -Remediation Show configuration steps" -ForegroundColor Gray
}
}
catch {
throw
}
finally {
Write-Host "`n========================================`n" -ForegroundColor Cyan
}
"
throw
}
}
try {
Write-Host "β οΈ DMARC records must be configured in DNS" -ForegroundColor Yellow
Write-Host "`nSteps to configure DMARC:" -ForegroundColor Cyan
Write-Host " 1. For each domain, create a TXT record:" -ForegroundColor Gray
Write-Host " Name: _dmarc.yourdomain.com" -ForegroundColor Gray
Write-Host " Value: v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com" -ForegroundColor Gray
Write-Host "`n 2. DMARC Policy Options:" -ForegroundColor Cyan
Write-Host " β’ p=none - Monitor only (start here)" -ForegroundColor Gray
Write-Host " β’ p=quarantine - Suspicious mail to spam" -ForegroundColor Yellow
Write-Host " β’ p=reject - Block suspicious mail (strongest)" -ForegroundColor Green
Write-Host "`n 3. Additional recommended tags:" -ForegroundColor Cyan
Write-Host " β’ rua=mailto:... - Aggregate reports email" -ForegroundColor Gray
Write-Host " β’ ruf=mailto:... - Forensic reports email" -ForegroundColor Gray
Write-Host " β’ pct=100 - Apply to 100% of mail" -ForegroundColor Gray
Write-Host " β’ sp=quarantine - Subdomain policy" -ForegroundColor Gray
Write-Host "`n 4. Example DMARC record:" -ForegroundColor Cyan
Write-Host " v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@yourdomain.com; pct=100; sp=quarantine" -ForegroundColor Gray
Write-Host "`n 5. Verify with:" -ForegroundColor Cyan
Write-Host " Resolve-DnsName -Name _dmarc.yourdomain.com -Type TXT" -ForegroundColor Gray
Write-Host "`nπ Start with p=none, monitor reports, then move to p=quarantine, then p=reject" -ForegroundColor Cyan
exit 0
}
catch {
Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red
exit 2
}
}
function Invoke-Revert {
Write-Host "`nReverting configuration..." -ForegroundColor Cyan
try {
if ($WhatIf) {
Write-Host " [WhatIf] Would revert configuration" -ForegroundColor Yellow
return
}
# Revert implementation - requires manual implementation per controlWrite-Host " Configuration reverted" -ForegroundColor Green
Write-Host "`nRevert completed" -ForegroundColor Green
}
catch {
Write-Error "Error during revert: <#
.SYNOPSIS
DMARC Records Configuration
.DESCRIPTION
Ensures DMARC (Domain-based Message Authentication, Reporting & Conformance) records exist.
DMARC prevents email spoofing and provides reports on authentication failures.
.NOTES
Filename: dmarc-records.ps1
Author: Nederlandse Baseline voor Veilige Cloud
.EXAMPLE
.\dmarc-records.ps1 -Monitoring
Check DMARC configuration for all domains
#>#Requires -Version 5.1#Requires -Modules ExchangeOnlineManagement, DnsClient
[CmdletBinding()]
param(
[Parameter(Mandatory=$false)]
[switch]$Monitoring,
[Parameter(Mandatory=$false)]
[switch]$Remediation,
[switch]$Revert,
[switch]$WhatIf
)
$ErrorActionPreference = 'Stop'
Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host "DMARC Records Configuration" -ForegroundColor Cyan
Write-Host "========================================`n" -ForegroundColor Cyan
function Invoke-Monitoring {
try {
Write-Host "Connecting to Exchange Online..." -ForegroundColor Gray
Connect-ExchangeOnline -ShowBanner:$false -ErrorAction Stop
Write-Host "Getting accepted domains..." -ForegroundColor Gray
$domains = Get-AcceptedDomain | Where-Object { $_.DomainType -ne 'InternalRelay' }
$result = @{
isCompliant = $true
totalDomains = $domains.Count
withDMARC = 0
withoutDMARC = 0
domainDetails = @()
}
Write-Host "Checking DMARC records for $($domains.Count) domains...`n" -ForegroundColor Cyan
foreach ($domain in $domains) {
try {
# Check for DMARC record (_dmarc.domain.com)$dmarcDomain = "_dmarc.$($domain.DomainName)"
$dmarcRecord = Resolve-DnsName -Name $dmarcDomain -Type TXT -ErrorAction SilentlyContinue
if ($dmarcRecord) {
$dmarcText = $dmarcRecord | Where-Object { $_.Strings -like "v=DMARC1*" } | Select-Object -First 1if ($dmarcText) {
$result.withDMARC++
# Parse DMARC policy$policy = if ($dmarcText.Strings -match 'p=(reject|quarantine|none)') { $matches[1] } else { "unknown" }
Write-Host " [OK] $($domain.DomainName): DMARC CONFIGURED" -ForegroundColor Green
Write-Host " Policy: $policy" -ForegroundColor Cyan
Write-Host " Record: $($dmarcText.Strings)" -ForegroundColor Gray
$result.domainDetails += @{
Domain = $domain.DomainName
HasDMARC = $true
Policy = $policy
}
}
else {
$result.withoutDMARC++
$result.isCompliant = $falseWrite-Host " [FAIL] $($domain.DomainName): NO DMARC RECORD" -ForegroundColor Red
}
}
else {
$result.withoutDMARC++
$result.isCompliant = $falseWrite-Host " [FAIL] $($domain.DomainName): NO DMARC RECORD" -ForegroundColor Red
}
}
catch {
Write-Host " β οΈ $($domain.DomainName): Could not check DNS" -ForegroundColor Yellow
}
}
Write-Host "`n Total domains: $($result.totalDomains)" -ForegroundColor Cyan
Write-Host " With DMARC: $($result.withDMARC)" -ForegroundColor Green
Write-Host " Without DMARC: $($result.withoutDMARC)" -ForegroundColor $(
if ($result.withoutDMARC -gt 0) { "Red" } else { "Green" }
)
if ($result.isCompliant) {
Write-Host "`n[OK] COMPLIANT - All domains have DMARC" -ForegroundColor Green
exit 0
}
else {
Write-Host "`n[FAIL] NON-COMPLIANT - Configure DMARC for all domains" -ForegroundColor Red
exit 1
}
}
catch {
Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red
exit 2
}
}
function Invoke-Remediation {
try {
Write-Host "β οΈ DMARC records must be configured in DNS" -ForegroundColor Yellow
Write-Host "`nSteps to configure DMARC:" -ForegroundColor Cyan
Write-Host " 1. For each domain, create a TXT record:" -ForegroundColor Gray
Write-Host " Name: _dmarc.yourdomain.com" -ForegroundColor Gray
Write-Host " Value: v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com" -ForegroundColor Gray
Write-Host "`n 2. DMARC Policy Options:" -ForegroundColor Cyan
Write-Host " β’ p=none - Monitor only (start here)" -ForegroundColor Gray
Write-Host " β’ p=quarantine - Suspicious mail to spam" -ForegroundColor Yellow
Write-Host " β’ p=reject - Block suspicious mail (strongest)" -ForegroundColor Green
Write-Host "`n 3. Additional recommended tags:" -ForegroundColor Cyan
Write-Host " β’ rua=mailto:... - Aggregate reports email" -ForegroundColor Gray
Write-Host " β’ ruf=mailto:... - Forensic reports email" -ForegroundColor Gray
Write-Host " β’ pct=100 - Apply to 100% of mail" -ForegroundColor Gray
Write-Host " β’ sp=quarantine - Subdomain policy" -ForegroundColor Gray
Write-Host "`n 4. Example DMARC record:" -ForegroundColor Cyan
Write-Host " v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@yourdomain.com; pct=100; sp=quarantine" -ForegroundColor Gray
Write-Host "`n 5. Verify with:" -ForegroundColor Cyan
Write-Host " Resolve-DnsName -Name _dmarc.yourdomain.com -Type TXT" -ForegroundColor Gray
Write-Host "`nπ Start with p=none, monitor reports, then move to p=quarantine, then p=reject" -ForegroundColor Cyan
exit 0
}
catch {
Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red
exit 2
}
}
try {
if ($Monitoring) {
Invoke-Monitoring
}
elseif ($Remediation) {
Invoke-Remediation
}
else {
Write-Host "Usage:" -ForegroundColor Yellow
Write-Host " -Monitoring Check DMARC records for all domains" -ForegroundColor Gray
Write-Host " -Remediation Show configuration steps" -ForegroundColor Gray
}
}
catch {
throw
}
finally {
Write-Host "`n========================================`n" -ForegroundColor Cyan
}
"
throw
}
}
try {
if ($Monitoring) {
Invoke-Monitoring
}
elseif ($Remediation) {
Invoke-Remediation
}
else {
Write-Host "Usage:" -ForegroundColor Yellow
Write-Host " -Monitoring Check DMARC records for all domains" -ForegroundColor Gray
Write-Host " -Remediation Show configuration steps" -ForegroundColor Gray
}
}
catch {
throw
}
finally {
Write-Host "`n========================================`n" -ForegroundColor Cyan
}
Risico zonder implementatie
Risico zonder implementatie
High: High - Domain spoofing succeeds: attackers Verzend phishing van @yourcompany.com, BEC attacks impersonating executives, damage to domain reputation, geen zichtbaarheid in spoofing attempts. DMARC p=reject Blokkeert domain spoofing completely.
Management Samenvatting
DMARC policy: start p=none (monitor) β p=quarantine β p=reject. Blokkeert domain spoofing, biedt spoofing visibility via reports. vereist SPF+DKIM. Voldoet aan CIS 2.1.4 L1, BIO 13.02. Setup: 3u phased rollout.