Arch Linux mail server tutorial - part 3 - Get DNS right, it's important!

Published on 2017-12-29. Modified on 2021-07-20.

In this part of the tutorial we're going to take a look at the important parts of setting up DNS in order to run a mail server.

Get DNS right, it's important!

DNS is short for Domain Name System. DNS is a comprehensive translation system that in its simplest form is used to translate domain names to unique IP addresses.

Because computers communicate using numbers, and we humans, obviously, do not, DNS translates such numbers into human-friendly phrases. Each IP address on the Internet must be distinct from others. An IPv4 address could be a set of any four numbers in the range from 0 to 255, like 208.67.222.222. When you type a domain name into your browser, the DNS system translates the domain name into the IP address associated with the domain. Once the website IP address is found, your browser connects with the web server and the requested page is displayed in your browser. This works the same for SMTP servers when they relay email.

DNS is the cornerstone in how the Internet functions.

In order to operate a mail server you need to setup some DNS records for your server. If you are the owner of the example.com domain, and a mail server on the Internet wants to send an email to foo@example.com, that mail server needs to find out which other mail server on the Internet it will have to establish an SMTP connection to in order to deliver the email.

If you don't know anything about DNS you need to do some research first. It is very important that you get DNS right!

Here are some recommended resources:

You need the following records set up:

The PTR, SPF, DKIM, and DMARC records are not obligatory, but they are very important if you want to make sure the emails you send out isn't rejected by receiving mail server (more about that in a moment).

The A, CNAME, and MX records

Because different services can run on different machines you need to specify both an IP address for your apex domain (the domain name without anything in front of it), and an IP address for the FQDN you enter as the MX server.

When a foreign SMTP server contacts a DNS server in order to get information about your SMTP server, it will ask who can receive email for the apex domain, example.com, and get the FQDN located in the MX record, mail.example.com, then it will ask for the IP address of the FQDN mail.example.com

INFO:
In most cases bigger corporations have more than one SMTP server, just in case a server should fail to respond for various reasons. Each server is then listed in an order of priority, like this:

gmail.com. 3600 IN MX 5 gmail-smtp-in.l.google.com.
gmail.com. 3600 IN MX 10 alt1.gmail-smtp-in.l.google.com.
gmail.com. 3600 IN MX 20 alt2.gmail-smtp-in.l.google.com.
gmail.com. 3600 IN MX 30 alt3.gmail-smtp-in.l.google.com.
gmail.com. 3600 IN MX 40 alt4.gmail-smtp-in.l.google.com.


The server with the lowest priority number, in this case number 5, will be chosen first.

If you have the resources it's always a good idea to have at least one backup server.

Now, mail.example.com and example.com may very well be the same machine, but you need to tell the DNS server that either by using two A records, or by using a CNAME record with mail.example.com which points to example.com and then use an A record for example.com

So you should then at least have these three records to begin with:

HOST               TYPE          POINTS TO           TTL
example.com        A             1.2.3.4             3600
mail.example.com   CNAME         example.com         3600
example.com        MX            mail.example.com    3600

Or:

HOST               TYPE          POINTS TO           TTL
example.com        A             1.2.3.4             3600
mail.example.com   A             1.2.3.4             3600
example.com        MX            mail.example.com    3600

The reason why you need to setup both example.com and mail.example.com is because they could each be associated with two different machines and IP addresses.

Let's make another example in which example.com and www.example.com are the same machine serving HTML (a web server in other words), but the mail server mail.example.com is setup on another machine. The setup would then look like this:

HOST               TYPE          POINTS TO           TTL
example.com        A             1.2.3.4             3600
www.example.com    CNAME         example.com         3600
example.com        MX            mail.example.com    3600
mail.example.com   A             4.5.6.7             3600

If you have never handled DNS before this part can be a bit confusing so you need to make sure you do it right. Look at the information provided by your DNS provider on how to set it up correctly and ask them if you're in doubt.

We can imagine an email DNS request between the mail server (SMTP) and the DNS server as a conversation:

SMTP server asks: I got an email for foo@example.com, who's responsible for accepting email for the domain example.com?

The DNS server looks at the MX record and provides the answer: mail.example.com is responsible for accepting email on behalf of example.com.

The SMTP server then asks: Where's mail.example.com located on the Internet?

The DNS server then looks at the A record for mail.example.com and answers: It's located at IP address 4.5.6.7.

