----- Original Message -----
From: "Daniel Schatz" <daniel.schatz@???>
To: <exim-users@???>
Sent: Monday, November 24, 2003 12:07 PM
Subject: [Exim] smtp-forwarding
> Hi,
> i want to do some smtp-forwarding with exim. can someone tell me how to
> configure exim to forward all mails it gets for a specific domain, let's
> say example.com, to another ip-adress (my "hidden" mailserver). on the
> other hand exim should forward all mails from my "hidden" mailserver to
> all internet-domains, but should only accept incoming connections from
> my "hidden" mailserver (if the destination is everything but the
> example.com domain).
Before we begin, switch to Exim 4, you will have to do so sooner or later
anyway :) The rest of this mail discusses Exim 4.
First of all, configurations like these are problematic at the best of
times, and you should not be doing this if you don't *REALLY* have to. I
would recommend using Exim as the main server, you shouldn't need another
server inside, Exim is extremely secure and running another mail server is
duplication, and a waste of hardware. The only situation where I would
recommend a set-up like this is if you are using an old MS Exchange server
that is sending the underscore character in its HELO, and the NETBIOS name
of which can not be changed as it would effect large numbers of internal
users.
If you want to do this for strange archaic spam or virus filters, I urge you
to use alternatives like SpamAssassin and ClamAV, wich are safe, free, and
can be made to interact directly with Exim at the ACL stage of security
checking via the exiscan ACL patches, which are included as standard with
most new distribution packages. You can also use SpamAssassin and ClamAV (or
any other UNIX AV, free or commercial) via AMaViS, which can interact with
any mail server, including your current Exim 3, via SMTP.
If you absolutely have to have this, there are a few ways to acumplish it.
The cleanest way is by putting the internal server in a seperate zone, say,
for instance, intranet.example.com. The problem is that Exim checks DNS MX
records, configured host names, and configured domain lists to help prevent
misconfiguration. For instance, it will not like relaying out to example.com
if it is listed as the MX for example.com, it will squeal even more if the
remote server it relays to picks up and asnwers as "example.com" in its
bannar.
To split off the zones is relatively simple, it can be achieved by simple
smart host routes and some fancy rewriting rules in the Exim configuration
file.
First of all, you want to set up Exim's main configuration area like this:
domainlist local_domains = @ : example.com
hostlist relay_from_hosts = localhost : 192.168.1.1
Note that in your example, you used *.example.com. That would not work
correctly, as it would accept for foo.example.com and bar.example.com but
not example.com itself, Exim is strict about these things. If you want to
accept for example.com, and for any host under example.com, your domainlist
should look like this:
domainlist local_domains = @ : example.com : *.example.com
The @ also tells Exim to accept for its own hostname, either determined from
the system, or the value of primary_hostname in the configuration file. It
will accept mail sent to the host even if it is not under the example.com
zone, ie, if your host is yourname.yourisp.net, it would accept for
*@yourname.yourisp.net in addition to *@example.com and *@*.example.com.
Note that I have also included localhost in the relay_form_hosts hostlist,
this is not default, but it can be very useful, if you run webmail services
from the Exim machine, or use AMaViS, or any service that will deliver to
Exim over SMTP via the loopback interface.
I now digress from the topic slightly, if you are not doing this to get
around the underscore problem, you can skip the next section.
If you are doing this to solve the underscore problem (I am assuming so),
keep in mind that by default, Exim 4 rejects any mail from hosts that send
an underscore in their HELO line. This is to comply with the requirements of
RFC 2821. You will still need to configure it to accept the underscore
character from your internal server. The best way to do this is the one put
forward by Sheldon Hearn, who has devised a way to whitelist hosts allowed
to send the underscore character. This allows you to comply with RFC 2821,
while allowing mail through from hosts where you really need it. My own
version of Sheldon's method is below:
# In primary configuration area:
acl_smtp_helo = check_helo
helo_allow_chars = _
# In ACL area:
check_helo:
#
# Deny illegal helo arguments from hosts whose operators haven't
# contacted us and asked us to work around their problematic
# configurations.
#
deny message = syntactically invalid argument(s):
$sender_helo_name http://www.example.com/underscore.html
hosts = !+relay_from_hosts : *
condition = \
${if \
and { \
{ match {$sender_helo_name}{_} } \
{ \
!eq \
{${lookup{${lc:$sender_helo_name}} \
lsearch{/usr/local/etc/exim/broken_helo_hosts} \
{yes}{no} \
}} \
{yes} \
} \
} \
{true} \
}
#
accept
Note, the precondition hosts = !+relay_from_hosts : *. That means that the
underscore will always be accepted from the list of hosts your server relays
for. Any other hosts will have their mail blocked if they send an underscore
in the HELO line, unless they appear, one on each line, in the file
/usr/local/etc/exim/broken_helo_hosts (use which ever file you want, change
above to reflect your file name).
Also, in the deny message, you will see I include a URL. This should be a
page that explains to the remote admin why their mail is being blocked, and
direct them to contact you at postmaster@??? to have them
whitelisted if they can not fix the problem on their end. The URL does not
need to be included, according to RFC 2821, you should be dropping any mail
from these hosts, the white listing method designed by Sheldon is to show
some hosts some mercy, while not breaking the rules yourself. For an example
of what you could put in this URL, see
http://apollo.laserfence.net/underscore.html
NB: If you are skipping the section, you should start reading from this
point.
Anyway, back to the topic, once this is set up, your Exim machine will relay
mail out from the internal host. Now, you want to set up a mechanism to send
mail from outside sources to the internal host. First, configure the
internal host to accept for the internal domain you have chosen, let's stick
with intranet.example.com. Your internal machine should accept any mail to
*@intranet.example.com.
Now the fun part begins, in Exim's rewriting configuration, add a line like
this:
*@example.com $1@??? T
This rewrites the envelope TO: header. This is a change only visible to mail
servers, the envelope TO: address is never seen by the client, so this won't
affect addresses people see, or that are seen by external recipients. It is
a very simple rule, it would rewrite like this:
johndoe@??? would be matched to *@example.com and the first * would
match johndoe. johndoe is then copied into the $1 variable, and will be
written in like this: johndoe@???.
Thus, any mail sent from outside (or inside) to example.com will be
rewritten in the envelope to go to intranet.example.com, again, the mail
clients never see this change, it is only visible to servers. If external
users send mail to example.com, it will be intercepted and rewritten to
intranet.example.com, if users inside send mail, it will also be rewritten
to intranet.example.com, thus, mail will travel:
From outside:
To example.com: Internet -> Exim -> [Address Rewriter] -> Exim ->
Internal Server
From inside:
To other domains: Internal Server -> Exim -> Internet
To example.com: Internal Server -> Exim -> [Address Rewriter] -> Exim ->
Internal Server
If your internal server supports rewriting of this kind, you can set it up
there to prevent mesasges having to loop through the Exim machine first, if
the machine is fast, the delay should be minimal though. If you want to
accept mail for *.example.com (ie, all hosts under the zone) your rules
should look more like:
*@example.com $1@??? T
*@*.example.com $1@??? T
*@intranet.example.com * T
The third rule is important, I hope I have the syntax right, that excludes
mail to intranet.example.com from being rewritten if it should be received
externally. Else it might fall into a loop with the *.example.com rule,
although Exim should detect and prevent that, but better safe than sorry.
Now that we have addresses being rewritten, we can safely route mail to your
internal server with a router called a smart host in old Exim 3 terms, now
called a domainlist. Remember that the order of routers is important, the
first router that can deliver a message, will deliver the message. Your
smart host router should, in this case be very high up, unless you are doing
aliasing on the Exim server, then the smart host router should come after
the system alias router. It should always come after virus scanning if you
use a router on the Exim machine to do that. The router should look like
this:
intranet_users:
driver = manualroute
transport = remote_smtp
route_list = intranet.example.com 192.168.1.1 byname
This will deliver mail for intranet.example.com via SMTP to 192.168.1.1,
make sure that server sees intranet.example.com as a local domain, and *DOES
NOT* see example.com or *.example.com as local (as this would cause further
confusion and occasional errors).
Once this is all set up, your server will appear to the internet as directly
handing example.com. Your internal server should think it handles
intranet.example.com, and know that the external server handles example.com.
The external server converts any mail to example.com to intranet.example.com
and sends it to your internal server, which should accept it.
To end off, I should say that you could also directly send it via smart
host, without the rewriting or anything else, as mentioned in an e-mail from
Bernard Massot sent to the list while I was working on this one. This is
dangerous though, if your internal server thinks it is example.com and your
external server thinks it is example.com, there might be errors that cause
long delays and messages getting stuck in Exim's queue or dropped. If you
want to try this, you can do it in Exim 4 with a router like this:
smart_route:
driver = manualroute
transport = remote_smtp
route_list = !+local_domains 192.168.1.1 byname
This is also possible in Exim 3, check the syntax in your documentation.
Again, I urge you to switch to Exim 4, and not to use this set up if it can
be avoided, with Exim 4, spam and virus prevention can be done *AT* the Exim
server, so for those applications this should not be needed.
Hope this helps.
Will