One of the most effective anti-spam measures one can implement is to enforce
valid use of SMTP and other standards. Spam clients are interested in
sending messages as quickly as possible, and so usually don't bother with
actually implementing standards correctly. In this post I shall describe the
various checks which can be used, show how to implement these checks in
Postfix, and describe how to ensure that your mail server passes these
checks when sending mail.
Reverse DNS Entries
RFC 1912 states that "every Internet-reachable host should have a name"
and "make sure your PTR and A records match". This can be checked by performing
a Forward Confirmed reverse DNS lookup1. This check can be done
before even accepting the TCP connection, which means the mail server's
existence isn't even revealed to rejected clients.
Postfix: Add reject_unknown_client_hostname
to
smtpd_client_restrictions
.
Passing: Ensure that your mail server has matching PTR
and A
records.
HELO
/EHLO
Hostname
RFC 2821 states that "a client SHOULD start an SMTP session by issuing
the EHLO command". Almost all SMTP client implementations do do this, and so we
can require the use of HELO
/EHLO
.
Postfix: Set smtpd_helo_required = yes
.
RFC 2821 states that "the argument field [of the HELO/EHLO command]
contains the fully-qualified domain name of the SMTP client if one is
available". Since external mail servers have to be Internet reachable this is a
requirement, and can be checked by looking up the name in DNS2.
Postfix: Add reject_invalid_helo_hostname
, reject_non_fqdn_helo_hostname
and reject_unknown_helo_hostname
to smtpd_helo_restrictions
.
Passing: Ensure that your mail server is configured to send a fully
qualified hostname which exists in DNS.
If there is only one mail server (and possibly even if there are multiple
servers), SMTP clients should not be using the server's hostname as the
HELO
hostname. Clients which do so can therefore be rejected.
Postfix: Add check_helo_access hash:/etc/postfix/helo_access
to
smtpd_helo_restrictions
. Use helo_access as a template for
/etc/postfix/helo_access
, and run postmap /etc/postfix/helo_access
afterwards.
Originator Address
The originator (MAIL FROM
) address is where error reports will be sent, and
therefore should be a valid address. The only thing which can be checked though
is that the address is fully qualified and that the domain exists.
Postfix: Add reject_non_fqdn_sender
and reject_unknown_sender_domain
to
smtpd_sender_restrictions
.
Passing: Ensure that your mail server only emits fully qualified addresses.
This should happen by default, except possibly for mail submitted with
sendmail
.
Recipient Addresses
Unless the mail server is a relay or backup MX, it should already only be
accepting addresses for which it is the destination. If it is a relay or backup
MX the same checks as above can be done.
Postfix: Add reject_non_fqdn_recipient
and
reject_unknown_recipient_domain
to smtpd_recipient_restrictions
.
One other check has to do with multiple recipients for bounced mail. Error
reports for bounced mail uses a null originator address, and should only have
one recipient.
Postfix: Add reject_multi_recipient_bounce
to smtpd_data_restrictions
.
Pipelining
Unless the client explicitly requests pipelining (as described in RFC
1854), the SMTP conversation must occur in lock step (i.e. the client
must wait for a response from the server before sending the next command). Since
spam clients are trying to send messages as quickly as possible it is likely
that they do not adhere to this requirement.
Postfix: Add reject_unauth_pipelining
to smtpd_data_restrictions
.
RFC 2821 specifies that the server must send the first message after the
connection is established. A neat trick is to delay this initial message to
catch out clients which don't wait for it.
Postfix: Add sleep 1, reject_unauth_pipelining
to
smtpd_client_restrictions
. This also requires smtpd_delay_reject = no
(explained below).
Monitoring
Since these measures will reject valid mail from misconfigured mail servers, I
like to keep an eye on rejections via logcheck. However, some of these
measures by their very nature reject the client before it's even sent the
originator and recipient addresses, which makes identification of valid mail
difficult. Postfix therefore has a feature which delays rejection until after
the recipient addresses have been sent. This is enabled by default, but can be
disabled by setting smtpd_delay_reject = no
.
Trackback URL for this post:
https://michael.gorven.za.net/trackback/1484
The Reverse DNS argument of
The Reverse DNS argument of yours has been debated quite a lot. FWIW the author of the quoted RFCs disagrees with your interpretation, and those restrictions will cause you many unwanted rejections.
The HELO rejections will also cause you headaches. I gave up on reject_unknown_helo_hostname and currently use reject_invalid_helo_hostname and reject_non_fqdn_helo_hostname combined with a lookup file to permit all those badly configured windows machines out there.
Neat pipelining trick. I shall be trying that. Thanks. :)