Hardening Postfix For ISPConfig 3

Want to support HowtoForge? Become a subscriber!
Submitted by pititis (Contact Author) (Forums) on Wed, 2012-02-01 17:25. :: Anti-Spam/Virus | ISPConfig | Linux | Control Panels | Email | Postfix

Hardening Postfix For ISPConfig 3

Author: Jesús Córdoba
Email: j.cordoba [at] gmx [dot] net
Forum user: pititis

Version: 1.2

The goal of this tutorial is to harden the mail server postfix used by ISPConfig for internet mail servers where authenticated users are trusted. With this setup you will reject a great amount of spam before it passes into your mail queue, saving a lot of system resources and making your mail server strong against spammers and spam botnets. Let's go.


Reverse DNS, (DNS PTR Record)

To set up rdns you will find two situations:

- Your ISP allows to you change it yourself. Take a look in your control panel.

- Your ISP doesn’t allow to you change it. Just send an email with your request.

Ask or point your rdns record to your server. i.e server.example.com You can check your rdns with the command host:

root@server / # host

69.64- domain name pointer pub2.kernel.org.

Remember dns must propagate the changes.


SPF For Your Domain (DNS TXT Record)

SPF is an email validation system designed to prevent email spam by detecting email spoofing, a common vulnerability, by verifying sender IP addresses.

To set up spf you will need to add a TXT record to your dns zone but first you can generate your record here: http://www.mailradar.com/spf/

Copy the spf result, then go to ISPConfig -> dns -> zones ->click on your domain name -> click on records tab -> and click on TXT

Hostname -> example.com. (with dot at the end!)

Text -> Paste here the spf result (without " ").

Example: v=spf1 a mx ptr ip4:11.222.333.444 -all        …and click on Save.

Remember dns must propagate the changes.


Postfix main.cf

Let's add/change something to /etc/postfix/main.cf

Helo restrictions:

smtpd_helo_required = yes
smtpd_helo_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_helo_hostname, reject_invalid_helo_hostname

Helo restrinctions in action:

Jan 12 01:57:08 server postfix/smtpd[4687]: NOQUEUE: reject: RCPT from unknown[]: 450 4.7.1 Client host rejected: cannot find your hostname, []; from=
<pamela_nathan@ixxxxxs.com.au> to=<boricua@domain.com> proto=ESMTP helo=<[]>
Jan  8 00:32:22 server postfix/smtpd[17504]: NOQUEUE: reject: RCPT from 201-93-87-2.dial-up.telesp.net.br[]: 504 5.5.2 <lan-32204df3031>: Helo command rejected: need fully-qualified hostname; from=<nils-allan.lindgren@dexxxxxe.ca> to=<boricua@domain.com> proto=ESMTP helo=<lan-32204df3031>

Strict rfc:

strict_rfc821_envelopes = yes

Clients restrictions:

smtpd_client_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unknown_client_hostname, check_client_access mysql:/etc/postfix/mysql-virtual_client.cf

Recipient restrictions:

smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, check_recipient_access mysql:/etc/postfix/mysql-virtual_recipient.cf, reject_unauth_destination, reject_unknown_recipient_domain

Data restrictions:

smtpd_data_restrictions = reject_unauth_pipelining

Smtpd delay:

smtpd_delay_reject = yes

Don’t forget reload postfix:

/etc/init.d/postfix reload


SPF Check For Postfix (Debian And Ubuntu)

Intstall spf package:

apt-get install postfix-policyd-spf-python


apt-get install postfix-policyd-spf-perl

Add this to /etc/postfix/main.cf :

policy-spf_time_limit = 3600s

and add check_policy_service unix:private/policy-spf at the end of smtpd_recipient_restrictions:

smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, check_recipient_access mysql:/etc/postfix/mysql-virtual_recipient.cf, reject_unauth_destination, reject_unknown_recipient_domain, check_policy_service unix:private/policy-spf

Now edit master.cf and add at the end this (for the python version):

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

or this for the perl version:

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

…reload postfix.

/etc/init.d/postfix reload

Spf check in action:

Jan  4 15:50:11 server postfix/smtpd[19096]: NOQUEUE: reject: RCPT from g230068165.adsl.alicedsl.de[]: 550 5.7.1 <william@domain.org>: Recipient address rejected: Message rejected due to: SPF fail - not authorized. Please see http://www.openspf.org/Why?s=helo;id=paxxxxxn.com;ip=;r=william@domain.com; from=<opaquenesszv91@paxxxxxn.com> to=<william@domain.com> proto=ESMTP helo=



