[Pkg-exim4-users] Exim4 with local network as well as smarthost: revised

ael law_ence.dev at ntlworld.com
Sun Mar 29 14:04:01 UTC 2009


I am posting a revised version of my solution which overcomes the 
problem that I encountered before: I misinterpreted part of the 
documentation. This is mainly for the archives and others in a similar 
situation. It is broadly similar to the case described by Dave Witbrodt, 
but he is addressing a different problem.

---------------------------------------------

The standard debian exim configurations do not cater
for a small local private network behind a NAT router.

Most mail needs to go to an (isp) smarthost with FROM headers
rewritten. But local mail within the network needs to be delivered
directly with headers unchanged.

This can't be done with a global conditional rewriting rule because
exim4 makes a single record when a common message is sent to several
recipients: see FAQ 0807 at www.exim.org.

My local network is small and no single machine is necessarily
running at all times. Thus a dedicated local network mail machine
is not an option. Instead each machine runs its own copy of exim4
and accepts email directly from its local peers.

The local hosts each have the local network hostnames in /etc/hosts:
these are not registered dns names and are aliases as usual for
reserved 10.0.0.*, 192.168.*.* or 172.16.*.* IP4 addresses.

The description here is using a monolithic configuration.

First I define a new macro LOCAL_NETWORK in exim4.conf.localmacros.

LOCAL_NETWORKS is a regular expression used to recognise the local 
network names (held in /etc/hosts). I tried to get exim4 to examine 
/etc/hosts directly, but eventually resorted to writing the regular 
expression manually.

LOCAL_NETWORKS= \N^.*\.local\.net$\N

is a simple case which matches fully qualified names for local.net.


--------------- exim4.conf.localmacros -------------------------

# Define macros for local network here

LOCAL_NETWORKS = \N^.*\.local\.net$\N

# Since LOCAL_NETWORKS appears in string lists with default separator :,
# those lists need default changed (or ::/: above)

# DEFAULT_BOUNCE_ADDRESS is used when sending to the smarthost
# and no matching entry is found in /etc/email-addresses
# DEFAULT_BOUNCE_ADDRESS may be empty, in which case any misdirected
# mail by users not in email-addresses will not be detected by anyone.

DEFAULT_BOUNCE_ADDRESS = mybounces at my.isp

# Avoid HELO exposing internal info when remote:

HELO_ORIGIN=myisp.network.perhaps

# HELO_ORIGIN ought to be set to something sensible but only to a real
# host if you own it. Some MTAs might do a sanity check so it might need
# testing or changing.

#Since main rewriting rules are global we must turn them off:
NO_EAA_REWRITE_REWRITE = true
#To compensate, must add them to right transport

REMOTE_NETS_REWRITE1 = \
*@+local_domains "${lookup{${local_part}}lsearch{/etc/email-addresses}\
                     {$value}fail}" frs
REMOTE_NETS_REWRITE2 = \
*@ETC_MAILNAME "${lookup{${local_part}}lsearch{/etc/email-addresses}\
                     {$value}fail}" frs

REMOTE_NETS_REWRITES = REMOTE_NETS_REWRITE1 : REMOTE_NETS_REWRITE2

# We also need to rewrite the envelope via return_path which
# is set with REMOTE_SMTP_RETURN_PATH

REMOTE_RETURN_REWRITE= \
         "${lookup{$sender_address_local_part}lsearch{/etc/email-addresses}\
           {$value}\
           {DEFAULT_BOUNCE_ADDRESS}}"

-----------------------------------------------------------------------

I had to edit update-exim4.conf.conf manually:

----------------- update-exim4.conf.conf ----------------
#...

dc_eximconfig_configtype='smarthost'
dc_other_hostnames='mousebag.rodent'
dc_local_interfaces=''
dc_readhost='mouse1.rodent'
dc_relay_domains=''
dc_minimaldns='true'
dc_relay_nets=''
dc_smarthost='smtp.isp.com'
CFILEMODE='644'
dc_use_split_config='false'
dc_hide_mailname='false'
dc_mailname_in_oh='true'
dc_localdelivery='mail_spool'
---------------------------------------------------

