Having recently been battling to keep some servers out of the CBL, I decided it was time to get strict on what the email servers were accepting, so I created an Exim ACL to reject non-RFC2821 compliant HELO/EHLO strings.

The configuration comes in two parts: the configuration line to tell Exim to check HELO/EHLO strings, and the ACL itself.

The ‘check HELO’ command

Quite simple: (I called my ACL “acl_check_helo_rfc2821″)

acl_smtp_helo = acl_check_helo_rfc2821

This needs to go in the main configuration section.

Debian users: if you’ve using split config (if not, you really should at least try it!) then I’d create a new file in /etc/exim4/conf.d/main/ so that it doesn’t get clobbered.

The ACL

This needs to go in the ACL configuration section (Debian split config users: a new file in /etc/exim4/conf.d/acl/ – I called mine “30_exim4-config_check_helo”)

### acl/30_exim4-config_check_helo
#################################
 
# Check HELO/EHLO command
#
acl_check_helo_rfc2821:
deny
message = RFC 2821 invalid HELO/EHLO
condition = ${if or { \
{ !match {$sender_helo_name}{\\.} } \
{ match {${lc:$sender_helo_name}}{localhost\\.localdomain} } \
{ match {$sender_helo_name}{\N^(\d{1,3}\.){3}\d{1,3}$\N} } \
} {yes}{no}}
 
accept

Who’s allowed in and who isn’t

This ACL will reject, with a 550 code, any HELO/EHLO strings that:

  • do not contain a period (so they can’t be FQDNs)
  • are just ‘localhost.localdomain’ (Not strictly forbidden by RFC 2821, but the CBL doesn’t like it. Perl’s Net::SMTP will do this unless you set an explicit HELO string)
  • are four numbers separated by dots (I could have improved this to just match valid IP addresses, but anyone who HELOs as ‘999.999.999.999’ deserves to be rejected IMHO)

Note that it doesn’t do any kind of lookup or further checking, so it’ll quite happily accept a HELO of ‘my.foot’ (which, although it may not resolve, is still a FQDN). It’ll also quite happily accept ‘[999.999.999.999]’, but that still appears to be valid according to section 4.1.3 of RFC 2821