Reject Invalid EHLO/HELO Hostname
Some spammers don’t provide a valid HELO/EHLO
hostname during SMTP communication. They can be non-fully qualified domain name, or a domain name doesn’t exist or only for an 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
Add the following lines to reject SMTP client that does not provide valid HELO/EHLO hostname:
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
permit_mynetworks
: Allow IPs defined in this directivepermit_sasl_authenticated
: Allow authenticated users.check_helo_access
: Allow hostnames defined in this file.reject_invalid_helo_hostname
: Reject clients who provide malformed HELO/EHLO hostname.reject_non_fqdn_helo_hostname
: Reject non-fully qualified HELO/EHLO hostname.reject_unknown_helo_hostname
: Reject email with HELO/EHLO hostname has neither DNS A record nor MX record.
Now create the file /etc/postfix/helo_access
to whitelist domains that do not use a valid hostname:
optimus-webapi-prod-2.localdomain OK
va-massmail-02.rakutenmarketing.com OK
Then run the following command to create the /etc/postfix/helo_access.db
file:
sudo postmap /etc/postfix/helo_access
Save and close the file. Then reload Postfix.
sudo systemctl reload postfix
Reject Emails from Non-Valid Domains
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 reject those emails that you can’t reply to:
sudo nano /etc/postfix/main.cf
Make the smtpd_sender_restrictions
configuration directive look as follows:
smtpd_sender_restrictions =
permit_mynetworks
permit_sasl_authenticated
reject_unknown_sender_domain
reject_unknown_sender_domain
: Checks the sender's email domain in theMAIL FROM
address to ensure it has a valid DNS configuration. It requires that the domain in the sender's email address has a valid MX or A record.
Then restart Postfix for the change to take effect:
sudo systemctl restart postfix
Reject Emails if No Valid PTR or A Record for Hostname
A legitimate email server should have a PTR record and a valid A record for its hostname. The IP address returned from DNS A record should match the IP address of the contacting email server. So tell Postfix to perform these checks on SMTP client server:
sudo nano /etc/postfix/main.cf
Make the smtpd_sender_restrictions
configuration directive look as follows:
smtpd_sender_restrictions =
permit_mynetworks
permit_sasl_authenticated
reject_unknown_sender_domain
reject_unknown_reverse_client_hostname
reject_unknown_client_hostname
reject_unknown_reverse_client_hostname
: Checks the reverse DNS (PTR record) of the client’s IP address (the IP of the server connecting to your Postfix server) to ensures that the IP address of the sending server can be mapped back to a valid hostname.reject_unknown_client_hostname
: Performs a check that the hostname obtained from the PTR record has a valid forward DNS (A record) pointing back to the SMTP server that connecting to your Postfix server.
Save and close the file. Then restart Postfix for the change to take effect.
sudo systemctl restart postfix
Greylisting
Introduction
Greylisting is a spam prevention technique that can be implemented in Postfix to reduce unwanted email by temporarily rejecting new email senders and requiring them to retry. Because most legitimate mail servers will retry delivery after a short delay, while many spam servers or bots will not attempt to resend.
How Greylisting Works ?
- Initial Rejection: When an email is received from an unfamiliar sender IP, sender address, and recipient address combination, Postfix temporarily rejects it with a
451
(Temporary failure) response. This tells the sending server to try again later. - Retry Attempt: If the sending server retries after a certain period, Postfix recognizes the retry as legitimate and accepts the email.
- Temporary Listing: After accepting the email, Postfix remembers this sender-recipient combination for a configurable period, so subsequent emails from this source are accepted without delay.
Configuration
Postgrey is a greylisting policy server for Postfix. So first install install postgrey:
sudo apt install postgrey
Start and enable it with systemctl:
sudo systemctl start postgrey
sudo systemctl enable postgrey
On Debian and Ubuntu, it listens on TCP port 10023 on localhost:
sudo netstat -lnpt | grep postgrey
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 line check_policy_service inet:127.0.0.1:10023
to smtpd_recipient_restrictions
configuration directive:
smtpd_recipient_restrictions =
reject_unauth_destination,
check_policy_service unix:private/quota-status,
check_policy_service unix:private/policyd-spf,
check_policy_service inet:127.0.0.1:10023
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/mail.log
(or sudo journalctl -u postgrey
) 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
Whitelist Domains
Greylisting can result in bad experience for the end user, as the user has to wait another several minute 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/postgrey/whitelist_clients
and /etc/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/mail.log
file shows this:
postgrey[1032]: action=pass, reason=client whitelist, client_name=mail-yb0-f190.google.com
You can add other hostnames in /etc/postgrey/whitelist_clients
file, like:
facebook.com
bounce.twitter.com
blogger.com
email.medium.com
Now let's create a secondary MX record in DNS with the same IP address pointing to your same Potfix server to allow the SMTP client to retry immediately after the first mail server rejects the mail. For example:
Record Type Name Mail Server Priority
MX @ mail1.example1.com 0
MX @ mail2.example1.com 5
The sender will try the first mail server (with priority 0). If mail1.example1.com
rejects email by greylisting, then the sender would immediately try the second mail server (with priority 5).
Since two mail server hostnames have the same IP address, 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 the email delay caused by greylisting.
Note that this requires you to set a very small delay time like 1 second in /etc/default/postgrey
. The delay time tells the SMTP client how many seconds to wait before sending again. If the delay time is not small enough, then the second email delivery would still be rejected:
POSTGREY_OPTS="--inet=127.0.0.1:10023 --delay=1"
Finally restart Postgrey:
sudo systemctl restart postgrey
Troubleshooting
If you see the following error in mail log (/var/log/mail.log
)
warning: connect to 127.0.0.1:10023: Connection refused
warning: problem talking to server 127.0.0.1:10023: Connection refused
The problem is that postgrey is not running. You need to specify 127.0.0.1 as the listening address in /etc/default/postgrey file. So change the following line:
POSTGREY_OPTS="--inet=10023"
to
POSTGREY_OPTS="--inet=127.0.0.1:10023"
Then restart postgrey:
sudo systemctl restart postgrey
Check if it’s listening:
sudo netstat -lnpt | grep 10023
Use Public Realtime Blacklists
There are spam emails that are sent from servers that has a valid hostname, valid PTR record and can pass all previous checks. 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 result depending on when you query the list.
You can use multiple blacklists to block spam. Go to www.debouncer.com and mxtoolbox.com, enter the spammer’s domain and/or 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:
- dbl.spamhaus.org
- zen.spamhaus.org
- multi.uribl.com
- ivmURI
- InvaluementURI
So I can add the following configurations in /etc/postfix/main.cf
file. Some public blacklisting service requires 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 inet:127.0.0.1:10023,
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
check_client_access
: File containing a list of domains you want to whitelist.reject_rhsbl_helo
: Postfix reject email when the client HELO/EHLO hostname is blacklisted.reject_rhsbl_reverse_client
: Checks the PTR (reverse DNS) record of the SMTP client’s IP address against Spamhaus's DBL. If the hostname is blacklisted, reject the email.reject_rhsbl_sender
Postfix reject email when the domain inMAIL FROM
header field is blacklisted.reject_rbl_client
: This is an IP-based blacklist. When the client IP address is backlisted, reject the email.
NOTE: 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 field, so reject_rhsbl_sender
will be effective.
Sometimes legitimate mail servers are blacklisted. In this case, we ask the Postfix server to whitelist these domains by listing them in a file:
sudo nano /etc/postfix/rbl_override
Add the domains you want to whitelist:
dripemail2.com OK //This domain belongs to drip.com
mlsend.com OK //This domain belongs to mailerlite email marketing service
Then run the following command to create the rbl_override.db
file.
sudo postmap /etc/postfix/rbl_override
Reload Postfix for the changes to take effect.
sudo systemctl reload postfix
Use 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 inet:127.0.0.1:10023,
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 below the permit_dnswl_client list.dnswl.org=127.0.[0..255].[1..3],
line:
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.
TODO Anti-spam — SpamAssassin
- State "TODO" from [2024-11-02 Sat 17:45]
Run the following command to install SpamAssassin from the default Debian/Ubuntu software repository. Spamc is the client for SpamAssassin spam filtering daemon.
sudo apt install spamassassin spamc