Greylisting is a method of defending email users against spam. A mail transfer agent (MTA) using greylisting will "temporarily reject" any email from a sender it does not recognize. If the mail is legitimate the originating server will, after a delay, try again and, if sufficient time has elapsed, the email will be accepted.

Installing postgrey (Debian, Ubuntu):

apt-get install postgrey

The configuration options are in /etc/default/postgrey ( default delay is 5 min).

Edit main.cf and add check_policy_service inet: to the end of smtpd_recipient_restrictions:

smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, check_recipient_access mysql:/etc/postfix/mysql-virtual_recipient.cf, reject_unauth_destination, reject_unknown_recipient_domain, check_policy_service unix:private/policy-spf,check_policy_service inet:

…reload postfix:

/etc/init.d/postfix reload

Greylist in action:

Jan 10 17:38:57 server postfix/smtpd[21302]: NOQUEUE: reject: RCPT from mailout-de.gmx.net[]: 451 4.7.1 <admin@domain.com>: Recipient address rejected: Greylisting in effect, please come back later; from=<joe@gmx.net> to=<admin@domain.com> proto=SMTP helo=<mailout-de.gmx.net>


DNSBL (DNS Based Blacklist/Blocklist)

A DNSBL is a list of ip addresses published through the Internet Domain Name Service (DNS) either as a zone file that can be used by DNS server software, or as a live DNS zone that can be queried in real-time. DNSBLs are most often used to publish the addresses of computers or networks linked to spamming; most mail server software can be configured to reject or flag messages which have been sent from a site listed on one or more such lists. These may include listing the addresses of zombie computers or other machines being used to send spam, listing the addresses of ISPs who willingly host spammers, or listing addresses which have sent spam to a honeypot system. To use dnsbl with postix we use reject_rbl_client. Just add some live dns zone for queries into the main.cf file.

In my example I will use two lists with very good reputation (added to the end of smtpd_client_restrictions):

smtpd_client_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unknown_client_hostname, check_client_access mysql:/etc/postfix/mysql-virtual_client.cf,  reject_rbl_client cbl.abuseat.org,  reject_rbl_client b.barracudacentral.org

rbl in action:

Jan 12 01:52:42 server postfix/smtpd[4616]: NOQUEUE: reject: RCPT from 89.pool85-49-26.dynamic.orange.es[]: 554 5.7.1 Service unavailable; Client host [] blocked using cbl.abuseat.org; Blocked - see http://cbl.abuseat.org/lookup.cgi?ip=; from=<dresschirp@fxxxxx.com> to=<william@domain.com> proto=SMTP helo=<colossus.home>
Jan 11 20:13:58 server postfix/smtpd[29591]: NOQUEUE: reject: RCPT from 93-87-122-56.dynamic.isp.telekom.rs[]: 554 5.7.1 Service unavailable; Client host [] blocked using b.barracudacentral.org; http://www.barracudanetworks.com/reputation/?pr=1&ip=; from=
<trundlesd@ukxxxxx.edu> to=<infoo@domain.com> proto=ESMTP helo=


Note: This feature is available in Postfix 2.8 and up

The Postfix postscreen daemon provides additional protection against mail server overload. One postscreen process handles multiple inbound SMTP connections, and decides which clients may talk to a Postfix SMTP server process. By keeping spambots away, postscreen leaves more SMTP server processes available for legitimate clients, and delays the onset of server overload conditions.

The main challenge for postscreen is to make an is-it-a-zombie decision based on a single measurement. This is necessary because many zombies try to fly under the radar and avoid spamming the same site repeatedly. Once postscreen decides that a client is not-a-zombie, it whitelists the client temporarily to avoid further delays for legitimate mail.

We will use for this tutorial the default settings with an exception. These settings are fine for the most situations

First, we add a line to main.cf with the command:

postconf -e postscreen_greet_action = enforce

Second we add postscreen and some new services to master.cf Note: These settings can already exists, just uncomment. Also be sure that the line "smtp inet ... smtpd", including any parameter is commented out (if any, parameters must be moved to the new smtpd service).

# Postfix master process configuration file.  For details on the format
# of the file, see the master(5) manual page (command: "man 5 master").
# Do not forget to execute "postfix reload" after editing this file.
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)   (never) (100)
# ==========================================================================
#smtp      inet  n       -       -       -       -       smtpd
#          -o ...
smtpd     pass  -       -       n       -       -       smtpd
     -o ... # Parameters moved from smtp service to the new smtpd service.(if any)
smtp      inet  n       -       n       -       1       postscreen
tlsproxy  unix  -       -       n       -       0       tlsproxy
dnsblog   unix  -       -       n       -       0       dnsblog

