A fresh Qmail installation on FreeBSD is something that i have to deal once a couple of years. It´s just one of those things that i could well live without, but the time will come again and usually i can’t remember of half of my previous installation…. this is my personal installation guide to do it faster and with less effort.
Why Qmail? Why FreeBSD? Well, if you come all the way into this dark corner of the Internet, you should know the answer to both… so moving on, this is a massive, uber-geek, fully comprehensive and detailed installation guide, so it takes time and some brain damage.
CAUTION: proceed at your own risk
1 – Installing daemontools
cd /usr/ports/sysutils/daemontools
make install clean
options selected: MAN, S_NORMAL, TESTS
add to /etc/rc.conf
svscan_enable=”YES”
svscan_servicedir=”/service”
2 – Installing ucspi-tcp
cd /usr/ports/sysutils/ucspi-tcp
make install clean
options selected: LIMITS, MANPAGES, RSS_DIFF
in fact i’m not using the limits patch, but it’s there if i want to. It offers a load limit, and a maximum connections from one IP address. Also is very easy, just set up some vars in tcp.smtp, ex:
:allow,MAXLOAD=”350″ # (the connection will be accepted only if load average is below 3.50)
:allow,MAXCONNIP=”5″ # (each IP address can get only 5 concurrent connections)
3 – Installing Qmail itself
cd /usr/ports/mail/qmail-tls
make extract
options selected: SMTP_AUTH_PATCH, QMAILQUEUE_PATCH, OUTGOINGIP_PATCH, LOCALTIME_PATCH, MAILDIRQUOTA_PATCH, BLOCKEXEC_PATCH, DISCBOUNCES_PATCH, SPF_PATCH
In the extracting process there was a failure fetching ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/distfiles/qmail/qmail-spf-rc5.patch-auth-tls, but i had it in another machine (it can be found here qmail-spf-rc5.patch-auth-tls) and just upload it to /usr/ports/distfiles/qmail/.
Also i would like to have the tarpit patch, but as this time it’s not on the port options, so i did manually.
cd /usr/ports/distfiles/qmail/
fetch http://www.palomine.net/qmail/tarpit.patch
cd /usr/ports/mail/qmail-tls/
make patch
cd work/qmail-1.03
patch -R < /usr/ports/distfiles/qmail/tarpit.patch
cd ../../
make install clean
Then make and install the certificate, we could use the port handy make target ‘make certificate’ that would generate and place a concatenated file in PEM format with a RSA key and a self signed certificate on /var/qmail/control/servercert.pem (as required by the TLS patch). But we would loose the key file and the certificate file, that we will use in other mail services and of course the insight of what is going on:
cd /var/qmail/control
openssl genrsa -out server.key 1024
openssl req -new -key server.key -out server.csr
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
cat server.key server.crt > servercert.pem
4 – Autorespond
This is hard…
cd /usr/ports/mail/autorespond
make install clean
5 – Ezmlm
This is also very hard…
cd /usr/ports/mail/ezmlm-idx
make install clean
options selected: none
6 – Vpopmail (with MySQL integration)
edit /etc/make.conf and add these lines
# Vpopmail
.if ${.CURDIR:M*/usr/ports/mail/vpopmail*}
WITH_CLEAR_PASSWD=1
WITH_MYSQL=1
WITH_MYSQL_LIMITS=1
WITH_VALIAS=1
WITHOUT_ROAMING=1
WITH_SINGLE_DOMAIN=1
LOGLEVEL="p"
.endif
save, exit, and
cd /usr/ports/mail/vpopmail
make install clean
The compilation process will also include the mysql client, in the options i disabled the SSL option as all the database access will be on the same server.
One really bad thing of vpopmail port is that installs everything in /usr/local/vpopmail (ala ports and freebsd hier), but usually /usr/local/ lives in the boot partition (slice in FreeBSD wonderland) / which is a small partition and outside the backups system. So i usually move this to the /home partition…
mv /usr/local/vpopmail
/home/ ln -s /home/vpopmail /usr/local/vpopmail
and change the home directory to /home/vpopmail
chpass vpopmail
Next you should fire up your MySQL server create a new database and a user with privileges and edit /usr/local/vpopmail/etc/vpopmail.mysql with host|port|user|password|database settings.
7 – Set-up main alias
Define the root, postmaster and mailer-daemon aliases to a account that you WILL later create
cd /var/qmail/alias
echo "myaccount@mydomain.com" > .qmail-root
echo "myaccount@mydomain.com" > .qmail-postmaster
echo "myaccount@mydomain.com" > .qmail-mailer-daemon
8 – Qmail configurations (control files)
Go to the control directory to set up qmail configurations
cd /var/qmail/control
The qmail-tls places the servercert under the normal qmaild user, but as we are going to use vpopmail, chown it.
chown vpopmail:vchkpw /var/qmail/control/servercert.pem
If you skip this starttls will not work correctly with the error:
454 TLS missing certificate: error:0200100D:system library:fopen:Permission denied (#4.3.0)
Empty the rcpthosts file. It’s filled with assigned domains to the server own IPs on install. This files controls the domains that we accept as local. If the domain of the address given in the RCPT TO command is listed here Qmail will accept the email, else it will (or not) relay it to other server.
cp /dev/null rcpthosts
Set the maximum simultaneously incoming emails, remember that SpamAssassin can eat up lots of resources, concurrencyincoming isn’t a standard qmail control file, we will be using it in the qmail-smtpd run script.
echo "20" > concurrencyincoming
Used from qmail-send, is the maximum number of simultaneous local delivery attempts (defaults to 10), i guess it makes sense to be at last as big as concurrencyincoming.
echo "20" > concurrencylocal
Again used by qmail-send, set up concurrencyremote (defaults to 20), max simultaneous remote deliveries.
echo "30" > concurrencyremote
Set-up default delivery to Maildir (this is read by /var/qmail/rc, that is executed by qmail-send run script).
echo "./Maildir" > defaultdelivery
Config the defaultdomain, it defaults to “me” control (a bit lower in this guide), and it is used by qmail-inject.
echo "domain.com" > defaultdomain
i really don’t quite understand the difference between envnoathost and defaultdomain, so i set-up the same value.
echo "domain.com" > envnoathost
and plusdomain, is used where the domain ends wirh a trailing + (plus sign) ??, i quite also don’t get why a domain is not in the normal host.domain.ext but like domain+, but if it does qmail-inject will use this value.
echo "domain.com" > plusdomain
Empty locals, because all domains will be in the virtual system.
cp /dev/null locals
Define “me”, this will be used in several places, and you will want to use a fqdn (and set up a reverse dns entry with the same value. Change this to your own fqdn (please don’t use mine). Also, it is a good idea to add this as an alias of your defaultdomain (if not the same).
echo "mail.domain.com" > me
If you want to customize the outgoing ip of your qmail, it defaults to your main, set up outgoingip control file. Again, remember to set up dns and reverse according, so your sent email doesn’t end up in spam folder.
echo "a.b.c.d" > outgoing
I lower the queue lifetime (defaults to 604800 secs = a week) to a much lower value (a day). It the mail doesn’t get delivered in one day it bounces back.
echo "86400" > queuelifetime
also timeoutsmtpd and timeoutremote (they timeout only after a massive 20 minutes), to a much lower value
echo "120" > timeoutsmtpd
echo "120" > timeoutremote
The default SPF record behavior. Will go with 4 (reject mails when SPF resolves to softfail). We can override this by source in /etc/tcp.smtp The full options are:
0: Never do SPF lookups, don’t create Received-SPF headers
1: Only create Received-SPF headers, never block
2: Use temporary errors when you have DNS lookup problems
3: Reject mails when SPF resolves to fail (deny)
4: Reject mails when SPF resolves to softfail
5: Reject mails when SPF resolves to neutral
6: Reject mails when SPF does not resolve to pass
echo "4" > spfbehavior
Configure tarpitting, from the patch website “tarpitcount is the
number of RCPT TOs you accept before you start tarpitting, and tarpitdelay is
the number of seconds of delay to introduce after each subsequent RCPT TO.”
echo "50" > tarpitcount echo "10" > tarpitdelay
Create tlsclientciphers and tlsserverciphers, these files have the available ciphers to client and server TLS communications.
openssl ciphers > /var/qmail/control/tlsclientciphers
openssl ciphers > /var/qmail/control/tlsserverciphers
Setup /etc/tcp.smtp, the compiled in cdb format of this file is used by tcpserver (that listens for incoming smtp connections and launches qmail-smtp) to setup variables that customize qmail behaviour and accept or reject incoming connections. You can find a template here, that must be customized to your needs (at least the IPs). Some stuff in this file will be more clear down this tutorial. After customization compile it to a cdb file.
tcprules /etc/tcp.smtp.cdb /etc/tcp.smtp.tmp < /etc/tcp.smtp
9 - Qmail start-up scripts and directories
cd /var/qmail/
edit rc
and copy rc file content save and mark it executable
chmod +x rc
create the daemontools scripts directories
mkdir -p supervise/qmail-pop3d/log
mkdir -p supervise/qmail-smtpd/log
mkdir -p supervise/qmail-send/log
and log directory (each service will automagically create it's own subdirectory on startup)
mkdir -p /var/log/qmail
chown qmaill /var/log/qmail
create qmail-pop3 run script, change the IP to where the pop3 daemon will listen for incoming connections and mark it executable
cd /var/qmail/supervise/qmail-pop3d
edit run
chmod +x run
now qmail-pop3-log, you can customize 's' the number of max bytes of each log file, and 'n' the number of log files to keep before rotating. I use the max value for bytes - 16777215 (16Mb) and keep 5 files. So each service will keep about 80Mb worth of logs.
cd /var/qmail/supervise/qmail-pop3d/log
edit run
chmod +x run
A note about djb multilog date format, they are in strange (precise) timestamp, like this @400000004fff531605fc768c. To convert it to something human readable you can use tai64nlocal. Ex:
tail -f /var/log/qmail/qmail-smtpd/current | tai64nlocal
Now do the same for qmail-send (run and log) and qmail-smtpd (run and log script).
In qmail-smtpd run please set the correct ip address, and it may be necessary to change the softlimit value, max memory in bytes used per qmail-smtpd run (more on this later).
10 - Stop sendmail, replace sendmail with qmail and start qmail
/etc/rc.d/sendmail stop
and make it permanently in /etc/rc.conf
# Disable Sendmail
sendmail_enable="NO"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"
FreeBSD comes with a mailwrapper that is used system wide by mail user programs (MUAs), so no need to symlink to the sendmail binary, just adjust mailer.conf and be confident that all programs will use qmail
Edit /etc/mail/mailer.conf with these:
sendmail /var/qmail/bin/sendmail
send-mail /var/qmail/bin/sendmail
mailq /var/qmail/bin/qmail-qread
newaliases /var/qmail/bin/newaliases
hoststat /var/qmail/bin/qmail-tcpto
purgestat /var/qmail/bin/qmail-tcpok
Now link the startup scripts to the /service dir to startup Qmail.
ln -s /var/qmail/supervise/* /service/
Download and put somewhere qmailctl, a pretty neat bash script that makes life much more easier to start, stop, make the cdb file, flush the queue, etc.
wget http://www.marcogoncalves.com/wp-content/uploads/2012/08/qmailctl
mv qmailctl /usr/local/bin/
chown +x /usr/local/bin/qmailctl
11 - Test the basic qmail setup
Now, we should have a functional email system. Some features are still missing, but this is the core and this is the time to taste it before adding extra layers.
Stop/start/stat qmail
qmailctl stop
qmailctl start
qmailctl stat
Create a dummy domain, list it and remove it
vadddomain dummy.com
vmoddomlimits -S dummy.com
vdeldomain dummy.com
If all goes nice and smooth, configure a real domain at vpopmail, configure DNS mx and test it. Send and reception of email within local accounts and remote accounts. Emails with attachments of different sizes. SMTP with TSL and without, etc. Most problems can be debugged with the aid of the logs in /var/log/qmail/* or telnet the service. Check the quota system, if the maildirsize (/home/vpopmail/domains/domain.com/user/Maildir/maildirsize) is correctly updated on each operation.
Actually i found myself a big no-no, because on email reception vpopmail was writing two times the same email in the maildirsize hence reporting a double usage of quota... i trace this with a help of Google™ and found a bug report that help me solve the problem. With a bit of source code edit, re-compilation and re-installation of vpopmail all was fine.
12 - Install Qmailadmin
Qmailadmin is a web interface for managing the domains emails by domain administrators. It's a bit old school, uses cgi interface to a elf binary, and the layouts suck. But for now is the best tool that just works out of the box.
You must have Apache running (the qmailadmin binary is setuided to change on call to the vpopmail:vchkpw user) but i rather like mpm-itk to set the user at virtualhost level), mod_cgi or mod_cgid, and if you want clean url's mod_rewrite.
First create a home directory to qmailadmin
cd /home
mkdir qmailadmin
cd qmailadmin
mkdir logs
The port install is a bit awkward because we can't configure all with make.conf and we will make changes in the Makefile.
cd /usr/ports/mail/qmailadmin
edit Makefile
and make these changes
CGIBINDIR?= /home/qmailadmin/cgi-bin
CGIBINSUBDIR?=
CGIBINURL?= /
WEBDATADIR?= /home/qmailadmin/www
WEBDATASUBDIR?=
WEBDATAURL?=
MAXUSERSPERPAGE?= 15
MAXALIASESPERPAGE?= 25
and also
CONFIGURE_ARGS+= \
--enable-qmaildir=${QMAIL_PREFIX} \
--enable-htmldir=${WEBDATADIR} \
--enable-imagedir=${WEBDATADIR}/images \
--enable-imageurl=/images \
--enable-htmllibdir=/home/qmailadmin/templates \
--enable-cgibindir=${CGIBINDIR} \
--enable-cgipath=/cgi-bin \
--enable-vpopmaildir=${VPOPMAIL_DIR} \
--enable-autoresponder-path=${LOCALBASE}/bin \
--enable-maxusersperpage=${MAXUSERSPERPAGE} \
--enable-maxaliasesperpage=${MAXALIASESPERPAGE} \
--enable-ezmlmdir=${LOCALBASE}/bin
exit and save.
make install clean
and select CATCHALL, IDX, IPAUTH, TRIVIAL PASSWORD, USER_INDEX
cd /home
chown -R vpopmail:vchkpw qmailadmin
cd /home/qmailadmin/cgi-bin/
mv qmailadmin qmailadmin.cgi
chmod 550 qmailadmin.cgi
If you don't have mod-itk in Apache DON'T chmod qmailadmin.cgi file (that is leave the sticky bit on). Now for the Apache Virtualhost:
<VirtualHost aaa.bbb.ccc.ddd:80>
ServerName email.domain.com
DocumentRoot "/home/qmailadmin/cgi-bin/"
CustomLog "/home/qmailadmin/logs/access.log" combined
ErrorLog "/home/qmailadmin/logs/error.log"
AssignUserId vpopmail vchkpw
<Directory "/home/qmailadmin">
Order deny,allow
Allow from all
</Directory>
# Rewrite
RewriteEngine on
RewriteCond %{REQUEST_URI} !(images) [NC]
RewriteRule ^/cgi-bin(.*)$ /qmailadmin.cgi/$1 [L]
DirectoryIndex qmailadmin.cgi
Options +ExecCGI
AddHandler cgi-script cgi
Alias /images/ /home/qmailadmin/www/images/
</VirtualHost>
restart Apache, and point your browser to ServerName to test qmailadmin. You can (kind of) customize the templates in /home/qmailadmin/templates/html.
13 - Install Imap Server
For the IMAP services we will be using Dovecot, a fast and secure imap server. It will be used mainly by the webmail and also by mobile devices. The installation? Quite simple, again thanks to the fabolous ports system.
cd /usr/ports/mail/dovecot2
make install clean
select DOCS, EXAMPLES, KQUEUE, SSL, VPOPMAIL
Add dovecot_enable="YES" to /etc/rc.conf.
Now for the configuration, the Dovecot is a highly configurable IMAP and POP server and that has a price, lots and lots of configurations options to consider. We will be using only the IMAP, as the POP service is provided by qmail-pop3d, also we want to have a SSL aware server for encrypted sessions in untrusted environments.
One must keep in mind that Vpopmail quota system doesn't account emails flagged as deleted or in the Trash folder (this is default in the Courier suite maildir++ implementation). As i didn't found any Vpopmail switch equivalent to the -with-trashquota in Courier to account emails in Trash, we have to enforce the same behavior in Dovecot (to discard deleted emails for quota calculations). We will also automagically create for the user the Trash, Junk, Drafts and Sent folders.
The port places at /usr/local/share/doc/dovecot/example-config all configuration files with all options from where you can jump start building your own custom configuration, but as a nice and friendly guy i am, my own configuration is posted here, if you are following this guide you only need download it, extract it to /usr/local/etc/dovecot/ and set the correct Listen IP address in dovecot.conf. How cool is that?
We will be using the certificate and key that we generated for qmail, so /var/qmail/control/server.crt and /var/qmail/control/server.key must exist.
Go ahead, customize the Dovecot configuration. And then fire it up:
/usr/local/etc/rc.d/dovecot start
Now test with an IMAP client or with telnet. Delete messages (or move to Trash folder) and check the quota. Logging is done to /var/log/mailog. To test the SSL features you can use a handy little ssl client that is bundled with openssl:
openssl s_client -crlf -connect aaa.bbb.ccc.ddd:993
With the IMAP server up and running is very easy to add an webmail to your system, i like a lot the excellent Roundcube webmail project.
14 - POP3 and SMTP over SSL
In current times, when users rely more and more on laptops, tablets and mobile devices to get things done through all kind of non-secure networks (think public Wi-Fi), it's very important to provide encryption and to educate your users to the importance of using it.
To add SSL support to POP3 and to SMTP (already has TLS but is quite easy to provide SSL too), we must install a handy little SSL proxy that will take care of the SSL layer transparently. We will install this (you guessed it) using the ports system:
cd /usr/ports/security/stunnel/
make install clean
options selected: PTRHEAD
now create the stunnel pop3 configuration file. Edit /usr/local/etc/stunnel/pop3.conf script (download it here) and replace the mail.domain.com after qmail-popup with the value you have in /var/qmail/control/me (unfortunately i couldn't find way to inject this in the configuration file, so if you change it you must change it here also...).
Next, it's just like step 9, just create /var/qmail/supervise/qmail-pop3ds and /var/qmail/supervise/qmail-pop3ds/log directories and put there the correspondent run scripts.
cd /var/qmail/supervise
mkdir qmail-pop3ds/log
the /var/qmail/supervise/qmail-pop3ds/run script will call stunnel that will take care of the SSL layer (remember to customize the IP address). And of course the /var/qmail/supervise/qmail-pop3ds/log/run script to take care of the logging. Mark both files as executable and your are ready to SSL.
Make a symbolic link to /services to fire the service up and you can test it with openssl
ln -s /var/qmail/supervise/qmail-pop3ds /service/qmail-pop3ds
svstat /service/qmail-pop3ds
openssl s_client -crlf -connect aaa.bbb.ccc.ddd:995
and you should be in an encrypted POP3 session. Now for the SMTP over SSL is just the same logic here are the files you need:
/usr/local/etc/stunnel/smtp.conf
/var/qmail/supervise/qmail-smtpds/run
/var/qmail/supervise/qmail-smtpds/log/run
and another treat, an updated qmailctl file accounting the new encrypted services.
15 - Clam Anti Virus, Spam Assassin and Qmail-scanner
We will install ClamAV an awesome open source anti-virus, SpamAssassin from Apache foundation as a spam filter and qmail-scanner to glue this stuff together with qmail.
First thing, ClamAV
cd /usr/ports/security/clamav
make install clean
options selected: ARC, ARJ, DOCS, ICONV, LHA, LLVM, TESTS, UNRAR, UNZOO
Add the rcvars to /etc/rc.conf
clamav_clamd_enable="YES"
clamav_freshclam_enable="YES"
and fire it up, the configuration dafaults should be good for both clamd (the ClamAV daemon) and the freshclamd (the virus definition database updater daemon).
Now, for the SpamAssassin
cd /usr/ports/mail/p5-Mail-SpamAssassin
make install clean
options selected: SPAMC, DKIM, GNUPG, RAZOR, DCC
like clamav, the configuration defaults should be fine. Just a tweak in rc.conf to rest assured that users can't mess up our system. So, put into /etc/rc.conf:
spamd_enable="YES"
spamd_flags="--nouser-config --username=spamd"
this is actually something that i want to change in the future, to be able to give to users the possibility of customizing SpamAssassin for their own accounts/domains.
Run the rules updater to see if everything goes well and start it up.
sa-update -v
/usr/local/etc/rc.d/sa-spamd start
we should put the ruleset in a periodic script, edit /usr/local/etc/periodic/daily/spamd and paste
#!/bin/sh
#
# Updates Spamassassin rules
#
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
/usr/local/bin/sa-update -v && /usr/local/etc/rc.d/sa-spamd restart
rc=0
exit $rc
And now, the glue of all this, the qmail-scanner script. The best way that i found was to customize was to edit the Makefile of the port. So edit /usr/ports/mail/qmail-scanner/Makefile and change the configure args to:
CONFIGURE_ARGS+= \
--qmaildir "${QMAIL_PREFIX}" \
--spooldir "${SPOOLDIR}" \
--etcdir "${SPOOLDIR}" \
--logdir "${SPOOLDIR}" \
--bindir "${PREFIX}/bin" \
--qmail-queue-binary "${QMAIL_QUEUE}" \
--mime-unpacker "reformime" \
--no-QQ-check \
--batch \
--log-details yes \
--sa-quarantine "10" \
--unzip yes \
--add-dscr-hdrs yes \
--scanners "clamdscan,mhr,fast_spamassassin=SPAM:"
we are adding several options, the first "log-details" discards syslog and logs to a nice csv formatted (that we can later parse for statistics) file in /var/spool/qscand/mailstats.csv, next "sa-quarantine" gets an identified spam message to get quarantined if the spam score is bigger than 10 (adjustable). The "unzip" option makes the qmail-scanner to unzip the attachments, it makes more sense to unzip it once and then feed the uncompressed attachments to Spamassassin and Clamav than to let each one them to do their own unzip. The "add-dscr-hdrs", adds X-Qmail-Scanner headers to the message (this is good to check fast if a message has passed trough the system.
And finally the strangest option --scanners "clamdscan,mhr,fast_spamassassin=SPAM:", normally the Qmail-scanner configuration script auto-detects and configures for the filters installed in the system but we need to override to have the subject rewritten for emails that have been scored high enough to be marked by SpamAssassin but not as high to quarantine them. The required score for an email be declared as spam by SpamAssassin is 5 (it can be adjusted in /usr/local/etc/mail/spamassassin/local.cf with the required_score option).
So, with these options:
Email scoring < 5 is normally delivered Email scoring > 5 and < 10 is delivered with the subject rewritten to "SPAM:original subject" Email scoring > 10 is automatic quarantined to /var/spool/qscand/quarantine/spam Maildir and not delivered
Now we must adjust the permissions, /var/spool/qscand is the directory that all the action takes in, and the both SpamAssassin and Clamav will work here, the best solution i have found is to change both the daemon users group to qscand. Find the qscand group in /etc/group (in my system is 98) and then use chpass or equivalent to change the spamd and clamav user.
chpass clamav
chpass spamd
and change the Gid to 98 (the group id of qscand that you checked in /etc/group).
One strange thing with qmail-scanner is that for local users it bypasses SpamAssassin checks, but for authenticated users it doesn't... when an user is authenticated we have the TCPREMOTEINFO environment variable set so we can check it.
Open /usr/local/bin/qmail-scanner-queue.pl and find "sub spamassassin {" around line 2697 and change:
sub spamassassin {
#Don't bother if this is going to be quarantined
return if ($quarantine_event);
#Only run SA if mail is from a "remote" SMTP client, or QS_SPAMASSASSIN
#is defined via tcpserver...
if ($QS_RELAYCLIENT && !$ENV{'QS_SPAMASSASSIN'}) {
&debug("spamassassin: don't scan as RELAYCLIENT implies this was sent by a local user");
return;
}
to
sub spamassassin {
#Don't bother if this is going to be quarantined
return if ($quarantine_event);
#Only run SA if mail is from a "remote" SMTP client which is not SMTP athenticated, or QS_SPAMASSASSIN
#is defined via tcpserver...
if (!$ENV{'QS_SPAMASSASSIN'}) {
if ($QS_RELAYCLIENT){
&debug("spamassassin: don't scan as RELAYCLIENT implies this was sent by a local user");
return;
}
if ($ENV{'TCPREMOTEINFO'}){
&debug("spamassassin: don't scan as TCPREMOTEINFO implies this was sent by a SMTP AUTHenticated user");
return;
}
}
And that does the trick.
Update 28-04-2013
In my latest Qmail install, with qmail-scanner-2.10, this is not needed anymore, as qmail-scanner-queue.pl as been updated to get the authenticated users into consideration. The code isn't exactly the same as i proposed (it should be better) but the end result is the same. So, no need to hack qmail-scanner-queue.pl and emails from authenticated users skip by apam checks.
A little extra configuration that must be done is the internal qmail-scanner filter rules. Copy quarantine-events.txt.sample to quarantine-events.txt and open it.
cd /var/spool/qscand
cp quarantine-events.txt.sample quarantine-events.txt
The file is well commented and by itself it blocks some virus and spam without the need to call external Spam-Assassin and Clamav. It works out of the box without any customization. Then it must be compiled to Berkeley DB format.
/usr/local/bin/qmail-scanner-queue.pl -g
Next, we must update our /etc/tcp.smtp to use our anti-spam system, we compiled Qmail with the qmailqueue patch that easily allows us to change to the qmail-scanner-queue. Updated tcp.smtp here. Then compile it to cdb format that is used by tcpserver.
qmailctl cdb
And finally, the system anti-spam system maintenance. First we need to delete the old quarantined messages, a periodic script will be fine, so edit /usr/local/etc/periodic/daily/clear-quarantined-emails and paste:
#!/bin/sh
#
# Deletes old quarantined emails by qmail-scanner and and cleanup old temp files
#
/usr/bin/find /var/spool/qscand/quarantine/* -type f -mtime +10 -exec /bin/rm -f {} \;
/usr/local/bin/qmail-scanner-queue -z
rc=0
exit $rc
and for the log rotation, we will use newsyslog (Linux folks should check logrotate). Edit /etc/newsyslog.conf and add a couple of lines, to rotate every day at 6am and keep 3 bzip2 compressed historical files.
/var/spool/qscand/quarantine.log qscand:qscand 640 3 * $D6 JCB
/var/spool/qscand/qmail-queue.log qscand:qscand 640 3 * $D6 JCB
/var/spool/qscand/mailstats.csv qscand:qscand 640 3 * $D6 JCB
16 - Adjust softlimit
In the qmail-smtpd run script (and qmail-smtpds for SMTP over SLL), there is an 100 Megabytes memory limit, this was set-up deliberately high to avoid any problems during the installation, but now is time to adjust it to a correct value. Each system is different, and has different memory requirements, so to adjust it:
1 - set the SOFTLIMIT down in the run script
2 - restart Qmail
3 - try to send an email trough SMTP or SMTP over SLL till you get '451 qq temporary problem (#4.3.0)' or on smtp-auth login '/libexec/ld-elf.so.1: /usr/lib/libstdc++.so.6: mmap of data failed: Cannot allocate memory'
4 - when that happens start to incrementally raise the limit
5 - don't forget to restart Qmail on each increment
6 - when the '451' error code goes away add a couple of Megabytes more.
Congratulations, you have make it all the way, by now you should be a proud system administrator with a full featured email system installed on your FreeBSD box. But you can (should) go the extra mile.
Nice, you are here for the extra mile.
The big picture: Qmail is bundled with a little but effective piece of anti-spam software, rblsmtpd that stands in front of the smptd server and checks DNS-based block lists of host servers known to disseminate spam, phishing attacks and other forms of malicious email. I can't just put this in front of my main Qmail installation because most of our users send legitimate email trough dynamic ip addresses many of them listed in these lists. So, to be able to use this powerful (and low resources compared with SpamAssassin and Clamav), i will setup another Qmail instance, that i will call 'mx.domain.com'. This will be the server that will be published in DNS MX records, so the incoming email will be filtered by rblsmtpd then routed (with artificial smtproutes) to the main Qmail that will check the email with Clamav and SpamAssassin. Our users will be continue to to send (and receive) trough the main 'mail.domain.com' instance.
As many stuff will be similar to the main Qmail instance it will not be as detailed. So, check the previous page if needed.
17 - Install a jail for the Mail eXchanger
Create a jail, you know how to do that, right? I recommend an excellent article about FreeBSD jails with ezjail.... now, enter into the jail, the next operations if not stated otherwise are all inside the newly created jail.
18 - Install daemontools and ucspi-tcp
cd /usr/ports/sysutils/daemontools
make install clean
options selected: MAN, S_NORMAL, TESTS
add to /etc/rc.conf
svscan_enable="YES"
svscan_servicedir="/service"
make /service directory and start svscan
mkdir /service
/usr/local/etc/rc.d/svscan start
ucspi-tcp
cd /usr/ports/sysutils/ucspi-tcp
make install clean
options selected: LIMITS, MANPAGES, RSS_DIFF
19 - Install Qmail itself
cd /usr/ports/mail/qmail-tls
make install clean
options selected: BLOCKEXEC_PATCH , DISCBOUNCES_PATCH, SPF_PATCH
20 - Set-up main alias
Define the root, postmaster and mailer-daemon aliases to a account that you WILL later create
cd /var/qmail/alias
echo "myaccount@mydomain.com" > .qmail-root
echo "myaccount@mydomain.com" > .qmail-postmaster
echo "myaccount@mydomain.com" > .qmail-mailer-daemon
21 - Qmail configuration
First the tricky part, we must get lots of values from the main Qmail and keep them in sync, we will use a mount null_fs. Really hope that you choosen the ezjail path (if not adapt to your system).
cd /var/qmail/control
mkdir main
Now exit the jail to the host environment, and if you created the jail with ezjail (i sure hope so), just edit /etc/fstab.mx_domain_com and add a line so ezjail can do the null mount for you.
/var/qmail/control /usr/jails/mx.domain.com/var/qmail/control/main nullfs ro 0 0
Restart and log on
/usr/local/etc/rc.d/ezjail restart mx.domain.com
ezjail-admin console mx.domain.com
And there you go, all the control files of the main Qmail are right in /var/qmail/control/main. Now we need to pull 3 of them with symbolic links (rcpthosts, morercpthosts and morercpthosts.cdb). In a new Qmail install, morercpthosts and morercpthosts.cdb don't exist, so touch them in the main host environment.
cd /var/qmail/control
rm rcpthosts
ln -s main/rcpthosts ./
ln -s main/morercpthosts ./
ln -s main/morercpthosts.cdb ./
Now, take care of other configuration files (in doubt what you are doing check previous page, section 8).
echo "20" > concurrencyincoming
echo "20" > concurrencylocal
echo "30" > concurrencyremote
echo "domain.com" > defaultdomain
echo "domain.com" > envnoathost
echo "domain.com" > plusdomain
cp /dev/null locals
echo "mx.domain.com" > me
echo "172800" > queuelifetime
echo "120" > timeoutsmtpd
echo "120" > timeoutremote
echo "4" > spfbehavior
Generate the certificate for TLS
openssl genrsa -out server.key 1024
openssl req -new -key server.key -out server.csr
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
cat server.key server.crt > servercert.pem
chown qmaild servercert.pem
And available ciphers files
openssl ciphers > /var/qmail/control/tlsclientciphers
openssl ciphers > /var/qmail/control/tlsserverciphers
Setup /etc/tcp.smtp, this will be much more simpler that the one in the host environment.
echo :allow,QMAILQUEUE=\"/var/qmail/bin/qmail-queue\" > /etc/tcp.smtp
tcprules /etc/tcp.smtp.cdb /etc/tcp.smtp.tmp < /etc/tcp.smtp
Now the magic that makes this thing actually work, the smtproutes, a file that let us create artificial SMTP routes. Of all the mail that arrives, we only accept for the domains that are in rcpthosts (and morercpthosts), so we can send all mail to our main Qmail server.
echo ":aaa.bbb.ccc.ddd" > smtproutes
22 - Qmail start-up scripts and directories
This is a simplified version of point 9.
cd /var/qmail/
edit rc
and copy the rc file content save and mark it executable
chmod +x rc
create the daemontools scripts directories
mkdir -p supervise/qmail-smtpd/log
mkdir -p supervise/qmail-send/log
and log directory
mkdir -p /var/log/qmail
chown qmaill /var/log/qmail
Now download and place the scripts for qmail-smptd (/var/qmail/supervise/qmail-smptd/run and /var/qmail/supervise/qmail-smptd/log/run) and qmail-send (/var/qmail/supervise/qmail-send/run and /var/qmail/supervise/qmail-send/log/run script). Don't forget to mark all the run scripts executable.
23 - Stop sendmail, replace sendmail with qmail and start qmail
/etc/rc.d/sendmail stop
and make it permanently in /etc/rc.conf
sendmail_enable="NO"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"
setup FreeBSD mailwrapper /etc/mail/mailer.conf
sendmail /var/qmail/bin/sendmail
send-mail /var/qmail/bin/sendmail
mailq /var/qmail/bin/qmail-qread
newaliases /var/qmail/bin/newaliases
hoststat /var/qmail/bin/qmail-tcpto
purgestat /var/qmail/bin/qmail-tcpok
Start Qmail
ln -s /var/qmail/supervise/* /service/
And, yes there you do have a qmailctl tailored to this Qmail installation (without pop3).
24 - Wrapping up and final thoughts
Like in the main server adjust the softlimit in /var/qmail/supervise/qmail-smptd/run (check how to do this in the previous page).
Anytime you create a new domain in the main Qmail, you must reload this instance so it will recognize the domain as local. As a lazy bastard i am, i put this in a root cronjob running once every 15 minutes
*/15 * * * * /usr/local/bin/qmailctl reload
Don't forget to configure the DNS MX record to point to this instance, and to have an A record like mail.domain.com to hand out to users.
The main weakness of this installation, is that if a clever spammer discovers that mail.domain.com accepts incoming emails for local domains, he can spam down your users bypassing the rbl tests.
Any comments, rants, soul pains, random thoughts are appreciated.