# HELO tests for Exim 4.xx # Version 1.01 by david @ ols . es # # Requires Exim 4.33 (minimum) # # The latest version of this file can be downloaded from: # http://www.ols.es/exim # # two checks are provided by acl's named acl_check_helo_fast and # acl_check_helo_slow # # acl_check_helo_fast does not need dns lookups, acl_check_helo_slow uses # $sender_host_name and does other dns lookups. Usually you could use # acl_check_helo_fast at the first possible stage (mail acl recommended) # as it rejects mail at high speed. acl_check_helo_slow is slower as it # does dns lookups, use it as soon as you used $sender_host_name in other # acl or when you have reached the end of acl's that do not need lookups # (rcpt acl recommended). You could use it like this: # # drop !authenticated = * # hosts = !+relay_from_hosts # !acl = acl_check_helo_fast # Fast checks ------------------------------------------------------------- acl_check_helo_fast: # No HELO/EHLO deny condition = ${if eq{$sender_helo_name}{}} message = Polite hosts say HELO first\n\ Please see RFC 2821 section 4.1.1.1 log_message = Bad HELO: Empty HELO # Invalid HELO/EHLO - Ip address without [] that do not match accept condition = ${if isip{$sender_helo_name}} condition = ${if eq{$sender_helo_name}{$sender_host_address}} deny condition = ${if isip{$sender_helo_name}} message = HELO/EHLO must contain your FQDN or IP literal\n\ please see RFC 2821 section 4.1.1.1 log_message = Bad HELO: Invalid HELO (ip does not match) accept condition = ${if isip6{$sender_helo_name}} condition = ${if eq{$sender_helo_name}\ {IPv6:$sender_host_address}} deny condition = ${if isip6{$sender_helo_name}} message = HELO/EHLO must contain a FQDN or IP literal\n\ please see RFC 2821 section 4.1.1.1 log_message = Bad HELO: Invalid HELO (ip does not match) # Check ip literals accept condition = ${if eq{$sender_helo_name}\ {[${if isip6{$sender_host_address}{IPv6:}}\ $sender_host_address]}} deny condition = ${if match {$sender_helo_name}\ {\N^\[(.*)\]$\N}} message = Forged HELO: you are not $sender_helo_name log_message = Forged HELO: ip does not match # Invalid HELO/EHLO deny condition = ${if match \ {$sender_helo_name}{\N^[^.:].*[.:][^.:]+$\N}\ {no}{yes}} message = HELO/EHLO must contain your FQDN or IP literal\n\ please see RFC 2821 section 4.1.1.1 log_message = Bad HELO: Invalid HELO # Hacked HELO (DOMAIN.com) (constructed by viruses) deny condition = ${if match \ {$sender_helo_name}{\N^[A-Z0-9\-]+\.[a-z0-9]+$\N}} condition = ${if match \ {$sender_helo_name}{\N^[0-9]+\.[a-z]+$\N}{no}{yes}} message = Hacked HELO: you are not $sender_helo_name log_message = Hacked HELO: constructed by viruses logwrite = :panic: OLS_BLACKLIST $sender_host_address # Hacked HELO (random domain names) (constructed by viruses) deny condition = ${if match {$sender_helo_name}{smtp}{no}{yes}} condition = ${if match {$sender_helo_name}\ {\N^[a-z0-9]+\.[a-z]+$\N}} condition = ${if match {$sender_helo_name}\ {\N.*[bcdfghjklmnpqrstvwxz]{7,}.*\.[a-z]+$\N}} message = Hacked HELO: you are not $sender_helo_name log_message = Hacked HELO: constructed by viruses (random) # Tipical unexistant domains deny condition = ${if match {$sender_helo_name}\ {(backup\.lst|localhost|system\.mail)}} message = Bad HELO: $sender_helo_name does not exist\n\ Please see RFC 2821 section 4.1.1.1 # Forged HELO (our hostname) drop condition = ${if match_domain{$sender_helo_name}\ {+local_domains}} message = Forged HELO: you are not $sender_helo_name log_message = Forged HELO: $sender_helo_name is one of our \ local domains logwrite = :panic: OLS_BLACKLIST $sender_host_address # Forged HELO (other mx for local domains) drop condition = ${if match{$sender_helo_name}{^(a|b)\.mx\.}} condition = ${if match_domain{${substr_5:$sender_helo_name}}\ {+local_domains}} message = Forged HELO: you are not $sender_helo_name log_message = Forged HELO: $sender_helo_name is one of our \ local domains logwrite = :panic: OLS_BLACKLIST $sender_host_address # Hacked HELO (Sober-Mailer/rarsoft) drop message = Hacked HELO: $sender_helo_name does not exists log_message = Hacked HELO: $sender_helo_name condition = ${if match{$sender_helo_name}\ {Sober-Mailer.de.|rarsoft}} # Usual non legally used forged HELO's deny condition = ${if match {$sender_helo_name}\ {^(gmail\.com|msn\.com|yahoogroups\.com|aol\.com)\$}} message = Forged HELO: you are not $sender_helo_name log_message = Forged HELO: $sender_helo_name is never used logwrite = :panic: OLS_BLACKLIST $sender_host_address # By now, it looks ok accept # Slow checks ------------------------------------------------------------ acl_check_helo_slow: # Accept ip literals, nothing to check now accept condition = ${if match {$sender_helo_name}\ {\N^\[(.*)\]$\N}{yes}{no}} set acl_c8 = no # Blacklisted domains deny log_message = Blacklisted domain in HELO: $sender_helo_name message = Blacklisted domain: $sender_helo_name ($dnslist_domain) dnslists = rhsbl.sorbs.net=127.0.0.12/$sender_helo_name :\ rhsbl.ahbl.org/$sender_helo_name :\ blackhole.securitysage.com/$sender_helo_name # CSA Authorization ? deny !verify = csa message = Forged HELO: Not authorized by CSA accept condition = ${if eq {$csa_status}{ok}} add_header = X-OLS-Security: OK - HELO authorized by CSA set acl_c8 = yes # HELO is coherent ? deny !acl = acl_check_helo_dns # Everything fine accept # HELO DNS checks -------------------------------------------------------- acl_check_helo_dns: # Get HELO hostname on acl_c4 warn condition = ${if !def:acl_c4} condition = ${if eq {$sender_host_name}{}} set acl_c4 = ${lookup dnsdb{defer_never,ptr=$sender_host_address}\ {${lc:$value}}{}} warn condition = ${if !def:acl_c4} condition = ${if !eq {$sender_host_name}{}} set acl_c4 = $sender_host_name # Hostname matches HELO accept condition = ${if eq {$acl_c4}{${lc:$sender_helo_name}}} # Reject hotmail.com helo for hosts with no rdns deny condition = ${if eq {$acl_c4}{}} condition = ${if match {$sender_helo_name}{hotmail\.com}} message = Forged HELO: you are not $sender_helo_name log_message = Forged HELO: Hostname does not match HELO logwrite = :panic: OLS_BLACKLIST $sender_host_address # Lookup HELO ip address on acl_m9 warn set acl_m9 = ${lookup dnsdb{>: defer_never,\ a=$sender_helo_name}{$value}{}} # HELO resolves to ip accept condition = ${if eq {$acl_m9}{}{no}{yes}} condition = ${if match {$sender_host_address}{($acl_m9)}} set acl_c8 = yes # Accept hosts related to sender domain accept !sender_domains = cioce.com hosts = +ignore_unknown : *.$sender_address_domain :\ $sender_address_domain : \ ${lookup dnsdb{>: defer_never,mxh=$sender_address_domain}} set acl_c8 = yes # Accept host authorized by SPF accept spf = pass # Now HELO does not exist --------------------------------------------- # Virus patterns deny condition = ${if match \ {$sender_helo_name}{\N^[A-Z0-9\-]+\.[a-z0-9]+\N}} message = Hacked HELO: $sender_helo_name does not exist logwrite = :panic: OLS_BLACKLIST $sender_host_address deny condition = ${if match \ {$sender_helo_name}{\N^[a-z0-9\-]+\.[a-z0-9]+\.\ (comcast\.net|ameritech\.net|optonline\.net|\ verizon\.net|cox\.net|rr\.com|adelphia\.net)$\N}} message = Hacked HELO: $sender_helo_name does not exist logwrite = :panic: OLS_BLACKLIST $sender_host_address # Forged HELO (yahoo - international) deny condition = ${if match {$sender_helo_name}{^yahoo\.}} message = Forged HELO: you are not $sender_helo_name log_message = Forged HELO: Not a yahoo server logwrite = :panic: OLS_BLACKLIST $sender_host_address # Check list of domains which HELO should match the hostname # return expected hostname domain in acl_m9 warn set acl_m9 = ${lookup{$sender_helo_name} \ nwildlsearch{/usr/local/exim/exim.helo.txt} \ {${if eq{$value}{}{$sender_helo_name}{$value}}}{}} # Should match but no rdns deny condition = ${if eq {$acl_m9}{}{no}{yes}} condition = ${if eq {$acl_c4}{}} message = Forged HELO: you are not $sender_helo_name log_message = Forged HELO: Not a $acl_m9 server logwrite = :panic: OLS_BLACKLIST $sender_host_address # Should match but does not deny condition = ${if eq {$acl_m9}{}{no}{yes}} condition = ${if !match{$acl_c4}{$acl_m9}} message = Forged HELO: you are not $sender_helo_name log_message = Forged HELO: Not a $acl_m9 server logwrite = :panic: OLS_BLACKLIST $sender_host_address # Should match and matches accept condition = ${if eq {$acl_m9}{}{no}{yes}} set acl_c8 = yes # helo is a second level .com/.net.org domain and does not exist deny condition = ${if match{$sender_helo_name}\ {^[a-z0-9\\-]+\\.(com|net|org)\$}} condition = ${lookup dnsdb{defer_never,ns=$sender_helo_name}\ {no}{yes}} message = $sender_helo_name does not exist log_message = Hacked HELO: $sender_helo_name does not exist logwrite = :panic: OLS_BLACKLIST $sender_host_address # HELO is acceptable accept