So at my dayjob we have a pretty good amount of domain names we've registered for brand protection or typo domains. 3 domains we send or receive emails on, and 23 domains that just forward to a URL on our main domain. Our customer care got word of someone sending scam emails on one of the brand protection domains that should never be sending emails.
Let's explore how I setup our parked domains to report spoofers to me and help other mail servers know they shouldn't trust these emails pretending to be us.
Image Source: LifeHacker |
All we really used the extra domains for was forwarding things like conotso.one or contoso.com to the main domain of contoso.one. We didn't run our own server to do the forwarding, we just let GoDaddy do that with it's URL Forward feature.
To do that it sets up
- SOA Record - showing that it is authoritative for the domain
- NS Records - to communicate which servers can provide lookups
- A Record on @ - GoDaddy puts an A record on the naked domain to provide the redirect to the other HTTP URL
I also add a CNAME from WWW to @ in case people look for www.contoso.com
But none of those records will help protect against someone pretending to be that domain and send emails.
But none of those records will help protect against someone pretending to be that domain and send emails.
To protect against spoofed emails the basic things we want to setup are
SPF | Telling receiving servers that whoever sent the email wasn't authorized |
DKIM | Telling receiving servers that the email isn't a valid email |
MX | Communicating the server cannot receive mail |
DMARC | Setting a policy for how emails that fail SPF and/or DKIM should be handled |
SPF
No server sending email for this domain is authorized
The SPF Record is simple, just "all emails are unauthorized". This boils down to "v=spf1 -all" . So we create one record for the naked domain (or @ in the case of GoDaddy), and one record to cover all of the subdomains ( the *.example.com domain)
example.com TXT "v=spf1 -all"
*.example.com TXT "v=spf1 -all"
How this looks in GoDaddy's DNS Management tool |
DKIM
No email that is received for this domain is authorized
The DKIM record is also simple. DKIM or DomainKeys Identified Mail is used to help the receivers determine if the email has been tampered with, or was sent by an authorized party. We can use this to help the receivers of the email think that the email signature isn't valid because it sees the key as "revoked". The way we do this is by specifying an empty key. In normal DKIM records, there are additional fields, but they aren't needed since we are trying to create an intentionally denied record
With the way that DKIM records work, it is in the format selectorname._domainkey.example.com, we can take advantage of this to respond on ALL tried selectors with a wildcard record.
With the way that DKIM records work, it is in the format selectorname._domainkey.example.com, we can take advantage of this to respond on ALL tried selectors with a wildcard record.
*._domainkey.example.com TXT "v=DKIM1; p="
MX
When do you need MX Records if you dont receive email
When a mailserver receives an email, it checks if that domain can be looked up, which usually means checking for an A/AAAA record on the naked domain first, and then checking to see if there is an MX record if there was an A/AAAA record on the naked domain. Since I am using my domains for forwarding (or just general parking) I will have an A record on the bare domain, so the receiving server might try to assume that I can receive mail.
Communicate that this domain cannot receive email
The 100% proper way to handle this is a Null MX Record. A proper Null MX record has nothing after the priority, ending with a period, like shown below.
However, GoDaddy doesn't seem to support Null MX Records as it doesn't like the destination being empty. The best solution that I have seen recommended is to use the TLD of .invalid as the destination, like below. The Priority field of 0, indicates that this record is the one it should use first, since the lowest priority is the highest preference in MX records.example.com MX 0.
*.example.com MX 0.Compared with a normal mx record
example.com MX 10 mailserver.example.com
example.com MX 0 noemail.invalid
*.example.com MX 0 noemail.invalid
DMARC
To report failures to the domain's owners, and to tell the receiving servers what they should do with the fraudulent emails
Now, there are two parts to setup for DMARC.
The main points I would recommend to begin with are
- Setting up the DMARC Reporting policy
- External Authorization for reporting
Setting up DMARC Reporting Policy
There are several DMARC Record Wizards/Creators. I recommend them because there are numerous fields. Some of which can be defaulted away to prevent cluttering up or lengthening the record, which is another reason I recommend one of the wizards. Some of my favorites are DMARCian and MX Toolbox.
If I was creating a record on example.com sending aggregate reporting and forensic reporting to dmarc@maindomain.com and failing on either DKIM or SPF failing (or both, like I am setting up for good measure) your DMARC Policy record might be something like the below record
In the example.com DNS Zone
This is the way I would recommend to start. Importantly, p=none means that this is JUST for monitoring currently and not recommending either blocking or quarantining at this time. The receiving domains should report on the failures and progress normally for them. You can use this to make sure there ARE no legitimate emails going out. Or at least none going out to a DMARC reporting compatible service. Once you have a short while receiving no reports or people missing emails and no reports of emails being sent legitimately on one of your domains that you had missed or someone didn't think to tell you about, then you can turn it up to "quarantine" (Deliver to Spam or Quarantine), and eventually "reject" (Drop the email altogether)_dmarc TXT v=DMARC1; p=none; rua=mailto:dmarc@maindomain.com; ruf=mailto:dmarc@maindomain.com; fo=1; adkim=s; aspf=s
The main points I would recommend to begin with are
- Start with policy of "none" just to report, graduate to "quarantine" and "reject" later when you're confident there's no legitimate emails being sent on this domain.
- Aggregate Reporting to an email will get you summaries of email seen on this domain
- Start with Aggregate reporting and no forensic emails
- Forensic Reporting is 1 DMARC report PER EMAIL. If you are a marketing firm, you could potentially overwhelm your email servers if you send a couple hundred thousand emails out and DMARC Forensics sends back a couple hundred thousand at once.
- "adkim=s; aspf=s" - these set strict alignment on the domain.
- The aspf portion means that the From: and Sender addresses MUST be the same domain. This helps prevent things like a spammer finding a domain that soft-fails and sending their spam under that domain, but with a different return path, so that they can get responses
- The adkim portion means that they can't sign messages with a subdomain and send as the main domain, or vice-versa. Either way, with the rest of the setup we have, we don't want them to try to send as another "valid" domain and then pretend to be us elsewhere in the headers
- DMARC Reports are returned mostly in an XML file, often with hundreds of email records inside, a processing service (often paid) like DMARCian is excellent to get yourself a better understanding.
- There are free tools to view DMARC reports, I have used DMARCian's XML-to-Human converter
External Authorization for Reporting
As I mentioned above, forensics reporting could overwhelm servers easily for a larger domain. If you are sending reporting emails to an email outside of the domain you are reporting on, like sending reporting emails for example.com to an email at maindomain.com, you create some records on maindomain.com to show that example.com is authorized to send reporting to you. Ultimately this is very simple.
In the maindomain.com DNS Zone you should create two records, one for the naked domain, and one for all subdomains.
example.com._report._dmarc TXT "v=DMARC1"
*.example.com._report._dmarc TXT "v=DMARC1"
You may think you could just create a record like below, and you're right, but beware this means that literally ANY and EVERY domain on the internet can have their reporting sent to you. Like I mentioned before, this could be used to overwhelm your servers and DDOS you
*._report._dmarc TXT "v=DMARC1"
Handling DMARC Reporting Policies for multiple parked domains
Now, when you have many parked domains, if you wanted to change the DMARC Policy to bump it up from just reporting, to marking as spam, to rejecting, that can quickly get to be a LOT of records to edit. One way you can make this simpler is to CNAME the _dmarc record for each of the parked domains to something like _dmarc.parked.maindomain.com
In the example.com DNS Zone and each other parked domain_dmarc CNAME _dmarc.parked.maindomain.com
In the maindomain.com DNS Zone
You still need the External Reporting Authorization records listed above for EACH PARKED DOMAIN, but at least, you only have one place to update all of their policies at once after it is setup.
In the maindomain.com DNS Zone only
And from there, all you have to do is modify the DMARC policy at _dmarc.parked.maindomain.com and it modifies the policy of ALL domains who are aimed at that record with the CNAME_dmarc.parked TXT v=DMARC1; p=none; rua=mailto:dmarc@maindomain.com; ruf=mailto:dmarc@maindomain.com; fo=0;
adkim=s; aspf=s
You still need the External Reporting Authorization records listed above for EACH PARKED DOMAIN, but at least, you only have one place to update all of their policies at once after it is setup.
Altogether
All said and done, since my provider doesn't support MX Null Records, my layout is like below
In the example.com DNS Zone and all parked domains
example.com TXT "v=spf1 -all"
*.example.com TXT "v=spf1 -all"
*._domainkey.example.com TXT "v=DKIM1; p="
_dmarc CNAME _dmarc.parked.maindomain.com
example.com MX 0 noemail.invalid
*.example.com MX 0 noemail.invalid
_dmarc.parked TXT v=DMARC1; p=none; rua=mailto:dmarc@maindomain.com; ruf=mailto:dmarc@maindomain.com; fo=0;
adkim=s; aspf=s
example.com._report._dmarc TXT "v=DMARC1"
*.example.com._report._dmarc TXT "v=DMARC1"
(Repeat the two previous records for each parked domain)
Checking your setup!
Once all of these are setup, you should check that they are all working. I usually use MXToolbox's testing tools.
SPF | https://mxtoolbox.com/spf.aspx |
DKIM | https://mxtoolbox.com/dkim.aspx - Note, you will need to specify a "Selector". You can put what you want in this, if you followed my setup above, any selector will match with the wildcard. This check should also have a FAIL as "Public key has been revoked", this is the desired effect |
MX | https://mxtoolbox.com/ |
DMARC | https://mxtoolbox.com/dmarc.aspx |
I threw a quick PowerShell script together that will load MXToolbox's check for the SPF,DKIM,MX,and DMARC on both the Bare domain and a generic subdomain on all of the domains listed. Have fun and catch those spammers!
Hi,
ReplyDeleteIs there any possibility to enforce SPF on the multiple third party domains (domains that we don't manage and/or administer) from our side? We can implement SPF on the email domains that we owned. Please shed light on this.
Hi! That's a great question!
DeleteNo. Not really.
The best that you can do is use something like an Exchange Transport Rule to say "if SPF Fails, reject the message with a custom error"
But I say "not really" because this is an EXTREMELY time consuming process and you are cutting your domain off from being able to receive an ENORMOUS portion of ALL EMAILs sent in the world.
It is frankly astounding how many companies that are quite established don't have the basic level of a minimal SPF, or aren't just basically allowing everything with ?all or even literally +all
The only hope you have of enforcing this on them is rejecting their emails, with a message that they should contact IT, perhaps. If you accept their emails, but just mark them as "Insecurely delivered" then the sending company basically NEVER cares enough to fix it.