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.cfAdd 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_hostnamepermit_mynetworks: Allows IP addresses in your trusted networks (defined inmynetworks) to pass HELO checks.permit_sasl_authenticated: Allows clients who authenticate successfully (SMTP AUTH) to bypass HELO restrictions.check_helo_access: Allow hostnames defined in this file.reject_invalid_helo_hostname: Rejects clients that send a syntactically invalid HELO name : Examples rejected:- Bad characters (
HELO mail@domain) - Missing hostname (
HELO) - Hostname starting with a dot (
HELO .domain.com)
This checks only format, not existence.
- Bad characters (
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 OKThen run the following command to convert plain-text file into a hashed database the /etc/postfix/helo_access.db file:
sudo postmap /etc/postfix/helo_accessThen reload Postfix.
sudo systemctl reload postfixProtect from Malicious Incoming Mail
Protect from malicious incoming mail that entering Postfix via SMTP service, from either external internet SMTP servers or internal clients submitting mail to your SMTP service instead of submission service.
sudo nano /etc/postfix/main.cfMake 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_hostnameAllows clients from the IP ranges defined in mynetworks (trusted networks). Allows clients who authenticated via SMTP AUTH to bypass sender restrictions.
reject_unknown_sender_domain: These rules control what Postfix checks after the SMTP client issues theMAIL FROM:command (also known as theenvelope fromaddress) and not the message headers. Some spammers use a non-existent domain in theMAIL FROMaddress. If a domain name has no MX record, Postfix will try to find the A record of the main domain and send email to that host. If the sender domain has neither an MX record nor an A record, Postfix can’t send email, so it rejects those emails.reject_unknown_reverse_client_hostname: Perform a reverse DNS query (look for a PTR record) on the IP address of the server/client connecting to your Postfix SMTP service. Then, perform a DNS A query on the result of the reverse query to check if it points back to the connecting IP. If it does not, reject the email.reject_unknown_client_hostname: Reject the request when the client IP address to name mapping fails, the name to IP address mapping fails, or the name to IP address mapping does not match the client IP address.
Then restart Postfix for the change to take effect:
sudo systemctl restart postfixGreylisting
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 postgreyStart and enable it with systemctl:
sudo systemctl start postgrey
sudo systemctl enable postgreyOn Debian and Ubuntu, it listens on TCP port 10023 on localhost:
sudo netstat -lnpt | grep postgreyNext, we need to edit Postfix main configuration file to make it use the greylisting policy server.
sudo nano /etc/postfix/main.cfAdd 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:10023Then restart Postfix.
sudo systemctl restart postfixFrom 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.comWhitelist 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.comYou can add other hostnames in /etc/postgrey/whitelist_clients file, like:
facebook.com
bounce.twitter.com
blogger.com
email.medium.comNow 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 5The 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 postgreyTroubleshooting
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 refusedThe 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 postgreyCheck if it’s listening:
sudo netstat -lnpt | grep 10023Use 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.orgcheck_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_senderPostfix reject email when the domain inMAIL FROMheader 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_overrideAdd 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 serviceThen run the following command to create the rbl_override.db file.
sudo postmap /etc/postfix/rbl_overrideReload Postfix for the changes to take effect.
sudo systemctl reload postfixUse 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.orgAnother 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