How To Implement SPF in Postfix

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 7

How To Implement SPF In Postfix

1 of 7

https://www.howtoforge.com/postfix_spf
English |

Deutsch

Log in or Sign up

Tutorial search
Tutorials

How To Implement SPF In Postfix

How To Implement
SPF In Postfix

On this page

Version 1.0
Author: Falko Timme

How To Implement SPF In Postfix


1 Preliminary Note
2 Install Required Perl Modules
3 Install postfix-policyd-spf-perl
4 Test policyd-spf-perl
5 Links

This tutorial shows how to


implement SPF (Sender Policy
Framework) in a Postfix 2.x installation. The Sender Policy Framework is an open standard specifying
a technical method to prevent sender address forgery (see http://www.openspf.org/Introduction).
There are lots of SPF extensions and patches available for Postfix, but most require that you
recompile Postfix. Therefore we will install the postfix-policyd-spf-perl package from
openspf.org which is a Perl package and can be implemented in existing Postfix installations (no
Postfix compilation required).

Author:
Tags:

falko
postfix, anti-spam/virus

Tweet

I want to say first that this is not the only way


of setting up such a system. There are many
ways of achieving this goal but this is the way
I take. I do not issue any guarantee that this
will work for you!

1 Preliminary Note
I assume that you have already set up a
working Postfix mail server.
The following procedure is distribution-independent, i.e., it should work on any Linux distribution
(however, I tested this on Debian Etch).

2 Install Required Perl Modules


The postfix-policyd-spf-perl package depends on the Mail::SPF and the NetAddr::IP
Perl modules. Therefore we are going to install them now using the Perl shell. Start the Perl shell like
this:
perl -MCPAN -e shell

If you run the Perl shell for the first time, you will be asked a few questions. You can accept all
default values. You will also be asked about the CPAN repositories to use. Select repositories that are
close to you.
After the initial Perl shell configuration, we can start to install the needed modules. To install
Mail::SPF, simply run
install Mail::SPF

In my case, it tried to install Module::Build (which is a dependency), but then it failed. If this

10/5/2016 11:48 AM

How To Implement SPF In Postfix

2 of 7

https://www.howtoforge.com/postfix_spf

happens to you, simply quit the Perl shell by typing


q

Then start the Perl shell again:


perl -MCPAN -e shell

and try to install Mail::SPF again:


install Mail::SPF

This time it should succeed, and you should see that it also installs the modules
Net::DNS::Resolver::Programmable and NetAddr::IP on which Mail::SPF depends.
A successful installation of Mail:SPF should end like this:
Installing /usr/local/bin/spfquery
Writing /usr/local/lib/perl/5.8.8/auto/Mail/SPF/.packlist
/usr/bin/make install -- OK
Because NetAddr::IP has already been installed, we can now leave the Perl shell:
q

3 Install postfix-policyd-spf-perl
Next we download postfix-policyd-spf-perl from http://www.openspf.org/Software to the
/usr/src/ directory and install it to the /usr/lib/postfix/ directory like this:
cd /usr/src
wget http://www.openspf.org/blobs/postfix-policyd-spf-perl-2.001.tar.gz
tar xvfz postfix-policyd-spf-perl-2.001.tar.gz
cd postfix-policyd-spf-perl-2.001
cp postfix-policyd-spf-perl /usr/lib/postfix/policyd-spf-perl

Then we edit /etc/postfix/master.cf and add the following stanza at the end:
vi /etc/postfix/master.cf

[...]
policy

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

(The leading spaces before user=nobody are important so that Postfix knows that this line belongs
to the previous one!)
Then open /etc/postfix/main.cf and search for the smtpd_recipient_restrictions
directive. You should have reject_unauth_destination in that directive, and right after
reject_unauth_destination you add check_policy_service unix:private/policy
like this:
vi /etc/postfix/main.cf

[...]
smtpd_recipient_restrictions = permit_sasl_authenticated,permit_mynetwork
s,reject_unauth_destination,check_policy_service unix:private/policy
[...]
or like this:

10/5/2016 11:48 AM

How To Implement SPF In Postfix

3 of 7

https://www.howtoforge.com/postfix_spf

[...]
smtpd_recipient_restrictions =
[...]
reject_unauth_destination
check_policy_service unix:private/policy
[...]
[...]
It is important that you specify check_policy_service AFTER
reject_unauth_destination or else your system can become an open relay!
Then restart Postfix:
/etc/init.d/postfix restart

That's it already. You should check the README file that comes with the postfix-policydspf-perl package, it contains some important details about how postfix-policyd-spf-perl
processes emails, e.g. like this part from the postfix-policyd-spf-perl-2.0001 README:

This version of the policy server always checks HELO before Mail From (older
versions just checked HELO if Mail From was null). It will reject mail that
fails either Mail From or HELO SPF checks. It will defer mail if there is a
temporary SPF error and the message would othersise be permitted
(DEFER_IF_PERMIT). If the HELO check produces a REJECT/DEFER result, Mail From
will not be checked.
If the message is not rejected or deferred, the policy server will PREPEND the
appropriate SPF Received header. In the case of multi-recipient mail, multiple
headers will get appended. If Mail From is anything other than completely empty
(i.e. ) then the Mail From result will be used for SPF Received (e.g. Mail
From None even if HELO is Pass).
The policy server skips SPF checks for connections from the localhost (127.) and
instead prepends and logs 'SPF skipped - localhost is always allowed.'

4 Test policyd-spf-perl
We can test policyd-spf-perl by running
perl /usr/lib/postfix/policyd-spf-perl

The cursor will then wait on the policyd-spf-perl shell. We can now act as if we tried to send
an email from a certain domain and a certain server to another email address. policyd-spf-perl
will then check if that certain server is allowed to send emails for the sender domain and show us
the result.
So let's see what happens if we try to send a mail from info@h****forge.com from the server
h****.server*********.net (IP address 81.169.1**.**). The h****forge.com has an
SPF record that allows 81.169.1**.** to send emails from h****forge.com.
So on the policyd-spf-perl shell we type:
request=smtpd_access_policy
protocol_state=RCPT
protocol_name=SMTP
helo_name=h****forge.com
queue_id=8045F2AB23
sender=info@h****forge.com
recipient=falko.timme@*******.de
client_address=81.169.1**.**
client_name=h****.server*********.net
[empty line]

The output should look like this:


action=PREPEND Received-SPF: pass (h****forge.com: 81.169.1**.** is

10/5/2016 11:48 AM

How To Implement SPF In Postfix

4 of 7

https://www.howtoforge.com/postfix_spf

authorized to use 'info@h****forge.com' in 'mfrom' identity (mechanism


'ip4:81.169.1**.**' matched)) receiver=server1.example.com;
identity=mfrom; envelope-from="info@h****forge.com"; helo=h****forge.com;
client-ip=81.169.1**.**
which means we passed the test.
Let's run another test, this time we will send from the client 1.2.3.4 (www.example.com) which is
not allowed to send emails from h****forge.com:
request=smtpd_access_policy
protocol_state=RCPT
protocol_name=SMTP
helo_name=h****forge.com
queue_id=8045F2AB23
sender=info@h****forge.com
recipient=falko.timme@*******.de
client_address=1.2.3.4
client_name=www.example.com
[empty line]

This is the output, the test failed as expected:


action=PREPEND Received-SPF: softfail (h****forge.com: Sender is not
authorized by default to use 'info@h****forge.com' in 'mfrom' identity,
however domain is not currently prepared for false failures (mechanism
'~all' matched)) receiver=server1.example.com; identity=mfrom; envelopefrom="info@h****forge.com"; helo=h****forge.com; client-ip=1.2.3.4
We can now even try to leave the sender field empty, as many spammers do. Still, policydspf-perl should be able to complete its tests:
request=smtpd_access_policy
protocol_state=RCPT
protocol_name=SMTP
helo_name=h****forge.com
queue_id=8045F2AB23
sender=
recipient=falko.timme@*******.de
client_address=81.169.1**.**
client_name=h****.server*********.net
[empty line]

This is the output, we are still allowed to send from h****forge.com:


action=PREPEND Received-SPF: pass (h****forge.com: 81.169.1**.** is
authorized to use 'h****forge.com' in 'helo' identity (mechanism
'ip4:81.169.1**.**' matched)) receiver=server1.example.com; identity=helo;
helo=h****forge.com; client-ip=81.169.1**.**
Let's try the same test with an invalid client:
request=smtpd_access_policy
protocol_state=RCPT
protocol_name=SMTP
helo_name=h****forge.com
queue_id=8045F2AB23
sender=
recipient=falko.timme@*******.de
client_address=1.2.3.4
client_name=www.example.com
[empty line]

As expected, this is the output:


action=PREPEND Received-SPF: softfail (h****forge.com: Sender is not
authorized by default to use 'h****forge.com' in 'helo' identity, however
domain is not currently prepared for false failures (mechanism '~all'
matched)) receiver=server1.example.com; identity=helo;
helo=h****forge.com; client-ip=1.2.3.4
To leave the policyd-spf-perl shell, type
[CTRL+C]

10/5/2016 11:48 AM

How To Implement SPF In Postfix

5 of 7

https://www.howtoforge.com/postfix_spf

5 Links

OpenSPF: http://www.openspf.org
policyd-spf-perl Download: http://www.openspf.org/Software
SPF Definition On Wikipedia: http://en.wikipedia.org/wiki/Sender_Policy_Framework
Postfix: http://www.postfix.org
view as pdf |

print

Share this page: Tweet Follow

14 Comment(s)
Add comment

Name *

Email *

Comments
From:

Reply

Thank you for the excellent how-to. I've only recently come across SPF and after creating a short
tutorial detailing how to set up SPF / Sender ID records with 123-reg for the domain itself, I was
dreading having to actually implement it in Postfix.
I'll let you know how I get on.
From:

Reply

If you are using the current release of Ubuntu (7.04 - Feisty Fawn) mail::spf and the Postfix policy
server are built into the packaging system. All you have to do is:
sudo apt-get install libmail-spf-perl postfix-policyd-spf-perl
and all of the packages with dependencies will get pulled in.

The is also a Python policy server at the same site. It is also in Ubuntu with the Python SPF library
updated to the current release (2.0.3). If you prefer Python all you have to do is:
sudo apt-get install python-spf python-policyd-spf

With the exception of the saying python instead of perl and the path to the executable (covered in the
documentation), integration with Postfix is the same.
From:

Reply

One other small comment... The How-To says Postfix 2.x, but the policy service was introduced in
Postfix 2.1, so it should say 2.1+ rather than 2.x.
From:

Reply

this is on my schedule to do tomorrow.

Just wondering though why other How Tos for this menution DNS

10/5/2016 11:48 AM

How To Implement SPF In Postfix

6 of 7

https://www.howtoforge.com/postfix_spf

settings and this one does not?


Thanks

From: Panzer

Reply

This HOWTO describes the way to check if the incoming mail message is in accordance with the
SPF that is set by the admins of the domain from which the message was sent.
DNS records for SPF serve the purpose of setting your own policy for others to check.

Therefore, you can check for SPF for incoming messages and not use SPF for your own domain

(makes sense if you're not in control of your DNS records, or if it is complicated for you to create a
sutable SPF policy), or you can set your own SPF policy for your domain and not use SPF for

incoming messages (stupid), or you can use both SPF checking for incoming mail and set your own
SPF policy for others to check (best).
From:

Reply

Hi there

Thanks for this HOWTO, it was very informative. I picked up a problem, however. In this section:
smtpd_recipient_restrictions =
permit_sasl_authenticated,permit_mynetworks,reject_unauth_destination,check_policy_service
unix:private/policy
The entry check_policy_service unix:private/policy causes Postfix to generate the following error:
postfix/smtpd[2815]: warning: problem talking to server private/policy: Connection timed out
This may be due to policyd-weight not being installed. Deleting this entry from main.cf resolves the
issue (or presumably installing policyd-weight will solve the issue too, however, since policyd-weight is
no longer being maintained, I don't think I will go for this option.)
Regards
From: Dauto

Reply

Hi,

I follow the steps and im getting the same error:


Jan 12 18:41:52 mta01 postfix/smtpd[9392]: warning: connect to private/policy: No such file or directory
Jan 12 18:41:53 mta01 postfix/smtpd[9392]: warning: connect to private/policy: No such file or directory
Jan 12 18:41:53 mta01 postfix/smtpd[9392]: warning: problem talking to server private/policy: No such file or directory
Any help.
Regards,
Dauto
From:

Reply

Thanks for a really nice tutorial, works like a charm!

As for Fedora 9, all files are installed from standard repositories by :

yum install perl-Mail-SPF-Query perl-Mail-SPF


The postfix-policyd-spf script lives in the perl-Mail-SPF package as

/usr/share/doc/perl-Mail-SPF-Query-1.999.1/examples/postfix-policyd-spf

I just copied this file to /usr/local/libexec, making corresponding changes to master.cf.

From: NicuAdrian

Reply

greylisting and SPF-policyd-perl work together?


From: Alv

Reply

If you get error like this:


warning: problem talking to server private/policy-spf: No such file or directory

You should check name of policy in master.cf. In this howto is name in master.cf

policy unix - ........

but in main.cf is policy-spf. So easily rename to policy-spf in master.cf to


policy-spf unix - ........

From: Bogdan

Reply

Hey there, is it me or between the updates for ISPConfig 3 (from 3.0.5.2 to 3.0.5.3 for example) the

Postfix main.cf file is modified and in smtpd_recipient_restrictions the check_policy_service


unix:private/policy option is missing after an update ?

10/5/2016 11:48 AM

How To Implement SPF In Postfix

7 of 7

https://www.howtoforge.com/postfix_spf

I am using Ubuntu 12.04.3 LTS x64, with your guide for ISPConfig and I've noticed that twice.
Thanks !
From: Ethan

Reply

I also had to install the CPAN module Sys::Hostname::Long.

By the way, it makes sense to test the script BEFORE editing main.cf and restarting postfix, to make
sure you don't lose any mails in case it doesnt work.
From: Clinton

Reply

Note that postfix-policyd-spf-perl is maintenance-only. For current development, see python-postfixpolicyd-spf, also at http://www.openspf.org/Software
From: Pat

Reply

useful info, thanks.

Tutorials

How To Implement SPF In Postfix

Xenforo skin by Xenfocus


Howtoforge projektfarm GmbH.

Contact

Help

Imprint

Tutorials

Top
Terms

10/5/2016 11:48 AM

You might also like