Re: [Exim] WishList # 230

Top Page
Delete this message
Reply to this message
Author: Andrew - Supernews
Date:  
To: exim-users
Subject: Re: [Exim] WishList # 230
>>>>> "Tony" == Tony Finch <dot@???> writes:

>> This can be done in ACLs already - _but_ that currently doesn't
>> work well due to the deferral problem with dnsdb; it's very common
>> with helo and return-path domains to have problems resolving the
>> nameservers even though the domain itself is resolvable.


Tony> I don't think you can do it in ACLs already, because zone
Tony> boundaries don't always coincide with domain
Tony> boundaries. E.g. hermes.cam.ac.uk has no nameservers of its own
Tony> since it resides in the cam.ac.uk zone. You have to retry after
Tony> trimming off a label if the NS lookup fails, and possibly
Tony> repeat.


Yes, so? While the recursion depth of ACLs is limited, it's sufficient
to deal with all plausible cases of that:

# warning: the code that follows is known not to work well in the wild
# due to dnsdb's inability to handle deferrals in a controllable manner

# variable convention: c0-c8 are scratch variables, m9 contains named
# per-message variables, m8 is the rejection text if set

# Given a domain in acl_c0, find the nearest zone cut, and return the zone
# base in c0, and the NS records in c1
check_domain_ns:
  warn    set acl_c1 = ${lookup dnsdb {NS=$acl_c0}{$value}{}}
  warn    condition = ${if eq{$acl_c1}{} {yes}{no}}
          condition = ${if match{$acl_c0}{\N\.\N} {yes}{no}}
          set acl_c0 = ${substr{${strlen:${extract{1}{.}{$acl_c0}}}}{$acl_c0}}
          set acl_c0 = ${s_1:$acl_c0}
          acl = check_domain_ns



# given a newline-delimited list of addresses in $acl_c0, look them all up
# in the dnslist $acl_c1, stopping if we find one (returned in c0)
check_addresses:
  deny    condition = ${if eq{$acl_c0}{} {yes}{no}}
  warn    set acl_c2 = ${extract{1}{\n}{$acl_c0}}
          set acl_c0 = ${substr{${strlen:$acl_c2}}{$acl_c0}}
          set acl_c0 = ${s_1:$acl_c0}
  warn    set acl_c3 = ${sg{4.3.2.1}{\N(\d)\N}{\N${extract{$1}{.}{$acl_c2}}\N}}
  accept  dnslists = $acl_c1/$acl_c3
          set acl_c0 = $acl_c2
  accept  acl = check_addresses



# given a newline-delimited list of NS names in acl_c0, see if any are
# locally considered bad.
check_nameservers:
  warn    set acl_c0 = ${sg{$acl_c0}{\N(.+)\n?\N}\
                           {\N${lookup{$1}\
                                  partial()lsearch{EXIM_HOME/bad_ns_domains}\
                                  {,$1.$2}{}}\N}}
          set acl_c0 = ${s_1:$acl_c0}
  accept  condition = ${if !eq{$acl_c0}{} {yes}{no}}



check_client_domain:
  warn    set acl_c0 = $sender_host_name
  deny    condition = ${if eq{$acl_c0}{} {yes}{no}}
  warn    acl = check_domain_ns
  warn    set acl_m9 = czone=${quote:$acl_c0} cns=${quote:$acl_c1} $acl_m9
          set acl_c2 = $acl_c0
          set acl_c0 = ${sg{$acl_c1}\
                           {\N(.+)(\n?)\N}\
                           {\N${lookup dnsdb {A=$1}{$value$2}{}}\N}}
          log_message = nameservers: $sender_host_name zone ${quote:$acl_c2} NS ${quote:$acl_c1} A ${quote:$acl_c0}
  warn    set acl_c1 = sbl.spamhaus.org
          acl = check_addresses
          set acl_m8 = bad client: $sender_host_name NS $acl_c0 on $dnslist_domain $dnslist_value: $dnslist_text
          log_message = $acl_m8
  warn    set acl_c0 = ${extract{cns}{$acl_m9}}
          acl = check_nameservers
          set acl_m8 = bad client: $sender_host_name NS $acl_c0 is locally banned
          log_message = $acl_m8


Tony> Consider also the amusement that can be had with classless
Tony> in-addr.arpa delegation and chasing CNAMEs.


Yeah, finding the nameservers for the reverse zone is harder, but I'm
less convinced that it is useful.

--
Andrew, Supernews
http://www.supernews.com