If example.com and mail.example.com are located on the same IP address, it's your choice whether you want to use two A records or one A record and a CNAME record. When a DNS server is authoritative for domains located in the same zone there is no difference between A records and CNAME records queries, they are equally fast.

If you try to look up www.gmail.com you'll see something like this:

$ dig www.gmail.com

;; ANSWER SECTION:
www.gmail.com.      86400   IN  CNAME   mail.google.com.
mail.google.com.    593961  IN  CNAME   googlemail.l.google.com.
googlemail.l.google.com. 268    IN  A   172.217.13.197

Which shows that www.gmail.com points to mail.google.com, and mail.google.com points to googlemail.1.google.com, which is located at the IP address 172.217.13.197. In other words all these addresses are identical. The DNS server resolved the CNAME's for us and attaches the whole answer in one go.

The PTR record

A Pointer Record (PTR) resolves an IP address to a fully-qualified domain name (FQDN) as an opposite to what an A record does. PTR records are also called Reverse DNS records. PTR records are mainly used to check if the server name is actually associated with the IP address from where the connection was initiated.

You can get the IP address of a domain by using the "dig" command:

$ dig send.one.com
send.one.com.       1003    IN  A   46.30.211.140

And you can get the FQDN when you lookup the IP address (if a PTR record is setup) using the -x option:

$ dig -x 46.30.211.140
140.211.30.46.in-addr.arpa. 1078 IN PTR send.one.com.

The most difficult record to deal with is the PTR record because you need permission from the owner of the IP address to set it up. If you cannot setup a PTR record because you don't own the IP address you're running with, and your ISP won't help you, you should first look for other options because some mail servers reject email from other mail servers that are missing a valid PTR record. However, if you haven't got any other options, which many home based legit mail server owners don't, you can still run your mail server, but you must make sure you get the SPF, DKIM, and DMARC records set. People do successfully run mail servers without valid PTR records without any problems (I myself have never had any problems), but the common denominator is the SPF, DKIM, and DMARC records.

The reason why a PTR record is important regarding mail servers is that any spammer may be able to send mail to a mail server, but many spammers will not be able to create a PTR record for their IP address, because they are using an open relay or a personal ISP, ie. an IP address that doesn't belong to them. This means that their IP address would not have an associated PTR record, or the PTR record is associated with the ISP. As such, blocking emails from IP addresses with no PTR record reduces the spam the mail server sends out and this is default on some SMTP servers.

The PTR record should match the SMTP response on port 25 when the receiving server sends back a verification check, which is the FQDN of the mail server. The PTR record shouldn't match the MX record as some believe, because the MX record may hold another server IP address altogether. The verification response that happens, which is called "sender verify" by most email servers, is when there is a match between the PTR record and the SMTP FQDN.

You can see a server's SMTP response by issuing the following command to an SMTP server using the IP address or the FQDN:

$ telnet 1.2.3.4 25
220 mail.example.com ESMTP OpenSMTPD

Where 1.2.3.4 is the IP address for the server in question. Basically, you will get a response that tells the server hostname, which is what the PTR record should match, in this case mail.example.com.

Some administrators setup their mail server PTR record with a FQDN that points to a CNAME record. So if mail.example.com is a CNAME for smtp.example.com then they use that, but CNAME should never be used for any mail related matters. Make sure you set it to your FQDN of your mail server!

The PTR record should not contain anything besides the IP address and the FQDN.

This is how it should look. First we lookup the IP address for the SMTP server that One.com is using (as we did in the above example):

$ dig send.one.com
send.one.com.       164 IN  A   46.30.211.140

Then we use that IP address to lookup the PTR record:

$ dig -x 46.31.211.140
140.211.30.46.in-addr.arpa. 2240 IN    PTR    send.one.com.

Notice the trailing dot, that's not something you should put in, it gets automatically added.

If you are in doubt, get assistance from the ISP or DNS hoster your are using.

Continuing from the example above, let's add the PTR record to our DNS setup:

HOST                    TYPE          POINTS TO           TTL
example.com             A             1.2.3.4             3600
mail.example.com        A             1.2.3.4             3600
example.com             MX            mail.example.com    3600
4.3.2.1.in-addr.arpa    PTR           mail.example.com    3600

Please notice how the IP address in the PTR record is listed backwards, this is how it is supposed to be.

The SPF record

A Sender Policy Framework (SPF) record is a simple email-validation system designed to detect email spoofing by providing a mechanism to allow receiving mail exchangers to check that incoming mail from a domain comes from a host authorized by that domain's administrators.