Now, we reload postfix:

/etc/init.d/postfix reload

Please do not use the comment function to ask for help! If you need help, please use our forum.
Comments will be published after administrator approval.
Submitted by cbj4074 (registered user) on Wed, 2014-07-09 20:56.

In the postscreen section, isn't this line erroneous?


postconf -e postscreen_greet_action = enforce


You state to place this line in main.cf, but you seem to have prepended the directive with "postconf -e", which is not valid syntax in the context of main.cf.

The line should be:


postscreen_greet_action = enforce

Submitted by cbj4074 (registered user) on Wed, 2013-06-05 22:24.
Regarding the smtpd_recipient_restrictions list that is recommended in the How-To, the Postfix author himself (Wietse Venema) states very clearly that reject_unauth_destination should always come before check_recipient_access in order to prevent unexpected open-relay problems. The order should be:

smtpd_recipient_restrictions =
check_recipient_access mysql:/etc/postfix/mysql-virtual_recipient.cf

For the original discussion, see http://archives.neohapsis.com/archives/postfix/2013-06/0053.html .
Submitted by cbj4074 (registered user) on Mon, 2013-06-03 19:41.

Thanks, pititis! Just about every Postfix user should benefit from this How-To. The default configuration is hardly suitable for most real-world scenarios (and I understand why the Postfix authors have set the defaults as they have; I'm not blaming them).

While perhaps outside the scope of this How-To, another measure I have taken that has cut-down on spam-related activity considerably is switching-on fail2ban's Postfix filter, which essentially bans IP addresses (via iptables) whenever they elicit a 554 response code. (Actually, I added banning for 504 responses, too, as no legitimate user should experience one in my particular environment.) This measure ensures that the same remote hosts do not hammer on Postfix with illegitimate garbage for extended periods of time.

Thanks again!

Submitted by pititis (registered user) on Tue, 2013-05-28 00:22.
Removed reject_unknown_helo_hostname  from helo restrictions. It causes several false positives from legitimate clients with dns problems/misconfiguration.
Submitted by pedrovalmor (registered user) on Fri, 2013-06-21 14:43.
I think is reject_invalid_helo_hostname right? thanks! great tutorial.
Submitted by cbj4074 (registered user) on Wed, 2014-07-09 21:00.

They are two different directives:

reject_invalid_helo_hostname (with Postfix < 2.3: reject_invalid_hostname)

Reject the request when the HELO or EHLO hostname is malformed. Note: specify "smtpd_helo_required = yes" to fully enforce this restriction (without "smtpd_helo_required = yes", a client can simply skip reject_invalid_helo_hostname by not sending HELO or EHLO). 
The invalid_hostname_reject_code specifies the response code for rejected requests (default: 501).

reject_unknown_helo_hostname (with Postfix < 2.3: reject_unknown_hostname)

Reject the request when the HELO or EHLO hostname has no DNS A or MX record. 
The unknown_hostname_reject_code parameter specifies the numerical response code for rejected requests (default: 450). 
The unknown_helo_hostname_tempfail_action parameter specifies the action after a temporary DNS error (default: defer_if_permit). Note: specify "smtpd_helo_required = yes" to fully enforce this restriction (without "smtpd_helo_required = yes", a client can simply skip reject_unknown_helo_hostname by not sending HELO or EHLO).

Submitted by vwpete (registered user) on Tue, 2013-03-05 04:47.
Spam was really a problem, this has really solved the prob. Thanx loads
Submitted by pititis (registered user) on Fri, 2012-09-14 01:38.
Added postscreen to the tutorial.
Submitted by jan-paul (registered user) on Mon, 2012-09-10 22:58.

I Implemented all these nice features in my mailserver now.

Now I also want postscreen to work properly but it just won't work for me. I followed the instructions on postfix.org (postscreen README) but as soon as I change the line:
smtp      inet  n       -       -       -       -       smtpd
smtp      inet  n       -       n       -       1       postscreen
I can't send any emails from my POP3 email client anymore.

Sure hope that you can shine more light on postscreen for ISPConfig3 too.

Submitted by Anonymous (not registered) on Sat, 2014-05-10 03:21.
You need to send email through port 587 (submission) and not anymore through port 25.
Submitted by todx (registered user) on Wed, 2012-09-05 08:58.
This tutorial helped me get rid of all spam my clients were receiving, thank you very much! Great tutotiral!
Submitted by MaddinXx (registered user) on Fri, 2012-08-17 22:56.

Very useful, thank you - especially because there's a big lack of tutorials for mailserver hardening otherwise.