amavisd-new + qmail dual MTA setup
Some 'big picture' ;).
I will deal here only with essential things which definitely have to be done in order to run amavisd-new with qmail. However, this WILL NOT assure top performance - please see suggestions later on.
- qmail
- virus scanner (optional but recommended)
- operating system of Your choice (FreeBSD, of course :)
- some time (20 minutes should be most sufficient)
http://cr.yp.to/daemontools/install.html
http://cr.yp.to/ucspi-tcp/install.html
Fetch qmail distribution from http://cr.yp.to/qmail.html.
Unpack into temporary directory and create two (2) identical copies of what You have just extracted, name them qmail-outside and qmail-inside (this were names I chose (and will refer to in the whole document), choose Your own If You wish).
'The qmail system is heavily partitioned for security; it does almost nothing as root', each its part runs as a different user - therefore You will need to create them:
group nofiles-outside
members: alias-outside, qmaild-outside, qmaill-outside, qmailp-outside
group qmail-outside
members: qmailq-outside, qmailr-outside, qmails-outside
and
group nofiles-inside
members: alias-inside, qmaild-inside, qmaill-inside, qmailp-inside
group qmail-inside
members: qmailq-inside, qmailr-inside, qmails-inside
File INSTALL.ids in the qmail source directory deals with this problem. Just use the correct suffix. For FreeBSD You may use this script.
Now create directories:
mkdir /var/qmail-outside
mkdir /var/qmail-inside
cd to qmail-outside src directory and edit files:
conf-qmail (configuration file for qmail directory):
change directory to reflect Your directory, e.g.:
/var/qmail-outside
This is the qmail home directory. It must be a local directory, not
shared among machines. This is where qmail queues all mail messages.
The queue (except for bounce message contents) is crashproof, if the
filesystem guarantees that single-byte writes are atomic and that
directory operations are synchronous. These guarantees are provided by
fixed-block filesystems such as UFS and by journaling filesystems. Under
Linux, make sure that all mail-handling filesystems are mounted with
synchronous metadata.
conf-groups (configuration file for qmail groups):
change groups to reflect Your groups, e.g.:
qmail-outside
nofiles-outside
These are the qmail groups. The second group should not have access to
any files, but it must be usable for processes; this requirement
excludes the ``nogroup'' and ``nobody'' groups on many systems.
conf-users (configuration file for qmail users):
change users to reflect Your users, e.g.:
alias-outside
qmaild-outside
qmaill-outside
root
qmailp-outside
qmailq-outside
qmailr-outside
qmails-outside
The qmail system is heavily partitioned for security; it does almost
nothing as root.
The first eight lines of this file are the alias user, the daemon user,
the log user, the owner of miscellaneous files such as binaries, the
passwd user, the queue user, the remote user, and the send user.
Now You are ready to compile and install qmail-outside:
make setup check
After compilation and installation type:
./config
You should see something like this:
Your hostname is some.host.com.
Your host's fully qualified name in DNS is
some.host.com.
Putting some.host.com into control/me...
Putting host.com into control/defaultdomain...
Putting host.com into control/plusdomain...
Checking local IP addresses:
127.0.0.1: Adding localhost to control/locals...
192.168.0.1: Adding some.host.com to control/locals...
If there are any other domain names that point to you,
you will have to add them to /var/qmail-outside/control/locals.
You don't have to worry about aliases, i.e., domains with CNAME records.
Copying /var/qmail-outside/control/locals to /var/qmail-outside/control/rcpthosts...
Now qmail will refuse to accept SMTP messages except to those hosts.
Make sure to change rcpthosts if you add hosts to locals or virtualdomains!
If it prints something like this, You have to setup Your host in DNS correctly:
Your hostname is
some.host.com.
soft error
Sorry, I couldn't find your host's canonical name in DNS.
You will have to set up control/me yourself.
Now repeate the same procedure for qmail-inside (conf-qmail, conf-groups, conf-users, make setup check, ./config).
If You
are done, setup alias files (replace 'solko' with your login or mail address).
If the address begins with a letter or number, you may leave out the ampersand
(man dot-qmail):
cd ~alias-outside
echo "&solko" > .qmail-root
cp .qmail-root .qmail-mailer-daemon
cp .qmail-root .qmail-postmaster
cp .qmail-root .qmail-virusalert
cp .qmail-root .qmail-spamalert
cd ~alias-inside
echo "&solko" > .qmail-root
cp .qmail-root .qmail-mailer-daemon
cp .qmail-root .qmail-postmaster
cp .qmail-root .qmail-virusalert
cp .qmail-root .qmail-spamalert
Create *.cdb files for tcpserver:
/etc/tcp.smtp-outside, e.g.:
127.0.0.1:allow,RELAYCLIENT=""
192.168.0.1:allow,RELAYCLIENT=""
:allow
You will probably want to relay mail for this host as well for some subnet, e.g.:
127.0.0.1:allow,RELAYCLIENT=""
192.168.0.:allow,RELAYCLIENT=""
:allow
will relay mail for localhost and whole subnet 192.168.0.0/24.
/etc/tcp.smtp-inside:
127.0.0.1:allow,RELAYCLIENT=""
:deny
(we want to accept only mail from amavisd-new).
Make them:
tcprules /etc/tcp.smtp-outside.cdb temporary_file < /etc/tcp.smtp-outside
tcprules /etc/tcp.smtp-inside.cdb temporary_file < /etc/tcp.smtp-inside
Now setup supervise dirs. Either look at this page or use this script which does almost the same.
Using script for qmail-outside:
chmod 0700 qmail_make_supervise.pl
./qmail_make_supervise.pl
You are now ready to create supervise dirs. First, I kneed to know few things:
Where did You install qmail? (e.g. /var/qmail - default)
/var/qmail-outside
Where do You want to keep Your log files? (e.g. /var/log/qmail - default)
/var/log/qmail
What IP address will Your qmail listen to? (e.g. 192.168.0.1, type 0 (default) for all interfaces)
192.168.0.1
And what port? (e.g. 25 - default)
25
Where is the cdb file for tcpserver? (e.g. /etc/tcp.smtp.cdb)
/etc/tcp.smtp-outside.cdb
What suffix will You use? (e.g. -outside)
-outside
OK, so You want me to create files as follows:
Directory: /var/qmail-outside
Log directory: /var/log/qmail
IP address: 192.168.0.1
Port: 25
Control acces file for tcpserver: /etc/tcp.smtp-outside.cdb
Suffix: -outside
y/n?
y
Using script for qmail-inside:
You are now ready to create supervise dirs. First, I kneed to know few things:
Where did You install qmail? (e.g. /var/qmail - default)
/var/qmail-inside
Where do You want to keep Your log files? (e.g. /var/log/qmail - default)
/var/log/qmail
What IP address will Your qmail listen to? (e.g. 192.168.0.1, type 0 (default) for all interfaces)
127.0.0.1
And what port? (e.g. 25 - default)
10025
Where is the cdb file for tcpserver? (e.g. /etc/tcp.smtp.cdb)
/etc/tcp.smtp-inside.cdb
What suffix will You use? (e.g. -outside)
-inside
OK, so You want me to create files as follows:
Directory: /var/qmail-inside
Log directory: /var/log/qmail
IP address: 127.0.0.1
Port: 10025
Control acces file for tcpserver: /etc/tcp.smtp-inside.cdb
Suffix: -inside
y/n?
y
Let's have a look at control files for qmail-outside in /var/qmail-outside/control:
locals:
this file should be empty, delete everything but not the file itself.
rcpthosts:
add domains/hosts You wish to accept mail for (one per line). See suggestions later on.
smtproutes:
:127.0.0.1:10024
this tells qmail to send all mail to amavis.
defaultdomain and plusdomain:
change to Your needs, however, defaults should be ok for a mailgate setup.
And now look at control files for qmail-inside in /var/qmail-inside/control:
locals:
put here Your local domains/hosts or nothing - depends on Your needs. If You want to keep mails for Your mailgate host here, put its name here, otherwise create a proper MX pointing to another machine to avoid loops.
rcpthosts:
add domains/hosts You wish to accept mail for (one per line). This definitely should be a mirrored copy of rcpthosts in /var/qmail-outside/control. See suggestions later on.
defaultdomain and plusdomain:
change to Your needs, however, defaults should be ok for a mailgate setup.
smtproutes:
content depends on Your decision:
1. Will it be a mailgate?
add domain and IP address (optionally followed by a port - defaults to port 25) of the mailhost, e.g.:
domain.com:192.168.0.27:10025
which tells qmail to deliver all mail for domain.com to 192.168.0.27 on port 10025. I recommend setup like this. If You want to relay another domain, just add another record to this file. All other domains will be delivered according to MX lookups.
2. Will it be the mailserver itself?
You do not need to add anything, just adjust locals a virtualdomains and You are done here.
This should not be a very difficult task, right? Just a 'seek and destroy' mission ;). But be sure to kill the right process and disable proper startup file. Differs from system to system.
Don't forget to adjust mail wrapper (/etc/mail/mailer.conf in FreeBSD) or something like that to be able to send mail from this host.
Accepting mails
from openrelay server is probably not a good idea so You _would_ like to use
this. I know You would, trust me. Edit Your /var/qmail-outside/supervise/qmail-smtpd-outside/run
file and add rblsmtpd, e.g.:
before adding rblsmtpd:
#!/bin/sh
QMAILDUID=`id -g qmaild-outside`
NOFILESGID=`id -g qmaild-outside`
exec /usr/local/bin/softlimit -m 2000000 \
/usr/local/bin/tcpserver -H -R -v -P -x /etc/tcp.smtp-outside.cdb \
-u $QMAILDUID -g $NOFILESGID 192.168.0.1 25 \
/var/qmail-outside/bin/qmail-smtpd 2>&1
after adding rblsmtpd:
#!/bin/sh
QMAILDUID=`id -g qmaild-outside`
NOFILESGID=`id -g qmaild-outside`
exec /usr/local/bin/softlimit -m 2000000 \
/usr/local/bin/tcpserver -H -R -v -P -x /etc/tcp.smtp-outside.cdb \
-u $QMAILDUID -g $NOFILESGID 192.168.0.1 25 /usr/local/bin/rblsmtpd -r relays.ordb.org \
/var/qmail-outside/bin/qmail-smtpd 2>&1
Now check files /var/qmail-outside/rc and /var/qmail-inside/rc
and change them to something reasonable - but I think You should be happy with the script defaults ;)
We are done with qmails.
I am using NOD32 client/server version. It performs great and this is not some kind of advertising. It is fast and efficient. And as far as I know the daemon nod32d has never ever crashed since the time I started it for the first time ;).
But You have to use Your favourite one - amavisd-new supports a variety of them.
Most operating systems have its own port or package. If not, check http://www.ijs.si/software/amavisd/INSTALL.
Now You are ready to configure amavisd-new. This will not be given here in much detail as there are other very good documents dealing with it, look at amavisd-new documentation section.
Section I - Essential daemon and MTA settings
find
# MTA SETTINGS, UNCOMMENT AS APPROPRIATE,
# both $forward_method and $notify_method default to 'smtp:127.0.0.1:10025'
and add this below:
# USING qmail DUAL MTA SETUP
$forward_method = 'smtp:127.0.0.1:10025';
$notify_method = $forward_method;
***
Then do not forget to edit amavisd (added in amavisd-new-20030314-p1):
find
# to reduce the likelyhood of a qmail bare-LF bug (bare LF reported
# when CR and LF are separated by a TCP packet boundary) one may use
# this 'while' line, instead of the normal one:
### while (defined($_=$msg->getline)) {
while ( $msg->read($_,16384) > 0 ) {
$smtp_handle->datasend($_)
or die "sending mail body from file\n";
}
change
# to reduce the likelyhood of a qmail bare-LF bug (bare LF reported
# when CR and LF are separated by a TCP packet boundary) one may use
# this 'while' line, instead of the normal one:
while (defined($_=$msg->getline)) {
# while ( $msg->read($_,16384) > 0 ) {
$smtp_handle->datasend($_)
or die "sending mail body from file\n";
}
***
Section II - MTA specific (defaults should be ok)
Find and change like this:
$inet_socket_port = 10024; # accept SMTP on this local TCP port
$inet_socket_bind = '127.0.0.1'; # limit socket bind to loopback interface
@inet_acl = qw( 127.0.0.1 ); # allow SMTP access only from localhost IP
Section VII - External programs, virus scanners
find
@av_scanners = (
.
.
.
change
Well... uncomment and comment... the ones You want or don't want.
in my case:
['ESET Software NOD32 - Client/Server Version', '/usr/local/nod32/nod32cli',
'-a -r -d recurse --heur standard {}', [0], [10,11],
qr/^\S+\s+infected:\s+(.+)/ ],
You are definitely NOT done yet! Either read through amavisd-new documentation section or through amavisd.conf and amavisd itself. They are both HEAVILY commented.
rcpthosts':
Use symbolic links to mirror them and create some web interface for easier managment (if You have many domains), e.g.:
ln -s /var/qmail-inside/control/rcpthosts /var/qmail-outside/control/rcpthosts
ln -s /usr/local/www/data/qmail_web_interface/rcpthosts /var/qmail-inside/control/rcpthosts.
Edit (create) /var/qmail-outside/control/concurrencylocal
and add:
0
(We want to
check our mail before delivery | we are a mailgate | we have empty /var/qmail-outside/control/locals
file).
Edit (create) /var/qmail-outside/control/concurrencyremote
and add 2 or whatever You choose later for the option $max_servers in
amavisd.conf file.
Edit (create) /var/qmail-outside/control/timeoutsmtpd and add
30 which means a 30 second timeout on qmail-smtpd connection. I really don't know whether this is good or not but it helps/helped me a lot to prevent some nasty DOS attacks at tcpserver.
Take a look at /var/qmail-outside/supervise/qmail-smtpd-outside/run:
#!/bin/sh
QMAILDUID=`id -g qmaild-outside`
NOFILESGID=`id -g qmaild-outside`
exec /usr/local/bin/softlimit -m 2000000 \
/usr/local/bin/tcpserver -H -R -v -P -x /etc/tcp.smtp-outside.cdb \
-u $QMAILDUID -g $NOFILESGID 192.168.0.1 25 /usr/local/bin/rblsmtpd -r relays.ordb.org \
/var/qmail-outside/bin/qmail-smtpd 2>&1
and change like this:
#!/bin/sh
QMAILDUID=`id -g qmaild-outside`
NOFILESGID=`id -g qmaild-outside`
exec /usr/local/bin/softlimit -m 2000000 \
/usr/local/bin/tcpserver -c 100 -H -R -v
-P -l qmail-outside -x /etc/tcp.smtp-outside.cdb \
-u $QMAILDUID -g $NOFILESGID 192.168.0.1 25 /usr/local/bin/rblsmtpd -r relays.ordb.org \
/var/qmail-outside/bin/qmail-smtpd 2>&1
The '-c 100' parameter tells tcpserver how many concurrent connections it should accept. Use something reasonable for Your site.
The '-l qmail-outside' tells tcpserver not to look up local host name in DNS and use that name instead. Use something reasonable for Your site.
The '-H -R -P' parameters are nicely explained at tcpserver manpage. I always like to speed things up.
amavisd.conf:
Section I - Essential daemon and MTA settings
find
$max_servers = 2; # number of pre-forked children (default 2)
$max_requests = 10; # retire a child after that many accepts (default 10)
change
$max_servers = 2; # number of pre-forked children (default 2)
$max_requests = 350; # retire a child after that many accepts (default 10)
$max_requests performs better for me/others with a higher number.
Section II - MTA specific (defaults should be ok)
find
$unix_socketname = "$TEMPBASE/amavisd.sock"; # amavis helper protocol socket
#$unix_socketname = undef; # disable listening on a unix socket
# (default is undef, i.e. disabled)
# (usual setting is $TEMPBASE/amavisd.sock
change
# $unix_socketname = "$TEMPBASE/amavisd.sock"; # amavis helper protocol socket
$unix_socketname = undef; # disable listening on a unix socket
# (default is undef, i.e. disabled)
# (usual setting is $TEMPBASE/amavisd.sock
We do not need a socket.
Section III - Logging
find
$DO_SYSLOG = 1;
change
$DO_SYSLOG = 0;
What for?! We have
/var/amavis/amavis.log.
find
#$log_level = 2;
change
$log_level = 2;
It is really a good idea
to log. This log level is nice.
Section IV - Notifications, quarantine
find
$viruses_that_fake_sender_re = new_RE(
qr'nimda|hybris|klez|bugbear|yaha|braid|sobig'i );
add the new ones
$viruses_that_fake_sender_re = new_RE(
qr'nimda|hybris|klez|bugbear|yaha|braid|sobig|lirva'i );
This is _only_ an
example, you have to keep your virus list up-to-date on your own!
find
$final_virus_destiny = D_BOUNCE; # (defaults to D_BOUNCE)
$final_banned_destiny = D_BOUNCE; # (defaults to D_BOUNCE)
$final_spam_destiny = D_BOUNCE; # (defaults to D_REJECT)
$final_bad_header_destiny = D_PASS; # (defaults to D_PASS), D_BOUNCE suggested
change
$final_virus_destiny = D_BOUNCE; # (defaults to D_BOUNCE)
$final_banned_destiny = D_BOUNCE; # (defaults to D_BOUNCE)
$final_spam_destiny = D_DISCARD; # (defaults to D_REJECT)
$final_bad_header_destiny = D_PASS; # (defaults to D_PASS), D_BOUNCE suggested
Bouncing a spam message is almost every time a waste of time (D_REJECT is not a good idea with dual MTA setup), banned filename is almost always some kind of virus which fake its sender ;). But depends on Your needs, of course. If unsure set it to D_BOUNCE.
Section VII - External programs, virus scanners
find and change
$sa_local_tests_only = 1; # (default: false)
We do want only local tests.
Fire up your qmails:
ln -s /var/qmail-outside/supervise/* /var/service/
ln -s /var/qmail-inside/supervise/* /var/service/
and amavisd-new:
e.g. /usr/local/etc/rc.d/amavisd start for FreeBSD installation.
Don't forget to substitute right directories. Your qmails should start within few seconds.
If something do not work as You expected, check logs, read this again and start questioning me ;-).
If You find this document helpful, PLEASE SEND me some feedback to make it better. Thanks!
Copyright: copy&paste as You like (2004).
solko -at- imladris -dot- sk