I highly recommend reading the Wikipedia article about the Sender Policy Framework if you don't know what it is or how it works.

Then go to SPF Record Syntax in order to understand the different options and attributes.

You can use a SPF wizard to construct your SPF record.

Once you're done setting up DNS you can verify your settings with an online tool like: DNSsy or MX ToolBox.

Make sure you understand the different attributes before you use it.

Let's add our SPF record to our example.

HOST                    TYPE          POINTS TO           TTL
example.com             A             1.2.3.4             3600
mail.example.com        A             1.2.3.4             3600
example.com             MX            mail.example.com    3600
4.3.2.1.in-addr.arpa    PTR           mail.example.com    3600
example.com             TXT           v=spf1 a -all       3600

The DKIM record

As you probably remember we created a DKIM signature in part 2 of the tutorial. Use cat to output the public key and insert the public key string into a TXT field in a DNS record.

# cat /etc/mail/dkim/public.key
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDIKOKNy/ghYjFz8FfxOxdzXxUN
+x2+RONxX6icGZnF6m1Ji4YJMP5QuujoZEWDHhyTOJ5YqCCoBm3c73kns84gXcdw
5oXcounxtG3eROewl5ncpkgbn+eR8uTe+tSV8GU7J+koUXaXrlPpF9Qna0qgeTxv
w56WH3oQZm1jAV0zYQIDAQAB

I have shortened the key in the example below:

HOST                                     TYPE   POINTS TO                          TTL
example.com                              A      1.2.3.4                            3600
mail.example.com                         A      1.2.3.4                            3600
example.com                              MX     mail.example.com                   3600
4.3.2.1.in-addr.arpa                     PTR    mail.example.com                   3600
example.com                              TXT    v=spf1 a -all                      3600
selector1._domainkey.mail.example.com    TXT    v=DKIM1; p=MIG...; s=email; t=s    3600

The key goes into the p= part of the options.

Remember we used the name "selector1" for our selector. You can call it anything, but remember it must match the "selector" field in /etc/dkimproxy/dkimproxy_out.conf:

# specify the selector (i.e. the name of the key record put in DNS)
selector  selector1

If you would rather like it to be myselctor, you could use that:

selector myselector

And then in the DNS record:

myselctor._domainkey.mail.example.com    TXT    v=DKIM1; p=MIG...; s=email; t=s    3600

You can verify your DKIM record using the tool dkimcore.

If you get the error, "This is not a good DKIM key record. You should fix the errors shown in red", and it says, "The p= field must be base64 encoded", then it is because you have managed to get white spaces into the public.key when you copy/pasted it. Remove the white spaces.

The DMARC record

DMARC uses the two existing mechanisms, Sender Policy Framework (SPF) and DomainKeys Identified Mail (DKIM). A DMARC policy can tell a receiving mail server whether or not to accept an email from a particular sender. Not all receiving SMTP servers will perform a DMARC check, but all the major ISPs do and its implementation is growing fast. You can use DMARC to protect your domains against abuse in phishing or spoofing attacks.

You can use a DMARC Wizard to setup your DMARC DNS record.

HOST                                     TYPE   POINTS TO                                      TTL
example.com                              A      1.2.3.4                                        3600
mail.example.com                         A      1.2.3.4                                        3600
example.com                              MX     mail.example.com                               3600
4.3.2.1.in-addr.arpa                     PTR    mail.example.com                               3600
example.com                              TXT    v=spf1 a -all                                  3600
selector1._domainkey.mail.example.com    TXT    v=DKIM1; p=MIG...; s=email; t=s                3600
_dmarc.mail.example.com                  TXT    v=DMARC1; p=reject; sp=none; rua=mailto:postmaster@example.com!20m; ruf=mailto:postmaster@example.com!20m; rf=afrf; pct=100; ri=86400                3600

You can use dmarcian to inspect your DMARC record, and your SPF and DKIM records too.

Final notes

If you need to manually add the "Let's Encrypt" validation string to your DNS setup, maybe because the "acme.sh" client haven't got support for your DNS provider, or because you're using another client, then it looks like this:

_acme-challenge.mail.example.com    TXT    F24BbLWJyjTkFpg-LqSLiUWksaUwPbZB-LdaqbOxCcc    3600

Regarding blacklisting of mail servers, eventually, no matter what you do, you will most likely get blocked now and then even if you do everything right so don't worry to much about it.

If you're an SMTP server administrator reading this: Please stop filtering email on the mail server. Instead educate people in proper email address usage and email client filtering.