In previous tutorials, we discussed how to set up a mail server from scratch on Linux (Ubuntu version, CentOS/RHEL version). This tutorial is going to show you how to enable and configure Postscreen in Postfix SMTP server. Postscreen is an SMTP filter that blocks spambots (or zombie machines) away from the real Postfix smtpd daemon, so Postfix does not feel overloaded and can process legitimate emails more efficiently.
Note: If you are using iRedMail or Modoboa, then Postscreen is enabled by default on your server. Still, you will learn something new.
Reducing SMTP Server Overload
By default, Postfix can spawn up to 100 SMTP server processes to handle SMTP client connections. You can check the process limit by running the following command.
postconf default_process_limit
Sample output:
default_process_limit = 100
If spambots are constantly hitting your Postfix SMTP server, then there will be less Postfix SMTP server processes to accept legitimate email messages. And when the number of SMTP clients exceeds the number of Postfix SMTP server processes, other SMTP clients must wait until an SMTP server process becomes available.
By blocking spambots with Postscreen, we can save SMTP server processes for legitimate SMTP clients. Postscreen is designed as a first layer of defense against spammers. It is implemented as a single process listening on port 25 and can handle multiple inbound SMTP connections. It’s fast and lightweight, compared to using other SMTP-level access checks.
Measurements Used By Postscreen Against Spambots
Most spambots have faulty SMTP protocol implementation. Postscreen can take advantage of this fact and use several measurements to block spambots.
- Pregreet test. If the SMTP client speaks before its turn, stop the connection.
- Realtime blacklist check. If the SMTP client’s IP address is on a blaclist, such as Spamhaus, stop the connection.
- Deep protocol test.
Step 1: Enable Postscreen in Postfix
Postscreen is first introduced in Postfix 2.8. If you are using any current Linux distribution, you should have Postfix 3.0 or above. To check your Postfix version, run
postconf mail_version
Sample output:
mail_version = 3.3.0
Edit the Postfix master configuration file.
sudo nano /etc/postfix/master.cf
Comment out the following line.
smtp inet n - y - - smtpd
Then uncomment the following 4 lines.
smtp inet n - y - 1 postscreen smtpd pass - - y - - smtpd dnsblog unix - - y - 0 dnsblog tlsproxy unix - - y - 0 tlsproxy
Where:
- The first two lines enables Postscreen. Both Postscreen and the smtpd daemon will be listening on port 25. Postscreen will check the SMTP client first and then pass the connection to smtpd daemon.
- The dnsblog (DNS Blacklist Logger) service enables logging of DNS blacklist checks.
- The tlsproxy service enables STARTTLS support for postscreen, so remote SMTP clients can establish encrypted connection when Postscreen is enabled.
Save and close the file. (Don’t restart Postfix just yet.)
Create Permanent Whitelist/Blacklist
Edit the Postfix main configuration file.
sudo nano /etc/postfix/main.cf
We need to add our own IP addresses to Postscreen whitelist, so that our own SMTP requests won’t be tested by Postscreen. Add the following two lines at the end of the file.
postscreen_access_list = permit_mynetworks cidr:/etc/postfix/postscreen_access.cidr postscreen_blacklist_action = drop
Save and close the file. The permit_mynetworks
value will whitelist any IP address listed in the mynetworks
parameter. To check the value of mynetworks
, run
postconf mynetworks
Sample output:
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
You can also manually add additional IP addresses in the /etc/postfix/postscreen_access.cidr
file.
sudo nano /etc/postfix/postscreen_access.cidr
You might want to whitelist your mail server’s public IPv4 and IPv6 address. So I add the following lines in the file. Replace the IP addresses with your own. Note that you need to use the CIDR notation: For a single IPv4 address, add /32
at the end; For a single IPv6 address, add /128
at the end.
#permit my own IP addresses. 23.254.225.226/32 permit 2a0d:7c40:3000:b8b::2/128 permit
If your mail server also runs a VPN server, you may want to add the VPN server’s address to the whitelist. For example, my VPN server uses the 10.10.10.1 private IP address, so I add the following line in the file.
10.10.10.1/32 permit
If you want to permanently blacklist an IP address, you can do so like below.
12.34.56.78/32 reject
Save and close the file. Restart Postfix for the changes to take effect.
sudo systemctl restart postfix
Note: Postscreen listens on port 25 only, so authenticated users from port 587 or 465 won’t be affected by Postscreen.
Postscreen itself also maintains a dynamic whitelist to minimize the delay for legitimate emails, defined by the postscreen_cache_map
parameter.
postconf postscreen_cache_map
Sample output:
postscreen_cache_map = btree:$data_directory/postscreen_cache
Each IP address in the dynamic whitelist has a lifetime.
Step 2: Pregreet Test
There is a pregreet test in Postscreen to detect spam. As you may already know, in SMTP protocol, the receiving SMTP server should always declare its hostname before the sending SMTP server does so. Some spammers violate this rule and declare their hostnames before the receiving SMTP server does.
By default, Postscreen enables the pregreet test, but won’t do anything with the test result. As you can see from the following lines in my mail log (/var/log/mail.log
or /var/log/maillog
), the “PREGREET” text indicates the SMTP client declared its hostname first, but Postscreen still passed the connection to Postfix smtpd daemon.
mail postfix/postscreen[24075]: CONNECT from [156.96.118.171]:62604 to [23.254.225.226]:25
mail postfix/postscreen[24075]: PREGREET 11 after 0.07 from [156.96.118.171]:62604: EHLO Userrn
mail postfix/smtpd[24076]: connect from unknown[156.96.118.171]
mail postfix/smtpd[24076]: disconnect from unknown[156.96.118.171] ehlo=1 quit=1 commands=2
To reject SMTP clients that violate this rule, edit the Postfix main configuration file.
sudo nano /etc/postfix/main.cf
Add the following line at the end.
postscreen_greet_action = enforce
Save and close the file. Then restart Postfix.
sudo systemctl restart postfix
From now on, Postscreen will stop connection if an SMTP client violate this rule. As you can see the from the following log, Postscreen stopped the connection, so the spammer doesn’t have a chance to harass the smtpd daemon.
mail postfix/postscreen[6471]: CONNECT from [192.241.239.123]:48014 to [23.254.225.226]:25 mail postfix/postscreen[6471]: PREGREET 19 after 0 from [192.241.239.123]:48014: EHLO zg-0131a-136rn mail postfix/postscreen[6471]: DISCONNECT [192.241.239.123]:48014
Postscreen still allow other tests to complete before stopping the connection. If you prefer to drop the connection immediately without doing other tests, use the following setting instead.
postscreen_greet_action = drop
Step 3: Using Public Blacklists & Whitelists
The postscreen_dnsbl_sites
parameter can be used to check SMTP client’s IP address against public blacklists (DNSBL). You might be already using Postfix smtpd’s reject_rbl_client
to reject an SMTP client if its IP address is on a public blacklist. However, that can cause false positives because an innocent SMTP server’s IP address could be on a blacklist for whatever reason, even if you use permit_dnswl_client
to also check against public whitelist (DNSWL).
To reduce false positives, Postscreen allows you to check multiple blacklists and add weight factor to each blacklist. For example, if an IP address is on Spamhaus blacklist, add 3 points; if an IP address is on the BarracudaCentral blacklist, add 2 points. If the combined score is high enough (defined by postscreen_dnsbl_threshold
), reject the SMTP client. This scoring system is similar to that of SpamAssassin.
In the following configuration, we set the threshold to 3 points. Spamhaus has weight of 3. BarracudaCentral has weight of 2. SpamCop has weight of 1. If the combined score is equal to or greater than 3, Postscreen would reject the SMTP client.
postscreen_dnsbl_threshold = 3 postscreen_dnsbl_action = enforce postscreen_dnsbl_sites = zen.spamhaus.org*3 b.barracudacentral.org=127.0.0.[2..11]*2 bl.spameatingmonkey.net*2 bl.spamcop.net dnsbl.sorbs.net
We can also use postscreen_dnsbl_sites
to check SMTP client’s IP address against public whitelist (DNSWL). If a client’s IP address is on whitelist, add a negative score.
postscreen_dnsbl_sites = zen.spamhaus.org*3 bl.spameatingmonkey.net*2 dnsbl.habl.org bl.spamcop.net dnsbl.sorbs.net swl.spamhaus.org*-4, list.dnswl.org=127.[0..255].[0..255].0*-2, list.dnswl.org=127.[0..255].[0..255].1*-4, list.dnswl.org=127.[0..255].[0..255].[2..255]*-6
If you use Postfix smtpd’s reject_rbl_client
or permit_dnswl_client
parameter, you should delete them now, so smtpd daemon won’t perform IP checks again after Postscreen. Postscreen doesn’t check domain name based blacklist/whitelist, so we should continue using reject_rhsbl to perform domain name lookup on public blacklists.
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, ... ... reject_rhsbl_helo dbl.spamhaus.org, reject_rhsbl_reverse_client dbl.spamhaus.org, reject_rhsbl_sender dbl.spamhaus.org,
Save and close the Postfix main configuration file. Then restart Postfix for the changes to take effect.
sudo systemctl restart postfix
Note: If see the following message in your mail log, it means the SMTP client’s IP address is not on the whitelist (list.dnswl.org). This is not an error.
warning: dnsblog_query: lookup error for DNS query 161.223.143.185.list.dnswl.org: Host or domain name not found. Name service error for name=161.223.143.185.list.dnswl.org type=A: Host not found, try again
If it’s on the whitelist, the message will look something like this:
postfix/dnsblog[21188]: addr xx.xx.xx.xx listed by domain list.dnswl.org as 127.0.10.0
Also note that BarracudaCentral Blocklist requires registration, which is free of charge. After creating an account, simply add the IP address of your DNS resolver and you are done.
Some Dead/Closed DNSBL sites
You should not use dead or closed DNSBL sites, or your mail server will reject legitimate emails.
- dnsbl.njabl.org: has been offline since 2013.
- dnsbl.ahbl.org: Public access to the list was terminated in 2015.
Running Your own Local DNS Resolver
Note that Note that you should set up a local DNS resolver on your mail server when using public blacklists and whitelists, because most of them have query limit. If you use public DNS resolver like 8.8.8.8, you will likely to reach the query limit sooner than you think.
Step 4: Enable Deep Protocol Tests
There are 3 common deep protocol tests in Postscreen:
- SMTP pipelining test
- Non-SMTP command test
- Bare newline test
Pipelining is an extension to the SMTP protocol. It allows the SMTP client to send multiple SMTP command at once without waiting for response from SMTP server. Postfix supports pipelining by default. To check, use telnet to connect to your mail server.
telnet mail.yourdomain.com 25
Then use the EHLO command to declare your hostname.
EHLO mail.google.com
The SMTP server’s response below indicates it support pipelining.
250-PIPELINING 250-SIZE 157286400 250-VRFY 250-ETRN 250-STARTTLS 250-ENHANCEDSTATUSCODES 250-8BITMIME 250 DSN
Then quit the connection.
quit
If the SMTP server doesn’t announce pipelining support, then the SMTP client should not send multiple commands at once. Add the following two lines in /etc/postfix/main.cf
file to enable pipeling test and reject SMTP clients that fail this test.
postscreen_pipelining_enable = yes postscreen_pipelining_action = enforce
As the name suggests, non-SMTP command test makes Postscreen detect SMTP clients that send non-SMTP commands. Add the following two lines in /etc/postfix/main.cf
file to reject such SMTP clients.
postscreen_non_smtp_command_enable = yes postscreen_non_smtp_command_action = enforce
The bare newlines test allows Postscreen to detect SMTP clients that end a line with , instead of the standard . Add the following two lines in /etc/postfix/main.cf
file to reject such SMTP clients.
postscreen_bare_newline_enable = yes postscreen_bare_newline_action = enforce
Save and close the file. Then restart Postfix for the changes to take effect.
sudo systemctl restart postfix
The Greylisting Effect of Deep Protocol Tests
The limitation of deep protocol tests is that Postscreen would disconnect new SMTP clients no matter the tests are passed or not. Postscreen disconnects each client with the following message:
450 4.3.2 Service currently unavailable
And the client must try again later from the same IP address. This is effectly a form of greylisting, so you need to disable other forms of greylisting. For example, if you followed my previous tutorial to use Postgrey as the greylisting policy server, then find the following line in /etc/postfix/main.cf
file and comment it out.
check_policy_service inet:127.0.0.1:10023,
Save and close the file. Then restart Postfix.
sudo systemctl restart postfix
How to Minimize Bad User Expericence
Greylisting is rather annoying for the end user, as the user has to wait another several minutes for the email to arrive. To minimize this bad experience, there are 3 ways I can think of when using Postscreen deep protocol tests.
- Create a second MX record that points to the same IP address.
- If an SMTP client’s IP address is in a public whitelist, skip the deep protocol tests.
- Using Postwhite to add known good IP address to the Postscreen whitelist.
Create a second MX record that points to the same IP address
You can specify more than one MX record for your domain name like below.
Record Type Name Mail Server Priority MX @ mail.yourdomain.com 0 MX @ mail2.yourdomain.com 5
The sender will try the first mail server (with priority 0). If mail.yourdomain.com rejects email by greylisting, then the sender would immediately try the second mail server (with priority 5).
Greylisting in Postscreen doesn’t have a delay time like in Postgrey. If the two mail server hostnames have the same IP address, then when the sender tries the second mail server hostname, the email will be accepted immediately (if all other checks pass) and end users will not notice email delay caused by greylisting.
Note that not all mail servers would immediately try the second MX host. Some mail servers like Gmail would use a different IP address to try again, which of course will be rejected again. Postfix would try the second MX host by default. I don’t know if it’s also the case with Exim. If you run Exim SMTP server, please comment below.
Skip Deep Protocol Tests If an SMTP Client’s IP Address is on a Public Whitelist
Gmail will never retry sending email from the same IP address. However, Gmail’s IP address is on list.dnswl.org. We can tell Postscreen to ignore such SMTP clients. Add the following line in the /etc/postfix/main.cf
file to ignore clients whose score is equal to -2 or below.
postscreen_dnsbl_whitelist_threshold = -2
Restart Postfix for the changes to take effect.
sudo systemctl restart postfix
The following message in my mail log indicates Postscreen didn’t perform deep protocol tests and passed the connection to smtpd daemon because Gmail’s IP address is on the public whitelist.
Feb 10 10:31:14 mail postfix/postscreen[16579]: CONNECT from [209.85.166.44]:38543 to [144.91.93.31]:25 Feb 10 10:31:14 mail postfix/dnsblog[16582]: addr 209.85.166.44 listed by domain list.dnswl.org as 127.0.5.0 Feb 10 10:31:15 mail postfix/postscreen[16579]: PASS NEW [209.85.166.44]:38543 Feb 10 10:31:15 mail postfix/smtpd[16639]: connect from mail-io1-f44.google.com[209.85.166.44]
As a matter of fact, most major mailbox providers (Gmail, Hotmail, Outlook, Yahoo Mail, GMX Mail, ProtonMail, etc) are whitelisted on list.dnswl.org. It also includes mail servers in other industries, as can be seen on dnswl.org.
- 2 – Financial services
- 3 – Email Service Providers
- 4 – Organisations (both for-profit [ie companies] and non-profit)
- 5 – Service/network providers
- 6 – Personal/private servers
- 7 – Travel/leisure industry
- 8 – Public sector/governments
- 9 – Media and Tech companies
- 10 – some special cases
- 11 – Education, academic
- 12 – Healthcare
- 13 – Manufacturing/Industrial
- 14 – Retail/Wholesale/Services
- 15 – Email Marketing Providers
- 20 – Added through Self Service without specific category
So using postscreen_dnsbl_whitelist_threshold
will help you skip greylisting most of the time.
Using Postwhite
Postwhite is a script written by Steve Jenkins to automatically generate a static IP whitelist for Postscreen by using the published SPF records of known webmailers, social networks, ecommerce providers, and compliant bulk senders. Note that this whitelist would make Postscreen skip all tests (pregreet test, public blacklist/whitelist check, deep protocol tests) for the whitelisted IP addresses, so it will help reduce the load Postscreen and save DNS requests to public blacklists/whitelists.
To use Postwhite, first cd to /usr/local/bin/
.
cd /usr/local/bin/
Install git.
sudo apt install git
or
sudo dnf install git
Clone the SPF-Tools and Postwhite Github repository.
sudo git clone https://github.com/spf-tools/spf-tools.git sudo git clone https://github.com/stevejenkins/postwhite.git
Copy the postwhite.conf
file to /etc/
.
sudo cp /usr/local/bin/postwhite/postwhite.conf /etc/
Run Postwhite.
sudo /usr/local/bin/postwhite/postwhite
The whitelist will be save as /etc/postfix/postscreen_spf_whitelist.cidr
. Edit Postfix main configuration file.
sudo nano /etc/postfix/main.cf
Find the following line.
postscreen_access_list = permit_mynetworks cidr:/etc/postfix/postscreen_access.cidr
Add the new whitelist file.
postscreen_access_list = permit_mynetworks cidr:/etc/postfix/postscreen_access.cidr cidr:/etc/postfix/postscreen_spf_whitelist.cidr
Save and close the file. Then restart Postfix for the changes to take effect.
sudo systemctl restart postfix
Edit the root user’s crontab file.
sudo crontab -e
Add the following two lines at the end to regularly update the whitelist.
@daily /usr/local/bin/postwhite/postwhite > /dev/null 2>&1 #Update Postscreen Whitelists @weekly /usr/local/bin/postwhite/scrape_yahoo > /dev/null 2>&1 #Update Yahoo! IPs for Postscreen Whitelists
Save and close the file. Now if you send an email from Gmail to your own domain email address, and check the mail log, you will find Postscreen doesn’t perform any tests, because the IP address is whitelisted.
Feb 10 13:04:17 mail postfix/postscreen[24895]: CONNECT from [209.85.166.44]:38257 to [144.91.93.31]:25 Feb 10 13:04:17 mail postfix/postscreen[24895]: WHITELISTED [209.85.166.44]:38257 Feb 10 13:04:17 mail postfix/smtpd[26596]: connect from mail-io1-f44.google.com[209.85.166.44]
Postfix Log Report
Pflogsumm
is a great tool to create a summary of Postfix logs. Install it on Ubuntu with:
sudo apt install pflogsumm
On CentOS/RHEL, pflogsumm is provided by the postfix-perl-scripts
package.
sudo dnf install postfix-perl-scripts
Use the following command to generate a report for today. (Note that on CentOS/RHEL, the mail log file is /var/log/maillog
.)
sudo pflogsumm -d today /var/log/mail.log
Generate a report for yesterday.
sudo pflogsumm -d yesterday /var/log/mail.log
If you like to generate a report for this week.
sudo pflogsumm /var/log/mail.log
To emit “problem” reports (bounces, defers, warnings, rejects) before “normal” stats, use --problems-first
flag.
sudo pflogsumm -d today /var/log/mail.log --problems-first
To append the email from address to each listing in the reject report, use --rej-add-from
flag.
sudo pflogsumm -d today /var/log/mail.log --rej-add-from
To show the full reason in reject summaries, use --verbose-msg-detail
flag.
sudo pflogsumm -d today /var/log/mail.log --rej-add-from --verbose-msg-detail
You can add a cron job to make pflogsumm to send a report to your email address every day.
sudo crontab -e
Add the following line, which will generate a report every day at 4:00 AM.
0 4 * * * /usr/sbin/pflogsumm -d yesterday /var/log/mail.log --problems-first --rej-add-from --verbose-msg-detail -q
To receive the report via email, add the following line above all cron jobs.
MAILTO="[email protected]"
You should pay attention to the message reject detail
section, where you can see for what reason those emails are rejected and if there’s any false positives. Greylisting rejections are safe to ignore.
Wrapping Up
I hope this tutorial helped you use Postscreen to block spambots. As always, if you found this post useful, then subscribe to our free newsletter to get more tips and tricks. Take care 🙂
Rate this tutorial
[Total: 0 Average: 0]