RBL

------

Tips for Blocking Email Spam with Postfix on CentOS/RHEL

ip #6: Using Public Realtime Blacklists

There are spam emails that are sent from servers that has a valid hostname, valid PTR record, and can pass through greylisting. In this case, you can use blacklisting to reject spam. There are many public realtime blacklists (RBL), also known as DNSBLs (DNS based lists). By realtime, it means that the list is always changing. An IP address or domain name could be on the list today and off the list tomorrow, so you could get different results depending on when you query the list.

You can use multiple blacklists to block spam. Go to https://www.debouncer.com and mxtoolbox.com , enter the spammer’s domain and IP address to see which blacklists are blocking them, then you can use those blacklists. For example, I found that spammers are blacklisted by one of the following blacklists:

So I can add the following configurations in /etc/postfix/main.cf file. Some public blacklisting service requires a monthly fee. For now, I’m using the free service of spamhaus.org.

smtpd_recipient_restrictions =    permit_mynetworks    permit_sasl_authenticated    check_policy_service unix:private/policyd-spf    check_policy_service unix:postgrey/socket   reject_rhsbl_helo dbl.spamhaus.org   reject_rhsbl_reverse_client dbl.spamhaus.org   reject_rhsbl_sender dbl.spamhaus.org   reject_rbl_client zen.spamhaus.org

Where:

Some spammers use Google’s mail server, so reject_rhsbl_helo is ineffective, but most of them use their own domain names in the MAIL FROM header, so reject_rhsbl_sender will be effective.

Create A Whitelist

Sometimes there are legitimate email servers blacklisted. You can create a whitelist so they won’t be blocked. Create the following file.

sudo nano /etc/postfix/rbl_override

In this file, whitelist domain names like below.

dripemail2.com  OK           //This domain belongs to drip.com  mlsend.com      OK           //This domain belongs to mailerlite email marketing service

Save and close the file. Then run the following command to create the rbl_override.db file.

sudo postmap /etc/postfix/rbl_override

Edit Postfix main configuration file.

sudo nano /etc/postfix/main.cf

In smtpd_recipient_restrictions, add the following line.

check_client_access hash:/etc/postfix/rbl_override

Like below. It should be placed above other RBL checks.

smtpd_recipient_restrictions =    permit_mynetworks    permit_sasl_authenticated    check_policy_service unix:private/policyd-spf    check_policy_service unix:postgrey/socket   check_client_access hash:/etc/postfix/rbl_override    reject_rhsbl_helo dbl.spamhaus.org    reject_rhsbl_reverse_client dbl.spamhaus.org    reject_rhsbl_sender dbl.spamhaus.org    reject_rbl_client zen.spamhaus.org

Reload Postfix for the changes to take effect.

sudo systemctl reload postfix

Using Public Whitelist to Reduce False Positive

Maintaining a private whitelist is necessary sometimes, but you can also use public whitelists, the most famous of which is dnswl.org. Currently, there is only a whitelist for IP address. Domain name whitelist is in beta. To use it, put the following line in smtpd_recipient_restrictions.

permit_dnswl_client list.dnswl.org=127.0.[0..255].[1..3]

Like below. It should be placed above the reject_rbl_client check.

smtpd_recipient_restrictions =    permit_mynetworks    permit_sasl_authenticated    check_policy_service unix:private/policyd-spf    check_policy_service unix:postgrey/socket    check_client_access hash:/etc/postfix/rbl_override    reject_rhsbl_helo dbl.spamhaus.org    reject_rhsbl_reverse_client dbl.spamhaus.org    reject_rhsbl_sender dbl.spamhaus.org   permit_dnswl_client list.dnswl.org=127.0.[0..255].[1..3]    reject_rbl_client zen.spamhaus.org

Another well-known whitelist is swl.spamhaus.org, so you can also add it to your configuration.

permit_dnswl_client swl.spamhaus.org

It’s impossible for an IP address to be listed in Spamhaus whitelist and blacklist at the same time, so if you only use Spamhaus blacklist in Postfix, then it’s not necessary to check against Spamhaus whitelist.

Characteristics of Spam

Below is what I found about email spam. These spam are easy to block.

Legitimate email servers should never have these characteristics. So here comes my 7 tips, which will block 90% of spam.

Fact: Around 93%~95% of emails in the world are rejected at the SMTP gateway, never landed in the inbox or spam folder.

Tip #1: Reject Email if SMTP Client Has no PTR record

PTR record maps an IP address to a domain name. It’s the counterpart to A record. On CentOS/RHEL, you can query the domain name associated with an IP address by executing the following command:

host <IP address>

If host command can’t be found, then you need to install the bind-utils package.

sudo dnf install bind-utils

For example, the following command returns the hostname of my mail server.

host 23.254.225.226

Output:

