Exim Log
Being a techie, reading the manual is something of a rarity. The Exim Specification, however, is one thing I do read. Just occasionally I find the need to make some notes. Being on the terse side, Exim's logging is occasionally hard to fathom. Having discovered my notes on this subject are somewhat out of date I've updated them...
Log Flags
| <= | message arrival |
| => | normal message delivery |
| -> | additional address in same delivery |
| *> | delivery suppressed by -N |
| ** | delivery failed; address bounced |
| == | delivery deferred; temporary problem |
Fields
| A | authenticator name (and optional id) |
| C | SMTP confirmation on delivery |
| CV | certificate verification status |
| DN | distinguished name from peer certificate |
| DT | time taken for a delivery |
| F | sender address (on delivery lines) |
| H | host name and IP address |
| I | local interface used |
| id | message id for incoming message |
| P | on <= lines: protocol used |
| on => lines: return path | |
| QT | time spent on queue |
| R | on <= lines: reference for local bounce |
| on => lines: router name | |
| S | size of message |
| ST | shadow transport name |
| T | on <= lines: message subject (topic) |
| on => lines: transport name | |
| U | local user or RFC 1413 identity |
| X | TLS cipher suite |
Message Reception
2002-10-31 08:57:53 16ZCW1-0005MB-00 <= kryten@dwarf.fict.example
H=mailer.fict.example [192.168.123.123]:9767
I=[82.148.225.15]:25 U=exim
P=smtp S=5678 id=<incoming message id>
X=TLSv1:DES-CBC3-SHA:168 CV=no
T="Rimmer Directive #271"
- 2002-10-31 08:57:53
- date and time
- 16ZCW1-0005MB-00
- Message ID
- kryten@dwarf.fict.example
- envelope sender address
- A bounce message is shown with the sender address "<>"
- if locally generated 'R=<message id>' is a reference to the message that caused bounce it
- H=mailer.fict.example [192.168.123.123]:9767
- host name, IP address, port
- Ommitted for locally generated messages
- The number given in square brackets is the IP address of the sending host.
- If there is a single, unparenthesized host name in the H field it has been verified to correspond to the IP address (see the host_lookup option).
- If the name is in parentheses, it was the name quoted by the remote host in the SMTP HELO or EHLO command, and has not been verified.
- If verification yields a different name to that given for HELO or EHLO, the verified name appears first, followed by the HELO or EHLO name in parentheses.
- Only the final address in square brackets can be relied on.
- I=[82.148.225.15]:25
- incoming_interface & incoming_port
- U=exim
- local user or RFC 1413 identity (ident lookups not implemented)
- P=smtp
- protocol for incoming message
- X=TLSv1:DES-CBC3-SHA:168
- TLS cipher suite
- S=5678
- Size
- X=TLSv1:DES-CBC3-SHA:168
- TLS cipher suite
- S=5678
- size of message
- id=<incoming message id>
- incoming message id
- T="Rimmer Directive #271"
- message subject (topic)
- "No chance you metal bastard"
Message Delivery
There are 2 formats. First is for remote deliveries:
2002-10-31 08:59:13 16ZCW1-0005MB-00 => marv <marv@hitch.fict.example>
R=localuser T=remote_smtp S=1234
H=mailer.fict.example [192.168.123.123]
C="250 2.0.0 i1G0Bjif055100 Message accepted for delivery"
QT=6s DT='0's
The second is for local deliveries:
2002-10-31 09:00:10 16ZCW1-0005MB-00 => monk@holistic.fict.example
R=dnslookup T=local_delivery S=1234
QT=10s DT=4s
For ordinary local deliveries, the original address is given in angle brackets after the final delivery address, which might be a pipe or a file. If intermediate address(es) exists between the original and the final address, the last of these is given in parentheses a fter the final address. The R and T fields record the router and transport that were used to process the address.
- generation of a reply message by a filter file gets logged as a "delivery" to the addressee, preceded by ">"
- second and subsequent addresses are flagged with "->" instead of "=>"
- When two or more messages are delivered down a single SMTP connection, an asterisk follows the IP address in the "[-=]>" lines
Greppage
Using grep(1) to pull info from logfiles is useful. But it is mildly annoying as multiple log lines refer to individual mails. The exigrep utility is a Perl script that searches one or more main log files for entries that match a given pattern. When it finds a match, it extracts all the log entries for the relevant message, not just those that match the pattern. Thus, exigrep can extract complete log entries for a given message, or all mail for a given user, or for a given host, for example.
The usage is:
exigrep [-l] [-t<n>] <pattern> [<log file>] ...
The -t argument specifies a number of seconds. It adds an additional condition for message selection. Messages that are complete are shown only if they spent more than <n> seconds on the queue.
The -l flag means "literal", that is, treat all characters in the pattern as standing for themselves. Otherwise the pattern must be a Perl regular expression. The pattern match is case-insensitive. If no file names are given on the command line, the standard input is read.
SMTP AUTH with Exim
The default exim install has the the acl acl_check_rcpt which includes the line:
accept authenticated = *
Which is fine. All that's needed now is the actual authenticators. These live near the bottom of the configure file, and are relatively easy:
plain:
driver = plaintext
public_name = PLAIN
server_condition = \
${if eq{$3}{${lookup{$2}lsearch{/usr/local/etc/exim/authtab}{$value}}}{1}{0}}
server_set_id = $2
login:
driver = plaintext
public_name = LOGIN
server_prompts = Username:: : Password::
server_condition = \
${if eq{$2}{${lookup{$1}lsearch{/usr/local/etc/exim/authtab}{$value}}}{1}{0}}
server_set_id = $1
## CRAM-MD5
## - more secure than any AUTH mechanism
## - **requires** passwords are stored as plain text
##
lookup_cram:
driver = cram_md5
public_name = CRAM-MD5
server_secret = ${lookup{$1}lsearch{/usr/local/etc/exim/authtab}{$value}fail}
server_set_id = $1
Creating the file authtab with the authentication data is also easy:
cd /usr/local/etc/exim/
echo username p4ssw0rd > authtab
chmod 0600 authtab
chown mailnull:mail
Testing
This is where things start to get tricky. Testing anything but the PLAIN authenticator manually is painful, so using a configurable MUA is preferred. However, as exim produces some nice helpful messages when debugging, testing manually can prove helpful. But first you need to encode the username and password in Base64. Save the following as encode.pl:
use MIME::Base64;
printf ("%s", encode_base64(eval "\"$ARGV[0]\""));
If this bOrks then install the required perl module from /usr/ports/converters/p5-MIME-Base64. Now encode your password:
# ./encode '\0username\0p4ssw0rd' AHVzZXJuYW1lAHA0c3N3MHJk
Now you can test Exim's PLAIN authenticator:
# exim -bh 123.123.123.123 **** SMTP testing session as if from host 123.123.123.123 **** but without any ident (RFC 1413) callback. **** This is not for real! LOG: SMTP connection from [123.123.123.123] >>> host in host_lookup? no (option unset) >>> host in host_reject_connection? no (option unset) >>> host in sender_unqualified_hosts? no (option unset) >>> host in recipient_unqualified_hosts? no (option unset) >>> host in helo_verify_hosts? no (option unset) >>> host in helo_try_verify_hosts? no (option unset) >>> host in helo_accept_junk_hosts? no (option unset) >>> using ACL "acl_check_connect" >>> processing "accept" >>> accept: condition test succeeded 220 empty.packet.org.uk ESMTP Exim 4.41 Tue, 27 Jul 2004 10:05:23 +0100 EHLO authtest.somedomain.com >>> authtest.somedomain.com in helo_lookup_domains? no (end of list) >>> host in pipelining_advertise_hosts? no (end of list) >>> host in auth_advertise_hosts? yes (matched "*") >>> host in tls_advertise_hosts? no (option unset) 250-empty.packet.org.uk Hello authtest.somedomain.com [123.123.123.123] 250-SIZE 16777216 250-8BITMIME 250-AUTH PLAIN LOGIN CRAM-MD5 250 HELP AUTH PLAIN AHVzZXJuYW1lAHA0c3N3MHJk >>> plain authenticator: >>> $1 = >>> $2 = username >>> $3 = p4ssw0rd >>> expanded string: 1 235 Authentication succeeded QUIT 221 empty.packet.org.uk closing connection LOG: SMTP connection from (authtest.somedomain.com) [123.123.123.123] closed by QUIT
Authenticating with SASL
The only real reason to run saslauthd is to allow authentication against /etc/master.passwd - this is not the best of ideas as you can't use CRAM-MD5 authentication, and the other authenticators transmit your password over the network - which is rather handy for crackers if you use SSH with password authentication. It also requires all mail users to have an account on the mail server - which is plain wrongness IMHO. But should you wish to ignore such sage advice then you'll need to build exim with the -DWITH_SASLAUTHD option. Then edit your authenticator.
plain:
driver = plaintext
public_name = PLAIN
server_condition = ${if saslauthd{{$2}{$3}}{1}{0}}
server_set_id = $2
I've not tested this. So YMMV.
Sender Permitted From
The first thing to do is install exim with SPF enabled. As this is FreeBSD that's dead simple:
cd /usr/ports/mail/exim-mysql make -DWITH_SPF install clean
This installs exim with the Exiscan ACL patches, MySQL support, and crucially installs libspf-alt. The Exiscan ACL patches and libspf-alt are required for SPF to work, the MySQL support is required only to suit my particular tastes.
Now make sure sendmail does not start, and exim does
editing /etc/rc.conf: sendmail_enable=NONE exim_enable=YES exim_flags="-bd -q30m" ## The default, but it's nice to state explicitly
And now ensure the standard commands refer to exim, not sendmail
cd /etc/mail cp mailer.conf mailer.conf.old cat mailer.conf.old | sed 's#libexec/sendmail/sendmail#local/sbin/exim#' > mailer.conf
By default exim is "secure", though only a fool would take my word for it, so check for yourself. Once exim is working, and it's secure... add this to the Exim ACLs:
deny
spf = fail
message = $sender_host_address is not allowed to send mail from $sender_address_domain
Jiggering with the Exim ACLs is far from easy. So where this line should go is left as an excercise to the reader.