dpkg-reconfigure exim4 would not let me have smarthost and
dc_hide_mailname='false' together. This last was to turn off global 
envelope rewriting.

local_host_blacklist had
!a.b.c.0/17
to allow the incoming mail from local peers.
{ The local network has a wifi subnet. }

I had to edit exim4.conf.template:

First I added a new initial router to catch the local network mail:

----------------------------------------------------------------
   begin routers

#### LOCAL_NETWORKS is an RE from exim4.conf.localmacros ###

.ifdef LOCAL_NETWORKS
local_net:
    debug_print = "R: local_net for $domain"
    driver  = manualroute
    domains = <; LOCAL_NETWORKS
    route_list = * $domain byname
    condition = ${if match_domain{$domain}{+local_domains}{no}{yes}}
    transport = smtp_lnet
.endif

------------------------------------------------------------------
"byname" above ensures that the local network names can be translated
from /etc/hosts. The condition makes sure that the local names on the
host machine pass through.

It uses a dedicated transport smtp_lnet defined below:

--------------------------------------------------

   begin transports

# transport to avoid from rewrite

.ifdef LOCAL_NETWORKS
smtp_lnet:
    debug_print= "T: smtp_lnet for $local_part@$domain"
    driver = smtp
.endif

----------------------------------------------------------

But since the global header rewrite has been turned off, I had
to hack the next best thing

----------------------------------------------------------------
# local nets hack
.ifdef LOCAL_NETWORKS
REMOTE_SMTP_HEADERS_REWRITE=REMOTE_NETS_REWRITES
REMOTE_SMTP_RETURN_PATH=REMOTE_RETURN_REWRITE
REMOTE_SMTP_HELO_DATA=HELO_ORIGIN
.elifdef HIDE_MAILNAME
REMOTE_SMTP_HEADERS_REWRITE=*@+local_domains $1 at DCreadhost frs :
*@ETC_MAILNAME $1 at DCreadhost frs
.endif

.ifdef HIDE_MAILNAME
REMOTE_SMTP_RETURN_PATH=${if
match_domain{$sender_address_domain}{+local_domains}{${sender_address_local_part}@DCreadhost}{${if 

match_domain{$sender_address_domain}{ETC_MAILNAME}{${sender_address_local_part}@DCreadhost}fail}}}

.endif
# end of local nets hack

-------------------------------------------------------------------

That gets picked up in the remote_smtp_smarthost transport where
it causes the appropriate non-envelope headers to be re-written.

Last of all I adjusted the helo_data in remote_smtp_smarthost:

remote_smtp_smarthost:
   debug_print = "T: remote_smtp_smarthost for $local_part@$domain"
   driver = smtp
   hosts_try_auth = <; ${if exists{CONFDIR/passwd.client} \
         {\
         ${lookup{$host}nwildlsearch{CONFDIR/passwd.client}{$host_address}}\
         }\
         {} \
       }
.ifdef REMOTE_SMTP_SMARTHOST_HOSTS_AVOID_TLS
   hosts_avoid_tls = REMOTE_SMTP_SMARTHOST_HOSTS_AVOID_TLS
.endif
.ifdef REMOTE_SMTP_HEADERS_REWRITE
   headers_rewrite = REMOTE_SMTP_HEADERS_REWRITE
.endif
.ifdef REMOTE_SMTP_RETURN_PATH
   return_path = REMOTE_SMTP_RETURN_PATH
# hack
.ifdef LOCAL_NETWORKS
  helo_data=HELO_ORIGIN
.elifdef  REMOTE_SMTP_HELO_FROM_DNS
   helo_data=REMOTE_SMTP_HELO_DATA
.endif
# end hack

=====================================================================

Warning. I have not considered TLS or other configuration options
which may well be broken as the above stands.

ael





More information about the Pkg-exim4-users mailing list