226.225.254.23.in-addr.arpa domain name pointer mail.linuxbabe.com.

Due to the prevalence of spam, many mail servers (such as gmx.com, gmx.net, facebook.com) require that SMTP clients have valid PTR records associated with their IP addresses. Every mail server admin should set PTR record for their SMTP servers. If the SMTP client has a PTR record, you can find a line in Postfix log (/var/log/maillog) like below.

connect from mail.linuxbabe.com[23.254.225.226]

If the SMTP client doesn’t have a PTR record, then the hostname will be identified as unknown in Postfix log.

connect from unknown[120.41.196.220]

To filter out emails with no PTR records, open Postfix main configuration file.

sudo nano /etc/postfix/main.cf

Add the following line in smtpd_sender_restrictions. This directive rejects an email if the client IP address has no PTR record.

reject_unknown_reverse_client_hostname

Example:

smtpd_sender_restrictions =    permit_mynetworks    permit_sasl_authenticated    reject_unknown_reverse_client_hostname

Save and close the file. Then restart Postfix for the change to take effect.

sudo systemctl restart postfix

Tip #2: Enable HELO/EHLO Hostname Restrictions in Postfix

Some spammers don’t provide a valid HELO/EHLO hostname in the SMTP dialog. They can be non-fully qualified domain name, or a domain name doesn’t exist or only for internal network. For example, a spammer using an Amazon EC2 instance to send spam is logged on my server as follows:

Aug 16 04:21:13 email postfix/smtpd[7070]: connect from ec2-54-237-201-103.compute-1.amazonaws.com[54.237.201.103] Aug 16 04:21:13 email policyd-spf[7074]: prepend Received-SPF: None (mailfrom) identity=mailfrom; client-ip=54.237.201.103; helo=ip-172-30-0-149.ec2.internal; envelope-from=superdiem@carpaythe.tk; receiver=<UNKNOWN>

As you can see, the HELO hostname is ip-172-30-0-149.ec2.internal , which is only valid in AWS internal network. It has no valid A record nor MX record.

To enable HELO/EHLO hostname restriction, edit Postfix main configuration file.

sudo nano /etc/postfix/main.cf

First, add the following line to require the client to provide a HELO/EHLO hostname.

smtpd_helo_required = yes

Then add the following 3 lines to enable smtpd_helo_restrictions.

smtpd_helo_restrictions =      permit_mynetworks     permit_sasl_authenticated

Use the following line to reject clients who provide malformed HELO/EHLO hostname.

reject_invalid_helo_hostname

Use the following line to reject non-fully qualified HELO/EHLO hostname.

reject_non_fqdn_helo_hostname

To reject email when the HELO/EHLO hostname has neither DNS A record nor MX record, use

reject_unknown_helo_hostname

Like this:

smtpd_helo_required = yes smtpd_helo_restrictions =     permit_mynetworks     permit_sasl_authenticated     reject_invalid_helo_hostname     reject_non_fqdn_helo_hostname     reject_unknown_helo_hostname

Save and close the file. Then reload Postfix.

sudo systemctl reload postfix

Note that although most legitimate mail servers have valid A record for the HELO/EHLO hostname, occasionally a legitimate mail server doesn’t meet this requirement. You need to whitelist them with check_helo_access.

smtpd_helo_required = yes smtpd_helo_restrictions =     permit_mynetworks     permit_sasl_authenticated     check_helo_access hash:/etc/postfix/helo_access     reject_invalid_helo_hostname     reject_non_fqdn_helo_hostname     reject_unknown_helo_hostname

Then you need to create the /etc/postfix/helo_access file.

sudo nano /etc/postfix/helo_access

Whitelist legitimate mail server’s HELO/EHLO hostname like below.

optimus-webapi-prod-2.localdomain      OK va-massmail-02.rakutenmarketing.com    OK

It’s likely that you don’t know which hostnames to whitelist, then simply copy the above two lines, which is the only lines in my helo_access file. You can always add more hostnames later. Save and close the file. Then run the following command to create the /etc/postfix/helo_access.db file.

sudo postmap /etc/postfix/helo_access

And reload Postfix.

sudo systemctl reload postfix

Tip #3: Reject Email if SMTP Client Hostname doesn’t have valid A Record

A legitimate email server should also have a valid A record for its hostname. The IP address returned from A record should match the IP address of email server. To filter out emails from hosts that don’t have valid A record, edit Postfix main configuration file.

sudo nano /etc/postfix/main.cf

Add the following two lines in smtpd_sender_restrictions.

reject_unknown_reverse_client_hostname reject_unknown_client_hostname

Example:

smtpd_sender_restrictions =    permit_mynetworks    permit_sasl_authenticated    reject_unknown_reverse_client_hostname    reject_unknown_client_hostname

Save and close the file. Then restart Postfix for the change to take effect.

