Postscreen – Greylisting in Postfix
Greylisting is well known antispam technique. It’s idea is basing on fact, that spamming hosts (zombies) do not have time for re-transmission and are trying to send maximum amount of spam in shortest time period. This is achieved by connections to different mail servers and submission of message even without wait for server’s response. In opposition to that, legitimate mail servers presents themselves and waits for server’s response, and then beginning mail submission. If they receive temporary error code (4xx) from server, they will try to submit mail again after defined time period (e.g. 5 minutes)
Implementation of Greylisting brings tangible benefits for mail system. Greylisting is able to filter even above 90% incoming traffic to mail server, and it’s done on session level, which is huge benefit for system performance, because no resources are wasted for mail processing. General rule is to filter junk mail as soon as possible, so if we can filter this on session level we shouldn’t waste time and resources to antivirus and antispam. Cons of Greylisting is that incoming messages have few minutes of latency, because client’s server needs to repeat transmission. False positives are very rare and mostly comes from misconfiguration of sending server.
One of wide known and used solutions for Greylisting is Postgrey – Postfix Greylisting Policy Server written by David Schweikert. This is a Perl software, which we successfully used for few years. Actually we switched to Postscreen which is embedded in new version of Postfix.
Postscreen configuration is simple and well described in Postscreen HOWTO. To enable this mechanism and see how it works without enabling Greylisting you need only to add few lines to Postfix configuration (in main.cf
) and modify master.cf
– smtp
service needs to be changed to be served by postscreen
. See below:
#smtp inet n - - - - smtpd smtp inet n - - - 1 postscreen smtpd pass - - - - - smtpd dnsblog unix - - - - 0 dnsblog tlsproxy unix - - - - 0 tlsproxy
Create postscreen_access.cidr
file and add to main.cf
:
postscreen_blacklist_action = ignore postscreen_access_list = permit_mynetworks cidr:/etc/postfix/postscreen_access.cidr postscreen_greet_action = ignore postscreen_greet_banner = Spammers may talk now :)
For test purpose the action is set to ignore
, so there is no impact on system, but if you do telnet mydomain.tld 25
you will see greeting like this:
Trying... Connected to mydomain.tld. Escape character is '^]'. 220-Spammers may talk now :)
And after few seconds you will receive second line:
220 mydomain.tld ESMTP Postfix
Why after few seconds? That’s because legitimate server will wait for this line, but spammers in most cases will not wait for server’s answer but will start to submit messages. If you will change ignore
to enforce
or drop
– Postscreen will start to drop these type of connections. The difference between enforce
and drop
is that enforce
will wait until tests will be finished, logging helo/sender/recipient information and rejecting with 550 code, while drop
rejects immediately with 521 code. I recommend to use enforce
, especially on beginning, to have information about sender and recipient in logs to be able to check if there is no false positives.
In this stage you can also enable DNSBL, with settings are like below, client must be listed in zen.spamhause.org
(factor 2) and in one of other DNSBL to reach threshold of 3 and be rejected. Of course factors and DNSBL servers you can set at your own.
postscreen_dnsbl_action = enforce postscreen_dnsbl_threshold = 3 postscreen_dnsbl_sites = zen.spamhaus.org*2 bl.spamcop.net*1 b.barracudacentral.org*1
You should see similar entries in log after Postfix restart:
Aug 17 15:30:40 mydomain.tld postfix/postscreen[31984]: CONNECT from [41.205.39.169]:4308 Aug 17 15:30:40 mydomain.tld postfix/dnsblog[32089]: addr 41.205.39.169 listed by domain zen.spamhaus.org as 127.0.0.11 Aug 17 15:30:40 mydomain.tld postfix/dnsblog[32089]: addr 41.205.39.169 listed by domain zen.spamhaus.org as 127.0.0.4 Aug 17 15:30:40 mydomain.tld postfix/dnsblog[32088]: addr 41.205.39.169 listed by domain b.barracudacentral.org as 127.0.0.2 Aug 17 15:30:40 mydomain.tld postfix/dnsblog[32088]: addr 41.205.39.169 listed by domain bl.spamcop.net as 127.0.0.2 Aug 17 15:30:46 mydomain.tld postfix/postscreen[31984]: DNSBL rank 4 for [41.205.39.169]:4308 Aug 17 15:30:49 mydomain.tld postfix/postscreen[31984]: NOQUEUE: reject: RCPT from [41.205.39.169]:4308: 550 5.7.1 Service unavailable; client [41.205.39.169] blocked using zen.spamhaus.org; from=..., to=..., proto=ESMTP, helo=Aug 17 15:30:49 mydomain.tld postfix/postscreen[31984]: HANGUP after 3.2 from [41.205.39.169]:4308 in tests after SMTP handshake Aug 17 15:30:49 mydomain.tld postfix/postscreen[31984]: DISCONNECT [41.205.39.169]:4308
A client which will not reach a threshold defined in postscreen_dnsbl_threshold
, will obtain a status PASS NEW
:
Aug 17 16:12:43 mydomain.tld postfix/postscreen[2391]: CONNECT from [173.232.32.14]:45116 Aug 17 16:12:43 mydomain.tld postfix/dnsblog[2416]: addr 173.232.32.14 listed by domain b.barracudacentral.org as 127.0.0.2 Aug 17 16:12:49 mydomain.tld postfix/postscreen[2391]: PASS NEW [173.232.32.14]:45116 Aug 17 16:22:26 mydomain.tld postfix/smtpd[2919]: connect from unknown[173.232.29.251] Aug 17 16:22:26 mydomain.tld postfix/smtpd[2919]: 69AD180A94: client=unknown[173.232.29.251]
A client which was already noticed as legitimate and wants to submit another message will pass with status PASS OLD
:
Aug 17 16:51:53 mydomain.tld postfix/postscreen[4493]: CONNECT from [213.134.151.158]:45226 Aug 17 16:51:59 mydomain.tld postfix/postscreen[4493]: PASS OLD [213.134.151.158]:45226 Aug 17 16:52:00 mydomain.tld postfix/smtpd[4496]: connect from mail.silfarm.com.pl[213.134.151.158] Aug 17 16:52:00 mydomain.tld postfix/smtpd[4496]: 41B1780295: client=mail.silfarm.com.pl[213.134.151.158]
Postscreen has also ability known as deep_protocol_test
. Detailed description you can find in documentation. If client will pass these tests then it’s added to temporary whitelist, but this time is rejected with temporary failure error code 4XX. If client will connect once again then will be allowed to submission. Embedded in Postscreen SMTP engine doesn’t have AUTH, XCLIENT and XFORWARD implementation. Support for AUTH can be implemented in newer versions. In the meantime, when these services needs to be available on port 25, you shouldn’t enable deep protocol test. But good practice is to configure submission on port 587 (with TLS) or 465 with SSL, so deep_protocol_test
can be enabled and should not have impact on mail system. To enable it you need to add some configuration directives to (main.cf
):
postscreen_pipelining_action = enforce postscreen_pipelining_enable = yes postscreen_non_smtp_command_action = enforce postscreen_non_smtp_command_enable = yes postscreen_bare_newline_action = enforce postscreen_bare_newline_enable = yes
After Postfix restart is worthwhile – as always – to check logs and observe if system is working as expected. Description of particular tests is in mentioned documentation.
I wanted to know how to configure postscreen’s greylisting feature, which unforunately isn’t addressed here.