PowerShell, SPF, DKIM and DMARC ..oh my

It has been a few months since I have been here it appears, and as part of my personal goals for the year I have vowed to contribute more to the community.

With that in mind today I want to touch a little on using PowerShell to get domain SPF, DKIM and DMARC DNS values. This is part of a much larger project we have going on but I thought it was worth putting a little out there to help others with what it took me too long to figure out. As it turns out this is super easy and I am ashamed that I poked around too long on this.

To set this up lets say you want to check if your SPF, DKIM and DMARC DNS records are correct, or if they even exist for a domain. Sure… google it and go to any number of places on the web and put in your domain name and use the pull down, but that is way too easy. By now you know that I like to spend a dollar to save a dime so today I dove into PowerShell to do this for me. It turns out this is fairly easy to do with the Resolve-DNSName command in powershell. For instance lets say you want to get the SPF record for a particular domain:

Resolve-DNSName -Type TXT -Name <DomainName>

This will simply give you the txt records in a DNS Zone, which will include the SPF record. But what if you have many TXT records like some of my domains I haven’t cleaned up yet, then just add this:

Resolve-DNSName -Type TXT -Name <DomainName> | ? Strings -Match "spf1"

Now you get the SPF1 TXT record.

Next I want to see if they have DKIM entries. Since I am mainly working with Microsoft 365 these days I know those are going to be CNAME records with a “Select” name to them. SO:

Resolve-DNSName -Type CNAME -Name selector1._domainkey.<domainName>
# and / or 
Resolve-DNSName -Type CNAME -Name selector2._domainkey.<domainName>

Results give you the CNAMEs with those name, hence our DKIM DNS Values

Finally DMARC, you are using DMARC right?!?!

Resolve-DNSName -Type TXT -Name _dmarc.<domainName>

Yes, I know, its that easy!

From here we can get more complicated which you can see in the actual script that is easily a WORK IN PROGRESS, but this is an attempt to do some automation on SPF, DKIM and DMARC checking against Domains Setup in Microsoft 365.

# Connect to o365
Connect-MsolService

# Gets all domains in o365
$MSOL_Domains = Get-MsolDomain

Function GettingSPFDKIMDMARC_Records {
    
    $SPFResultes = Resolve-DnsName -Type TXT -Name $AbbriviatedName -erroraction 'silentlycontinue'
        If ($SPFResultes -eq $Null){
            Write-Host "No SPF Setting Found"
        } Else {
            $SPFResultes | Select Name, Strings | fl
        }
    $DKIM1Resultes = Resolve-DnsName -Type CNAME -Name selector1._domainkey.$AbbriviatedName -erroraction 'silentlycontinue'
        If ($DKIM1Resultes -eq $Null){
            Write-Host "No DKIM1 Setting Found"
        } Else {
            $DKIM1Resultes | Select Name, NameHost | fl
        }
    $DKIM2Resultes = Resolve-DnsName -Type CNAME -Name selector2._domainkey.$AbbriviatedName -erroraction 'silentlycontinue'
        If ($DKIM2Resultes -eq $Null){
            Write-Host "No DKIM2 Setting Found"
        } Else {
            $DKIM2Resultes | Select Name, NameHost | fl
        }
    $DMARCResultes = Resolve-DnsName -Type Txt -Name _dmarc.$AbbriviatedName -erroraction 'silentlycontinue'
        If ($DMARCResultes -eq $Null){
            Write-Host "No DMARC Setting Found"
        } Else {
            $DMARCResultes | Select Name, Strings | fl
        }
}

Function SPFCheck {

    $CheckResultes = Resolve-DnsName -Type TXT -Name $AbbriviatedName -erroraction 'silentlycontinue' | ? Strings -Match "spf1"
        
    # Checking Hard or Soft Fail
    $SoftFail = $CheckResultes.Strings -Match "~all"
    $HardFail = $CheckResultes.Strings -Match "-all"
        If ($SoftFail -eq $False -and $HardFail -eq $False) {
            Write-Host 'SPF Record Not Detected' -ForegroundColor Red
        } Else {
            If ($SoftFail -ne $Null){
                Write-Host 'SPF Set to Soft Fail' -foregroundColor Yellow
            }
            If ($HardFail -ne $Null){
                Write-Host 'SPF Set to Hard Fail' -ForegroundColor Green
            }
        }

    # Spliting SPF to get Include Count
    $split = $CheckResultes.Strings
    $split = $split -replace '(v=spf1 )'
    $split = $split -replace '( -all)'
    $split = $split -replace '( ~all)'
    $split = $split -split " "

    #put a check here if the SPF is not found then dont do this

    If ($split.count -ge 10) {
        Write-host 'Includes may be to many:' $split.Count -ForegroundColor Yellow
    } 
    If ($split.count -le 0) {
        Write-host 'Includes may be to few:' $split.Count -ForegroundColor Yellow
    } Else { 
        Write-Host 'Includes appear to be ok:' $split.Count -ForegroundColor Green
    }
}


# Runs for each domain in domains. Only returns if one exists
ForEach ($MSOLDomainName in $MSOL_Domains) {
    $AbbriviatedName = $MSOLDomainName.Name
    Write-Host " ------------------------------------------------"
    Write-Host "Domain:"$AbbriviatedName
    GettingSPFDKIMDMARC_Records # Calls Function to get all records
    SPFCheck
}

You can watch the progress from the GitHub repository here: https://github.com/flightgod/Script-GettingSPF_DKIM_DMARC

Bookmark the permalink.

Leave a Reply