sudo systemctl restart postfix

Note that reject_unknown_client_hostname does not require HELO from SMTP client. It will fetch the hostname from PTR record, then check the A record.

Tip #4: Reject Email If MAIL FROM Domain Has Neither MX Record Nor A Record

The MAIL FROM address is also known as envelope from address. Some spammers use a non-existent domain in the MAIL FROM address. If a domain name has no MX record, Postfix will find the A record of the main domain and send email to that host. If the sender domain has neither MX record nor A record, Postfix can’t send email to that domain. So why not reject emails that you can’t reply to?

To filter out this kind of spam, edit Postfix main configuration file.

sudo nano /etc/postfix/main.cf

Add the following line in smtpd_sender_restrictions. It will reject email if the domain name of the address supplied with the MAIL FROM command has neither MX record nor A record.

reject_unknown_sender_domain

Example:

smtpd_sender_restrictions =    permit_mynetworks    permit_sasl_authenticated    reject_unknown_sender_domain    reject_unknown_reverse_client_hostname    reject_unknown_client_hostname

Save and close the file. Then restart Postfix for the change to take effect.

sudo systemctl restart postfix

Note that I placed this restriction above other reject restrictions. From my experience, if it is below other reject restrictions, it won’t work. (Maybe this only happens on my email server.)

Tip #5: Enable Greylisting in Postfix

As required by the SMTP protocol, any legitimate SMTP client must be able to re-send email if delivery fails. (By default, Postfix is configured to resend failed emails for 4~5 days before it informs the sender that the message could not be delivered.) Many spammers usually just send once and would not retry.

Postgrey is a greylisting policy server for Postfix. CentOS/RHEL users can install it from EPEL repository.

sudo dnf install epel-release sudo dnf install postgrey

Once it’s installed, start it with systemctl.

sudo systemctl start postgrey

Enable auto-start at boot time.

sudo systemctl enable postgrey

On CentOS/RHEL, Postgrey listens on a Unix socket (/var/spool/postfix/postgrey/socket).

Next, we need to edit Postfix main configuration file to make it use the greylisting policy server.

sudo nano /etc/postfix/main.cf

Add the following line in smtpd_recipient_restrictions.

check_policy_service unix:postgrey/socket

In case you don’t know, the directive check_policy_service unix:private/policyd-spf in the above screenshot will make Postfix check SPF record on the sender’s domain. This directive requires you to install and configure the pypolicyd-spf package.

Save and close the file. Then restart Postfix.

sudo systemctl restart postfix

From now on, Postgrey will reject an email if the sender triplet (sender IP address, sender email address, recipient email address) is new. The following log message in /var/log/maillog shows a new sender triplet. The action “greylist” means this email message was rejected.

postgrey[1016]: action=greylist, reason=new, client_name=unknown, client_address=117.90.24.148/32, sender=pnccepjeu@rhknqj.net, recipient=xiao@linuxbabe.com

From my experience, Chinese email spammers like to use a fake, weird-looking, and randomly generated sender address for every email, so adding these fake email addresses to blacklist won’t stop them. On the other hand, they never try re-sending a rejected email with the same sender address, which means greylisting can be very effective at stopping this kind of spam.

How to Minimize Bad User Experience

Greylisting can result in a bad experience for the end-user, as the user has to wait another several minutes for the email to arrive. To minimize this bad experience, you can create a whitelist, and use a second MX record that points to the same host.

Whitelist

Postgrey ships with two whitelist files (/etc/postfix/postgrey_whitelist_clients and /etc/postfix/postgrey_whitelist_recipients). The former contains a list of hostnames and the latter contains a list of recipient addresses.

By default, Google’s mail servers are whitelisted. No matter the sender is using a @gmail.com address or other address, as long as the sender is using Google’s mail server, Postgrey won’t reject the email. The following line in my /var/log/maillog file shows this.

postgrey[1032]: action=pass, reason=client whitelist, client_name=mail-yb0-f190.google.com

Note: You can also see postgrey logs with this command sudo journalctl -u postgrey.

You can add other hostnames in /etc/postfix/postgrey_whitelist_clients file, like

facebook.com bounce.twitter.com blogger.com email.medium.com

You can get these hostnames with a tool called pflogsumm, which I will discuss later in this article. Save and close the file, then restart Postgrey.

sudo systemctl restart postgrey

Create Another MX Hostname with 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).

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 this requires you to set a very small delay time like 1 second in /etc/sysconfig/postgrey file like below. The delay time tells the SMTP client how many seconds to wait before sending it again. If the delay time is not small enough, then the second email delivery would still be rejected.

POSTGREY_DELAY="--delay=1"

Save and close the file. Then restart Postgrey.

sudo systemctl restart postgrey

Beware that not all mail servers would immediately try the second MX host.

-------