Ministry of Innovation / Business of Technology

Taking e-mail back, part 3: Fortifying your box against spammers

We load up OpenDKIM, SpamAssassin, ClamAV, and get Sieve filtering operational.

Telling Postfix about your milters

After a bit of work, we have OpenDKIM, SpamAssassin, and ClamAV up and running as milters. However, they won't actually do anything until we tell Postfix that we want to use them—and to do that, we need to go back to Postfix's configuration file.

Fortunately, we did a bit of pre-work in part 2 to get ourselves ready for this: open /etc/postfix/ up for editing and uncomment the following lines:

milter_default_action = accept
milter_connect_macros = j {daemon_name} v {if_name} _
non_smtpd_milters = $smtpd_milters
smtpd_milters = unix:/spamass/spamass.sock unix:/clamav/clamav-milter.ctl unix:/opendkim/opendkim.sock

Then, reload Postfix's configuration to make your change live:

service postfix reload

DNS and all its rainbow of services

E-mail is tied pretty heavily to DNS. Without the ability to look up domain names, you wouldn't be able to send an e-mail to, since you'd have no correlation between and the server or servers that handle its e-mail. We're going to add some DNS entries to your external DNS provider, whoever that is, in order to both identify your mail server and also provide some additional information about it.

Internal DNS is also another potential issue. It's one thing for everyone on the Internet to know that e-mail for is supposed to go to your Internet-facing public IP address, but what about LAN hosts? Ideally, you want LAN traffic to go to a local name and IP address on the LAN. This might not be a huge problem for desktops, but laptops and other portable devices that might need to send and receive e-mail on and off the LAN are definitely affected.

The most common way around this is setting up what's called split DNS or split horizon DNS—running a LAN-only DNS server or servers that will provide different answers for queries coming from different places.

In my case, I run an instance of bind9 on my LAN for internal DNS; it responds to queries for "" with "," which is my e-mail server's LAN IP address. On the other hand, if one of you does a DNS lookup for "," you'll see "," courtesy of whatever DNS server you're using. My internal DNS server isn't reachable from the Internet, but if you were to come over to my house, my DHCP server would seamlessly hand your device its address as part of the DHCP assignment.

If you want to go through the trouble of setting up your own unix-y bind9 server and do things in this exact fashion, I have a blog entry on my personal site that will walk you through it step by step. But split DNS with bind9 isn't the only way to skin this particular cat—if you're using a NAT router for DNS, you can probably set up static DNS entries there for your mail server, and that ought to do the trick. And if you're hosting your mail server offsite on a VPS or other hosting service, this isn't a problem you have to worry about at all!

External DNS: Registrar or cloud

External DNS, though, is something we absolutely have to get going. I mentioned back in part 1 that you can get some amount of additional security by segregating your services where possible, and DNS is potentially one of those places. The registrar where you registered your domain name will happily host your DNS for you, but you can also use a third-party DNS service like Amazon Route 53 or Cloudflare DNS as your DNS provider.

A lot of people wrote in to say that they recommend Cloudflare over Route 53 for several reasons, not the least of which is that it's free and Route 53 isn't (though my Route 53 bill for last month was $1.74 for three hosted DNS domains and about 214,000 queries—that's $0.50 per domain and $0.11 for the queries). Once you're signed up, the actual DNS configuration process is roughly similar between both services; I use Route 53, so that's what I'll show images from.

Whether you're going to use your registrar's hosting or transfer to a third-party DNS, the actual DNS entries that we need to make are the same. If you're going to stick with your registrar, you'll do these steps in your registrar's DNS control panel, wherever that happens to be. If you're going to use a third-party DNS provider, you make these changes there, and then after they're in place you'll transfer your DNS over from your registrar.

Enlarge / External DNS fields for one of my domains at

On Route 53, you go to the Route 53 service home and create a new zone with the "Create Hosted Zone" button at the top. You'll need to give it a name and a description—the description can be whatever you like ("this is my domain!"), but the name needs to be your domain's name—so, if you registered "," that's what you'd put. (If you're doing this on your registrar, your DNS zone should already be there—you won't have to create it a second time.)

Next, click on your zone to highlight it and click the "Go to record sets" button to see the existing records. You'll have a few in there—at least an SOA record (that's "Start of Authority") and some name servers—but we're going to add some more. Specifically, we'll need to add an MX record to identify our mail server's name and address, a TXT record with the DKIM information we generated earlier, and an SPF record (which we haven't really talked about yet).

