Table of Contents

About

A Sender Policy Framework (SPF) record is an e-mail validation system designed to prevent spam by verifying IP addresses. A DNS system can be configured to add an SPF TXT record to the sender domain. In essence, the SPF is a white-listing service that allows external mail-servers to query the DNS system and check whether a certain IP address is eligible for sending e-mail from a given domain.

This tutorial will show you how to add an entry to a domain file in order to allow other DNS servers to check whether e-mails sent by you are not spam, as well as configuring postfix to perform checks for incoming e-mails.

Adding an SPF Record

This is an easy job and consists in editing your zone file (do not forget to increment the serial) in order to include a TXT record. For example, the following zone file for the domain named domain.com:

$TTL  3D
@	IN	SOA	ns0.domain.com. email.domain.com. (
			432561131
			3H
			15
			4W
			1D )

		NS	ns1              ; DNS name server 1
		NS	ns2              ; DNS name server 2

;		MX	10 mail         ; Primary Mail Server
;		MX	20 mail2        ; Secondary Mail Server

domain.com.	                A       127.0.0.1
ns1				A	127.0.0.1
ns2				A	127.0.0.1

www				CNAME	domain.com.

@   IN  TXT    "v=spf1 +mx +ip4:192.168.1.0/24 +ip4:46.228.47.114 +a:domain1.tld +a:domain2.tld +a:domain3.tld -all"

has the following line at the end, which is the SPF TXT record:

@   IN  TXT    "v=spf1 +mx +ip4:192.168.1.0/24 +ip4:46.228.47.114 +a:domain1.tld +a:domain2.tld +a:domain3.tld -all"

The options are:

This is all that is required to whitelist your servers.

Alternatively, domain name servers now support an SPF record, instead of a TXT record. So, instead of the configuration mentioned previously, we have the following record:

@   IN  SPF   "v=spf1 +mx +ip4:192.168.1.0/24 +ip4:46.228.47.114 +a:domain1.tld +a:domain2.tld +a:domain3.tld -all"

Another, more simple rule is:

@   IN  SPF	"v=spf1 a mx -all"

which matches if the domain name has an A record corresponding to the sender address or if the domain name has an MX record that resolves to the sender address - otherwise, it will reject any other IPs. This relies on an MX record being present for the zone.

Testing

After the record has replicated, send an e-mail to yourself on some other e-mail provider (for example, GMail) and open the e-mail when you receive it and check the full headers. You should see something like:

Received-SPF: pass (google.com: domain of yourmail@domain.tld designates 46.228.47.114 as permitted sender) client-ip=91.70.104.88;

Installing the Postfix SPF Filter

On Debian, you can choose between python and perl, so let us go with perl and install the required packages:

aptitude install postfix-policyd-spf-perl

the next step is to edit /etc/postfix/master.cf to include the lines:

policy  unix  -       n       n       -       -       spawn
        user=nobody argv=/usr/bin/perl /usr/sbin/postfix-policyd-spf-perl

at the end of the file.

The next step is to add a restriction to the smtpd restrictions by editing /etc/postfix/main.cf and adding the line:

check_policy_service unix:private/policy

to the list smtpd_recipient_restrictions. The result will look something like this:

smtpd_recipient_restrictions = permit_mynetworks,
        permit_sasl_authenticated,
        reject_unauth_destination,
        check_policy_service unix:private/policy,
        reject_unauth_pipelining, 
#       reject_invalid_hostname,
#        reject_unknown_recipient_domain,
#        reject_unauth_destination,
        reject_rbl_client sbl.spamhaus.org
        reject_rbl_client zen.spamhaus.org,
        reject_rhsbl_helo dbl.spamhaus.org,
        reject_rhsbl_sender dbl.spamhaus.org,
        permit

depending on your other rules.

After that, postfix needs to be restarted with:

service postfix restart

Testing

Perform the same test again, by sending yourself an e-mail, this time, to your newly configured mail server and check /var/log/mail.log when you receive your e-mail:

May 10 11:03:23 was postfix/policy-spf[14580]: Policy action=PREPEND Received-SPF: pass (gmail.com ... _spf.google.com: Sender is authorized to use 'john.doe+caf_=john=domain.com@gmail.com' in 'mfrom' identity (mechanism 'include:_netblocks.google.com' matched)) receiver=domain.com; identity=mailfrom; envelope-from="john.doe+caf_=john=domain.com@gmail.com"; helo=mail-wi0-f174.google.com; client-ip=209.85.212.174

Final Touches

A good way to test your domain for SPF approval is to use the form on openspf.org and check whether certain IPs are allowed to send e-mail through your mail server. A good syntax checker can be found on the openspf page.