https://github.com/smtpd/qpsmtpd/pull/29
I've been running it on my server for a week in RFC policy mode. I knew from hours of watching logs that it would be effective, but measuring it was still surprising and delightful. Of the 10% of connections that make it past the dnsbl and karma tests, another 50% are rejected by these HELO tests. Of those 50%, more than 95% are connections from Windows (most Win 7) hosts where the DNS bears no resemblance to the HELO hostname offered. Since expanding the no_matching_dns test (earlier today), I have yet to see a single false positive from that test. While I'm still not using that as a condition for rejection, it may now be good enough to enforce. Matt NAME helo - validate the HELO message presented by a connecting host. DESCRIPTION Validate the HELO hostname. This plugin includes a suite of optional tests, selectable by the *policy* setting. The policy section details which tests are enforced by each policy option. This plugin adds an X-HELO header with the HELO hostname to the message. Using *policy rfc* will reject a very large portion of the spam from hosts that have yet to get blacklisted. WHY IT WORKS The reverse DNS of the zombie PCs is out of the spam operators control. Their only way to get past these tests is to limit themselves to hosts with matching forward and reverse DNS, and then use the proper HELO hostname when spamming. At present, this presents a very high hurdle. HELO VALIDATION TESTS is_in_badhelo Matches in the *badhelo* config file, including yahoo.com and aol.com, which neither the real Yahoo or the real AOL use, but which spammers use a lot. Like qmail with the qregex patch, the badhelo file can also contain perl regular expressions. In addition to normal regexp processing, a pattern can start with a ! character, and get a negated (!~) match. invalid_localhost Assure that if a sender uses the 'localhost' hostname, they are coming from the localhost IP. is_plain_ip Disallow plain IP addresses. They are neither a FQDN nor an address literal. is_address_literal [N.N.N.N] An address literal (an IP enclosed in brackets) is legal but rarely, if ever, encountered from legit senders. is_forged_literal If a literal is presented, make sure it matches the senders IP. is_not_fqdn Makes sure the HELO hostname contains at least one dot and has only those characters specifically allowed in domain names (RFC 1035). no_forward_dns Make sure the HELO hostname resolves. no_reverse_dns Make sure the senders IP address resolves to a hostname. no_matching_dns Make sure the HELO hostname has an A or AAAA record that matches the senders IP address, and make sure that the senders IP has a PTR that resolves to the HELO hostname. Since the dawn of SMTP, having matching DNS has been a minimum standard expected and oft required of mail servers. While requiring matching DNS is prudent, requiring an exact match will reject valid email. While testing this plugin with rejection disabled, I noticed that mx0.slc.paypal.com sends email from an IP that reverses to mx1.slc.paypal.com. While that's technically an error, I believe it's an error to reject mail based on it. Especially since SLD and TLD match. To avoid snagging false positives, matches are extended to the first 3 octets of the IP and the last two labels of the FQDN. The following are considered a match: 192.0.1.2, 192.0.1.3 foo.example.com, bar.example.com This allows *no_matching_dns* to be used without rejecting mail from orgs with pools of servers where the HELO name and IP don't exactly match. This list includes Yahoo, Gmail, PayPal, cheaptickets.com, exchange.microsoft.com, and likely many more. CONFIGURATION policy [ lenient | rfc | strict ] Default: lenient lenient Reject failures of the following tests: is_in_badhelo, invalid_localhost, and is_forged_literal. This setting is lenient enough not to cause problems for your Windows users. It is comparable to running check_spamhelo, but with the addition of regexp support and the prevention of forged localhost and forged IP literals. rfc Per RFC 2821, the HELO hostname must be the FQDN of the sending server or an address literal. When *policy rfc* is selected, all the lenient checks and the following are enforced: is_plain_ip, is_not_fqdn, no_forward_dns, and no_reverse_dns. If you have Windows users that send mail via your server, do not choose *policy rfc* without *reject naughty* and the naughty plugin. Windows users often send unqualified HELO names and will have trouble sending mail. <Naughty> can defer the rejection, and if the user subsequently authenticates, the rejection will be cancelled. strict Strict includes all the RFC tests and the following: no_matching_dns, and is_address_literal. I have yet to see an address literal being used by a hammy sender. But I am not certain that blocking them all is prudent. It is recommended that *policy strict* be used with <reject 0> and that you monitor your logs for false positives before enabling rejection. badhelo Add domains, hostnames, or perl regexp patterns to the badhelo config file; one per line. timeout [seconds] Default: 5 The number of seconds before DNS queries timeout. reject [ 0 | 1 | naughty ] Default: 1 0: do not reject 1: reject naughty: naughty plugin handles rejection reject_type [ temp | perm | disconnect ] Default: disconnect What type of rejection should be sent? See docs/config.pod loglevel Adjust the quantity of logging for this plugin. See docs/logging.pod RFC 2821 4.1.1.1 The HELO hostname "...contains the fully-qualified domain name of the SMTP client if one is available. In situations in which the SMTP client system does not have a meaningful domain name (e.g., when its address is dynamically allocated and no reverse mapping record is available), the client SHOULD send an address literal (see section 4.1.3), optionally followed by information that will help to identify the client system." 2.3.5 The domain name, as described in this document and in [22], is the entire, fully-qualified name (often referred to as an "FQDN"). A domain name that is not in FQDN form is no more than a local alias. Local aliases MUST NOT appear in any SMTP transaction. AUTHOR 2012 - Matt Simerson ACKNOWLEDGEMENTS badhelo processing from check_badhelo plugin badhelo regex processing idea from qregex patch additional check ideas from Hakura helo plugin ````````````````````````````````````````````````````````````````````````` Matt Simerson http://matt.simerson.net/ Systems Engineer http://www.tnpi.net/ Mail::Toaster - http://mail-toaster.org/ NicTool - http://www.nictool.com/ `````````````````````````````````````````````````````````````````````````