First, the all-important MX record. Every domain with e-mail needs at least one—this record is what tells inquiring servers where to send e-mail for your domain. If you have more than one mail server—which you would if you were setting up e-mail for something important—then you'd have multiple records, and each would have a priority and a weighting (which would allow both a distribution of load and also failover in case a server went offline). Click "Create record set," then change the type of record from "A - IPv4 address" to "MX - Mail exchange." Set the TTL to "1d"—that's adjusting the "time to live" on the record to a full day, which will help to reduce the number of times external servers try to look up the record from one of the Route 53 name servers.

In the "Value" box, you'll want to put the number "10" and the name of the server, like in this image:

Enlarge / Adding your MX record.

Then, click "Create." Boom, you have an MX record!

Next, the OpenDKIM record. We're going to embed that DKIM public key we generated back near the beginning of the guide into a text record that anyone on the Internet can query, along with some instructions about how it should be used. The actual record has already been created for us in text form: it's waiting patiently in /etc/opendkim/mail.txt, already in mostly the correct format for pasting into a DNS zone file. On some DNS providers, you can do just that; for Route 53, you'll have to change it up a bit.

First, take a look at the contents of /etc/opendkim/mail.txt. On my test virtual machine, it looks like this:

mail._domainkey IN TXT "v=DKIM1; h=sha256; k=rsa;
; ----- DKIM key mail for

Create another record set with the "Create Record Set" button, and this time change the drop-down at the right to "TXT - Text". In the "Name" field, type mail._domainkey (substituting in your mail server's name in place of "mail" if it's not "mail"). Set the TTL record to one day and then paste the quotes and everything inside of them into the "Value" field:

Enlarge / Adding your DKIM record.

Next, the SPF record. SPF stands for Sender Policy Framework, and it's an easy thing to set up that can help increase your mail's deliverability by giving remote hosts another way to verify that your e-mail originates from a legitimate, authorized sender. There are a number of different things you can do with an SPF record, and you can use this tool at SPF Wizard to come up with a customized record, but the best one is to use a simple one, like "v=spf1 mx a ?all":

Enlarge / Adding your SPF record.

That's all we need to do for record creation. The next thing you'll want to do is transfer your DNS away from your registrar, though if you've decided to use your registrar's DNS services, you can obviously skip this step as well. How to do this varies by registrar, but it should be relatively straightforward—you're looking for an option to use "external DNS" or "third-party DNS." There should be a simple method to switch off the registrar's name servers and plug in a list of name servers provided by your third-party provider.

One very important note: if you've already created entries in your registrar's DNS zone (like A records or CNAMEs for other hosts or services), you'll obviously want to recreate those in your third-party DNS registrar before you transition! Otherwise your website or whatever those records were for won't be locatable over the Internet.

A note on authentication

Make sure that whatever you choose for your DNS, you enable two-factor authentication on your account. For Route 53, you turn on two-factor authentication in your main Amazon AWS account under the Security Credentials page. Click the drop-down for "Multi-Factor Authentication" and get it set up immediately if you haven't already. Cloudflare also offers two-factor authentication. Regardless of your DNS provider, even if it's with your registrar, two-factor is an absolute requirement.

Reverse-lookup: a major factor in successful e-mail

The last big DNS task you'll need to tackle is getting your e-mail server's PTR record updated. Most e-mail servers will check your server's DNS name and then perform a reverse-DNS lookup on your server's IP address, like looking up a phone number in a reverse-lookup directory to find out someone's name. If the name given by the reverse-lookup doesn't match the name from the forward lookup, some mail servers will reject your e-mail (and indeed, the Postfix configuration we're using makes your server one of those servers). Because most spammers either blast e-mail out from hijacked machines or don't bother with correct DNS, rejecting e-mail from servers without proper reverse PTR records is common.

However, unlike forward lookup DNS records, you can't always set a reverse PTR record yourself. In my case, on a Comcast business class connection, I had to call into their support number and generate a support ticket; however, the support representatives said it was a common request and they had a relatively easy process for it. I gave them my static IP address and the name I wanted it to resolve to——and within 48 hours the change was in.

If you're using a VPS or cloud-hosted mail server, check with your hosting provider on how to set up a reverse PTR record. Most of them will be happy to accommodate you, provided you have your own IP address and aren't using dynamic DNS to a shared address. If you've decided to use an Amazon EC2 instance, you can get your PTR record updated using this form.

Lastly, if you're doing this from a residential IP address, you likely won't be able to get reverse lookups working right, which will have a definite impact on your e-mail deliverability. Unfortunately, there's not much you can do about it except switch to a hosting provider or upgrade to a business-class service that offers static IP addresses.

Expand full story

You must to comment.