Consulting djbware Publications

3. Servers

Content:

  1. Unix services
  2. Environment variables
  3. Communication control (cdb)
  4. Logging
  5. qmail-smtpd
  6. qmail-qmtpd
  7. qmail-qmqpd
  8. qmail-pop3d
  9. qmail-send
  10. s/qmail and systemd

3.1 Unix services

Throughout this document, I assume that all Unix daemons (= services)

are under control of supervise (out of the Daemontools package) and served by sslserver (part of the UCSPI-SSL package) or tcpserver (part of the UCSPI-TCP6 package). The primary settings are given by so-called run-scripts.

Services are controlled by three mechanisms:

  1. A configuration file or run script which is calles once while the service is invoked (called) and containing 'life-cycle' settings.
  2. A control file to be read every time the service is instantiated; typically for every connection or session.
  3. Environment variables with depending information to be defined and populated according to the current connection.

Using Deamontools, a run script possesses all necessary (static) environment settings for the daemon and is used to start the service. By means of supervise's control environment, the service is monitored, started, and stopped conveniently. In order to do so, the run script needs to stay in the 'foreground' thus shall not become 'detached'.

However, other mechanisms will also work to invoke the service:

The provided run script samples for supervise are minimalistic only an focus on the service itself. However, using additional programs from Daemontools suite allows a fine-grained setting of a service, in particular to restrict memory usage in the system for a specific service. Apart from that, supervise automatically will re-invoke the service in a case of failure (i.e. a SIGINT) and thus makes the service high available without the need to maintain a so-called pid file, which might become corrupted or invalid as well.

Note: In the supervise 'universe' a service is identified and called by the name of the directory ist resides in (typically raised under the /service path) and not by the name of the invoking script.

Given systemd's capabilities, s/qmail can comply to those without a big hustle, as documented in section 3.10.

3.2 Environment variables

The Unix services make use of environment variables which are available for a process (sharing the same environment).

Environment variables can be provided in four different fashions:

  1. (Gobal) Exported variables in the run script; eg. export RELAYCLIENT="", or export BADMIMETYPE="+".
  2. (Gobal) By means of the envdir facility as part of the Daemontools package.
  3. (Gobal) Using a "profile" configuration file called in the run script by means of the "dot" syntax (. profile).
  4. (Individual) Setting the appropriate variable in the tcpserver/ sslserver cdb database.

While the first three cases define static and 'global' environments variables, the last case makes the environment variables client-dependent and - by means of tcprules - dynamically changeable. Any mixture is possible, though only the "last" setting of an environment variable becomes effective for the current process.

3.2.1 Common informational TCP connection variables

Connection variables like the server's and the client's IP address (TCPLOCALIP, TCPREMOTEIP) and ports, the depending DNS information (TCPLOCALHOST, TCPREMOTEHOST) as well as some authentication (TCPREMOTEINFO) are defined by tcpserver or sslserver and described in tcp-environ (together with the IPv6 compagnions). These are common variables for all servers, except for qmail-qmqpd.

3.2.2 Common mod_ssl variables

In case sslserver is used, some information about the TLS context and the content of the X.509 certificate are provided via mod_ssl:

3.3 Communication control with tcpserver/sslserver cdb's

One 'merit' s/qmail inherits for qmail is the dependency to use any service in conjunction with a network-enabled programm, available

Other daemons (i.e. inetd and xinetd) are not supported because they are not able to feed the required connection parameters to the servers.

By means of tcpserver/ sslserver a daemon may be supplied with additional 'rules' per IP connection.

Those 'rule sets' are defined by tcprules as part of the USPI-TCP6 package and may be verified by tcprulescheck programm. In order to do so, you need to define the appropriate environment variable, i.e. TCP6REMOTEIP and check those against the cdb.

Here, we use the following default file name for the cdb:

3.3.1 Bindung to specific IP addresses and ports

All Unix services available by means of tcpserver and sslserver can be bound on individual IP addresses and ports.

The port can be given by it's name found in the file /etc/services (e.g. 'submission') or simply by number (eg. 6209 for QMTPS).

For the IP address three choices exist:

  1. IPv4 address (only): Together with the option '-4 for tcpserver/ sslserver an individual IPv4 address is provided. This allows to use different cdb's to be used.
  2. IPv6 address (only): Now with the option '-6 (which is optional) for tcpserver/ sslserver an individual IPv6 address is used. Again, this allows to use different cdb's to be used.
  3. All inclusive: If, however, the IP address is referenced as '0', tcpserver and sslserver bind to all available IP addresses, including loopback and link-local addresses which are available during start of the Unix service.

I strongly recommend to use specific bindings to IP addresses. Otherwise, in addition the loopback addresses '127.0.0.1', '::1', and the link local adresses 'fe80::...' are used. Unter OpenBSD, in presence of IPv6 addresses, IPv4 addresses will be omitted otherwise.

3.3.2 Dropping privileges

Both tcpserver and sslserver are able to drop privileges once invoked. Requesting a 'low' port on a Unix system initially requires to run as root; however - after forking - this user and group of the running process can be changed to the required effective one.

Here is a sample, how sslserver does this, given the fact it reads critical authentication information prior of calling the respective service:

Figure: sslserver running under supervise (among others) and with effective userids displayed using pstree.

3.4 Service logging

Any Unix service fed by 'unsolicited messages' from the Internet needs to be monitored and the result of (critical) operation needs to be logged.

supervise uses the concept of a 'co-process' to provide the logging not only automatically by means of multilog but in addition is able to do the housekeeping for the logfiles.

The use of splogger is an old-fashioned by to feed the log-results to the Unix system standard log-daemon, typically Syslog. However with multilog, s/qmail is able to analyse the log information and to feed the results for graphical display to MRTG by means of qmail-mrtg.

A generic run script for all services is included:

#!/bin/sh LOG_NAME=`basename ${PWD%/log}` LOG_DIR="/var/log/${LOG_NAME}" LOG_SIZE=2000000 # bytes if [ ! -d "${LOG_DIR}" ]; then mkdir -p "${LOG_DIR}" chown qmaill:nofiles "${LOG_DIR}" echo "Creating log dir for ${LOG_NAME}:" ls -ld "${LOG_DIR}" fi exec 2>&1 exec setuidgid qmaill multilog t s${LOG_SIZE} "${LOG_DIR}"

This script 'detects' the 'service' it is invoked for and automatically raises upon it's first call the required log directory names as 'service' and typically located under /var/log/.

Here, the log files ('current') are created as user qmaill and rotated again automatically if approaching ${LOG_SIZE}. This minimalistic version can be extended to filter particular log messages and to process those on demand.

3.5 qmail-smtpd

qmail-smtpd is the work-horse with s/qmail. Apart from providing transport functionality, qmail-smtpd does a lot in order to validate the incoming SMTP email:

These tasks are done during the transmission of the email in real-time while in addition enforcing the correct protocol sequence during reception.

3.5.1 SMTP environment variables

qmail-smtpd is able to use envrionment variables in two different ways:

Note: The environment variables may be static over the livetime of the process, or dynamically set; thus depend on the current SMTP connection, for instances IP address and port.

Environment variables read:

The following environment variables are processed:

The particular settings are explained in the next sections.

Further, the following environment variables are provided:

3.5.2 qmail-smtpd run scripts

Typically, qmail-smtpd is set up in thee instances:

  1. qmail-smtpd providing 'standard' ESMTP services on port 25 including SMTP authentication and STARTTLS. Port 25 is dedicated to an unsolicited, unqualified email service (according to RFC 5321).
  2. qmail-smtpd used for email Submission services on port 587 demanding SMTPS authentication usually based on STARTTLS (see RFC 6409).
  3. qmail-smtpd ist set up for ESMTPS service on port 465, thus requiring TLS encryption before the ESMTPS session is started. Though IANA has 'detached' that port from ESMTPS, it is still widely spread.

Note: The ESMTP service on port 25 is a public service once a corresponding MX DNS record is published, while the other onces act as client-only services.

3.5.2.1 qmail-smtpd on Port 25

Running qmail-smtpd on port 25 opens up the ESMTP email for the entire world and requires to set up an DNS MX record in addition for your domain or the respective host.

Since this service is a potential target for DDoS, spam, and virus attacks, caution is required to setup to that service. In addition to ESMTP specific filters, I recommend to restrict the Unix systems resources by means of Daemontool's softlimit within the run script.

A typical, unrestricted setting with STARTTLS but without Auth support is shown in this (default) run script:

#!/bin/sh QMAILU=`id -u qmaild` QMAILG=`id -g qmaild` HOSTNAME=`hostname` export UCSPITLS="" . /var/qmail/ssl/ssl.env exec env PATH="/var/qmail/bin:$PATH" \ sslserver -seVn -Rp -l $HOSTNAME \ -Xx /var/qmail/control/rules.smtpd.cdb \ -u $QMAILU -g $QMAILG 0 smtp \ qmail-smtpd 2>&1

The following notes shall be checked carefully:

  1. The STARTTLS settings for sslserver are provided via environment variables defined in the file /var/qmail/ssl/ssl.env.
  2. SMTP connection control is facilitated by the cdb /var/qmail/control/rules.smtpd.cdb. It requires the package UCSPI-TCP6 to generate the cdb.
  3. qmail-smtpd binds to all ports on all interfaces by means of the '0' given in the argument. This is not, what you typically want. Instead, you should setup different qmail-smtpd instances sharing the same queue but with different settings per IP address (binding). Use /var/qmail/bin/ipmeprint to check all your available IP addresses.

Running qmail-smtpd on port 25 probably requires additional anti-spam and anti-virus checks.

3.5.2.2 qmail-smtpd with Submission on Port 587

In order to allow relaying your you email users by means of qmail-smtpd on port 587 (the Submission port) was actually defined as work-around in order to prevent none-authorized relaying.

As a consequence, it is required to provide SMTP Authentication on this qmail-smtpd instance (perhaps together with STARTTLS support) and all other EMSTP sessions must be rejected .

qmail-smtpd provides a simple hook to demand SMTP Authentication within the run script but requires the presence of a authentication PAM:

#!/bin/sh QMAILU=`id -u qmaild` QMAILG=`id -g qmaild` HOSTNAME=`hostname` export SMTPAUTH="!+cram" . /var/qmail/ssl/ssl.env exec env PATH="/var/qmail/bin:$PATH" \ sslserver -seVn -Rp -l $HOSTNAME \ -Xx /var/qmail/control/rules.sub.cdb \ -u $QMAILU -g $QMAILG 0 submission \ qmail-smtpd qmail-authuser true 2>&1

Please consider:

  1. SMTP Authentication of type PLAIN and LOGIN can be easily eavesdropped on un-encrypted connections.
  2. STARTTLS can be enforced using UCSPITLS="!".
  3. CRAM-MD5 Authentication handles safe password exchange in any case. Enforcing CRAM-MD5 can be achieved with SMTPAUTH="!cram". Here, you need a CRAM-MD5 enabled PAM, i.e. qmail-authuser .
  4. UCSPI-SSL's connection cdb (/var/qmail/control/rules.sub.cdb is different from the standard one and probably less restrictive.
3.5.2.3 qmail-smtpd with on Port 465 (SMTPS)

Thus the SMTPS port 456 has been 'removed' by IANA, it is still wide spread supported by most MDAs (Android, iOS, Blackberry ...) and is from my point the best choice to protect the user's privacy. qmail-smtpd can easily set up to use 465 (SMTPS) together with authentication.

Binding qmail-smtpd to port 465 will automatically encrypt the entire conversation by means of TLS without compromise:

#!/bin/sh QMAILU=`id -u qmaild` QMAILG=`id -g qmaild` HOSTNAME=`hostname` export SMTPAUTH="+cram" . /var/qmail/ssl/ssl.env exec env PATH="/var/qmail/bin:$PATH" \ sslserver -seV -Rp -l $HOSTNAME \ -Xx /var/qmail/control/rules.smtpsd.cdb \ -u $QMAILU -g $QMAILG 0 smtps \ qmail-smtpd qmail-authuser true 2>&1

Here, it is import to omit

3.5.3 Qualification for the SMTP email recipient (domains)

There are three typical s/qmail configurations:

  1. One tier: s/qmail may to used to receive emails for (a set of) local domains and delivering it mainly on the local system.
  2. Two tier: s/qmail receives mails from the Internet, qualifies the recipient domain, filters the mails and forwards them to other (delivering) mails servers.
  3. Zero tier: s/qmail is used as a gateway only, with little or no qualification and validation of the incoming mails to be forwarded.

The 'zero tier' approach is usually called 'gatewaying'; however due to the abuse of emails, qualification of the recipient and checks on the emails (and their potentially malicious content) are pretty normal these days.

While message filtering for spam and viruses is discussed in the forthcoming chapters and the particular Recipientverification is discussed in chapter 4, here domain qualification is discussed.

3.5.3.1 Accepting emails on behalf of the 'Rcpt to:' domain information

The general logic in qmail-smtpd can be depict from here:

Figure: qmail-smtpd's 'Rcpt to:' logic (IdP: Identity Provider; see chapter 5).

Caution: In case the control files control/rcpthosts or control/recipients are not properly populated, qmail-smtpd acts as an Open Relay!

A typical control/rcpthosts can be setup to looks like this:

example.com .example.com myhost.mydomain.net

Thus qmail-smtpd receives mails targeting the domain example.com but in addition the leading 'dot' tells to accept emails for any host in here, i.e. send to root@host.example.com.

In case very many hosts need to be included in control/rcpthosts it is more efficient to put those into control/morercpthosts and call qmail-newmrh to generate a cdb from this information for quick look-up.

3.5.3.2 Mapping local IP addresses to a domain name

SMTP allows to use IP adresses in the Rcpt to: command, in case the IP address is enclosed in brackets:

By means of control/localiphosts these IP addresses may be mapped to the name of the s/qmail instance given by control/me. This translation is done before control/rcpthosts is evaluated.

3.5.4 SMTP envelope filters

Any E-Mail address, lets say <user@host.domain.com> consists of a

local part: user (left from the "@") and a
host part: host.domain.com (right hand side from the "@").

qmail-smtpd converts hostnames and domainnames taken from the tcpserver/ sslserver environment to lowercase qmail-smtpd reads the SMTP envelope address inside the recommended SMTP envelope brackets "<" and ">". Double-quotes in SMTP addresses "forwarding path" are stripped.

E-Mail addresses for local accounts are considered case-insensitive and delivered irrespective of their case.
Lets say - if the local account is "admin" and the RCPT to: tells <AdMin> or <adMIN> the delivery will be successful.

3.5.4.1 Filtering HELO/EHLO Greetings (badhelo)

s/mail records the HELO/EHLO greeting string for every received message in the E-Mail "Received:" header in case the provided HELO/EHLO string is different from the connecting host's FQDN:

Received: from foo.bar.de (HELO foo) (192.168.192.11) by heaven.bar.de with SMTP; 25 Apr 2003 15:01:42 -0000

The HELO/EHLO string is included as "(HELO foo)". The HELO/EHLO string is usually generated by the sending MTA without much control (MUAs often use their generic hostname).

qmail-smtpd allows a flexible filtering of the clients HELO/EHLO greeting string, which depends on the setting of the environment variable HELOCHECK:

HELOCHECK Meaning
"" evaluate control/badhelo
"." reject session, if no HELO/EHLO greeting is provided/empty and evaluate control/badhelo
"=" require that the HELO/EHLO greeting corresponds to the FQDN (= TCPREMOTEHOST) of the host
"A" DNS A lookup for the HELO/EHLO greeting and evaluate control/badhelo
"M" DNS MX lookup for the HELO/EHLO greeting and evaluate control/badhelo

The HELOCHECKs are only done, in case RELAYCLIENT is not set (split-horizon fashion). A useful setting is HELOCHECK="." and with the following input in control/badhelo

myIPAddress
myFQDN
localhost
localhost.localdomain

These settings exclude the spoofing of the MTA's own address, which is typical for spam senders, since they determine the EHLO/EHLO greeting from the initial IP/SMTP session parameter.

3.5.4.2 Filtering Mail From: SMTP Addresses (badmailfrom)

qmail-smtpd allows four types of checks against the provided "Mail From:" SMTP envelope address (which I often call the "Originator"):

DNS MX Checks of the Envelope Sender

Invoking the environment variable MFDNSCHECK in the qmail-smtpd startup script enables globally the DNS check for the envelope's Sender.

Example:

#!/bin/sh
export MFDNSCHECK="" .....

Additionally, the environment variable may be defined individually within a cdb of tcpserver/sslserver. Typically, a tcprules generated cdb:

127.0.01:allow,RELAYCLIENT="" 10.1.0..0/18:allow,RELAYCLIENT="" fe80/10:allow,RELAYCLIENT="" :allow,MFDNSCHECK=""

If the environment variable MFDNSCHECK is not set, qmail-smtpd does not perform this DNS MX check.

Standard badmailfrom Checks

control/badmailfrom was the only SMTP envelope filter Dan Bernstein originally implemented for qmail-smtpd. Here, only particular names or perhaps domains were listeted to be rejected in the SMTP dialogue. Since then, various flavours of badmailfrom have been brought out. However, the approach to reduce spam emails feeding control/badmailfrom with known spammer addresses is comparable trying to hit a moving target. Almost all Originator addresses spammer use today are fake and in this sense are meaningless.

badmailfromunknown Checks

There exist a special case, where you expect an email with a specific Originator address to be send via particular MTAs. For instance, if you see an email with Originator address "support@microsoft.com", it has to be send from a Microsoft MTA. qmail-smtpd has the knowledge of the sender's IP and FQDN (by means of the environment variables TCPREMOTEIP and TCPREMOTEHOST) in case you use tcpserver, or sslserver with the appropriate argument, i.e. tcpserver -h.

MTAs for which the FQDN can't be resolved are unqualified. In particular, emails from the large webmail providers (aol, hotmail, yahoo, gmx, t-online ...) have always to be send from qualified MTAs. Reversely, you can safely reject emails with those Originator hostparts, which can not be resolved tcpserver/ sslserver records them as "unkonwn".

In the current badmailfrom implementation, you simply include the Originator addresses for which you enforce a qualified TCPREMOTEINFO into control/badmailfrom in the following way appending a dash ("-"):

@aol.com- @hotmail.com- @yahoo.com- @gmx.de-

Note 1: Since tcpserver/ sslserver relies on a qualified DNS lookup.
Note 2: Wildmat support is not provided; thus an entry "@*.yahoo.com-" won't work.

badmailfromwellknown Checks

In particular for webmailer (ie. hotmail.com, yahoo.com) the domain-part of the provide Mail From: address coincides with the provided domain name in TCPREMOTEHOST. Enforcing coincidence can be achieved for addresses appended with an equal-sign ("=") in control/badmailfrom:

@t-online.de=

Receiving a Mail From: address like "max.mustermann@t-online.de" will only be accepted if TCPREMOTEHOST ends with "t-online.de", for instance "mailout03.t-online.de". Otherwise, the email will be rejected by badmailfrom.

badmailfrommismatcheddomains

Reversely to badmainfromwellknown now the MTA and it's FQDN is considered in the first place.
Thus, if you receive emails from mx1.yahoo.com you may require that the provided Mail from: address matches yahoo.com.

In order to enforce this, within control/badmailfrom you define extended (domain) addresses with a leading similar-sign ("~"):

~yahoo.com

Caution: It should be noted, that this filter is not in accordance with RFC 2821, since it couples the SMTP envelope with the domain of the sender. For example, yahoo uses DKIM records to label allowed envelope addresses for their domain. Further, this entry does not affect the 'Mail From:' address in the first place, but rather the value of TCPREMOTEHOST.

badmailfrom Anti-Spoofing

Another special case is given, rejecting none-Relayclient emails with Originator addreses spoofing your domain name or email addresses. Email can be rejected if the "responsible domains" are included with a trailing plus ("+") in the following way into control/badmailfrom:

god@mydomain1.com+ @mydomain2.net+ @mydomain3.org+
badmailfrom Test by-passing

Under some conditions, it might by necessary to by-pass all reqular badmailfrom checks and in addition the MFDNSCHECK. For this purpose, individual email addresses included in badmailfrom and enhanced with a leading question mark ("?") can be defined. While recognizing this address, qmail-smtpd will skip all further tests:

?nobody@example.com

Note: The enhanced addresses don't allow wildcarding.

3.5.4.3 Filtering particular 'Rcpt To' addresses (badrcptto)

SMTP Recipient addresses (Rcpt To: <Recipient>) can be unconditionally accepted or rejected by means of control/badrcptto by qmail-smtpd:

Note: The provided Rcpt To: <Recipient> information by the SMTP client is (apart from it's IP/FQDN) the only information which can not be faked, though these addresses are today often randomly generated by means of lexical/dictionary attacks by spammers or gathered by address harvesting.

By populating control/badrcptto emails to Recipients listed there in already rejected in the SMTP session. Wildcards are allowed. If you don't wont to receive emails for root (from the Internet) include in control/badrcptto:

root@*

Alternatively to the Recipients mechanism, as a side-effect of the wildmat filtering, you can use the control/badrcptto file as an effective whitelisting mechanism. The trick is, to initially reject everything while later to allow specific Recipients:

* !*@otherdomain.com !user1@mydomain.com !user2@mydomain.com

Note: The evaluation of control/badrcptto is done independent from the setting of the RELAYCLIENT environment variable.

3.5.4.4 Controlling the behaviour for 'Rcpt To' addresses

In one (ESMTP) session, multiple 'Rcpt to:'s can be used to send the (identical) message to several recipients. qmail-smtpd allows

In the latter case, tarpitting will start, after TARPITCOUNT 'Rcpt to:'s have been seen and each further command is delayed by TARPITDELAY seconds. If however, the Recipient mechanism is in place, this behaviour can be used to trigger the rejection, in case to many invalid 'Rcpt to:' have been encountered: Setting TARPITDELAY="999" and TARPITCOUNT=n, after receiving n invalid recipients will disrupt the entire ESMTP session and potentially the DATA command will not be accepted, thus no messages are accepted.

3.6 qmail-qmtpd

The 'Quick Mail Queueing Protocol' QMQP is an invention of D.J. Bernstein and enhanced to support TLS connections as well in order to provide privacy for any connection.

While qmail-remote acts as a QMTP client, qmail-qmtpd can advice to work in two different ways:

Note: QMTP is a proprietary protocol which can be used in a closed environment and does not provide the same level of control as ESMTP does.

3.6.1 QMTP environment variables

Since qmail-qmtpd is TLS-enabled, it respects and uses the MOD_SSL environment variables identically to qmail-smtpd. The same holds for the connection variables als described in tcp-environ.

Particular environment variables used by qmail-qmtpd are the following:

3.6.2 qmail-qmtpd run scripts

3.6.2.1 qmail-qmtpd togther with tcpserver von Port 209

The following minimum qmail-qmtpd run-script is sufficient for an un-encrypted QMTP setup:

#!/bin/sh QMAILU=`id -u qmaild` QMAILG=`id -g qmaild` HOSTNAME=`hostname` exec env PATH="/var/qmail/bin:$PATH" \ tcpserver -Rp -l $HOSTNAME \ -Xx /var/qmail/control/rules.qmtpd.cdb \ -u $QMAILU -g $QMAILG 0 qmtp \ qmail-qmtpd 2>&1

It should be noted, that the port assignment qmtp is taken from the definition given in /etc/services. The log information provided originates only from tcpserver. With this minimum configuration, the only control for a connection setup is provided by tcpserver only; i.e. RELAYCLIENT.

I recommend ot bind qmail-qmtpd not to all available IP address ('0') rather to use one dedicated. In an IPv6 environment ULA and LLU can be used. In both cases the privacy extension to automatically generate temporary IPv6 addresses need to be disabled.

3.6.2.2 qmail-qmtpd together with sslserver von Port 6209

s/qmail's QMTP implementation allows to use mandatory TLS for connection-encryption:

#!/bin/sh QMAILU=`id -u qmaild` QMAILG=`id -g qmaild` HOSTNAME=`hostname` . /var/qmail/ssl/ssl.env exec env PATH="/var/qmail/bin:$PATH" \ sslserver -seVn -Rp -l $HOSTNAME \ -Xx /var/qmail/control/rules.qmtpsd.cdb \ -u $QMAILU -g $QMAILG 0 6209 \ qmail-smtpd 2>&1

Unlike the ESMTP case, there is no 'STARTTLS' support, thus QMTPS can be compared with SMTPS. From qmail-smtpd qmail-qmtpd inherits the possibility to understand X.509 client certificates, thus now RELAYCLIENT may depend on the presence of a valid client certificate. In a distributed QMQ environment, the sending and receiving instances are mutually authenticated and authorized.

For further discussion on how to use X.509 client certificates, see chapter 5.

3.6.3 qmail-qmtpd control files

The minimalistic design of the QMTP protocol lets qmail-qmtpd make use only of three control files:

  1. control/rcpthosts
  2. control/morercpthosts.cdb
  3. control/databytes

The meaning and usage of those control files is identical to those for qmail-smtpd; in fact they are the same!

3.7 qmail-qmqpd

Unlike qmail-qmtpd which is 'fed' by qmail-remote, qmail-qmqpd is supplied by qmail-qmqpc which itself is as replacement for qmail-queue; usually a symbolic link.

Thus, qmail-qmqpd serves as 'remote queue' daemon only. Here, no security mechanism are in place: Either the transmissions happens solely in a protected environment or other mechanisms need to take place, i.e. IPSec shall be used to guarantee confidentiality.

3.7.1 QMQP environment variables

qmail-qmqpd does not depend and does not use any specific environment variables.

3.7.2 qmail-qmqpd run scripts

Since qmail-qmqpd provides an un-encrypted service only the following run-script is sufficient to bind to port 628:

#!/bin/sh QMAILU=`id -u qmaild` QMAILG=`id -g qmaild` HOSTNAME=`hostname` exec env PATH="/var/qmail/bin:$PATH" \ tcpserver -Rp -l $HOSTNAME \ -Xx /var/qmail/control/rules.qmqpd.cdb \ -u $QMAILU -g $QMAILG 0 628 \ qmail-qmqpd 2>&1

In order to control and restrict the connecting hosts (clients) qmail-qmqpd depends on tcpserver 's cdb providing accept and deny rules per IP or domain.

3.8 qmail-pop3d

POP3 - the Post Office Protocol (Version 3) - is the third protocol s/qmail support. In order to provide IMAP4 support, I recommend to use Timo Sirainen's Dovecot or Andreas Aardal Hanssen's Binc.

POP3 is an always authenticating protocol. This not only the daemon qmail-pop3d but in addition an authentication service is required: qmail-popup which depends on an additional PAM to query an IdP (Identity Provider).

3.8.1 POP3 environment variables

Since it is required to always use qmail-pop3d in conjunction with qmail-popup, the following environment variables can be used:

3.8.2 qmail-pop3d run scripts

The POP3 service an be used unencrypted or (always recommended) by means of STLS support, setting up the TLS context after the plain connection on port 110 has been established. This behavior can achieved with the following run script.

#!/bin/sh HOSTNAME=`hostname` export UCSPITLS="" export POP3AUTH="+apop" . /var/qmail/ssl/ssl.env exec env PATH="/var/qmail/bin:$PATH" \ sslserver -seV -Rp -l $HOSTNAME 0 pop3 \ qmail-popup $HOSTNAME qmail-authuser true \ qmail-pop3d Maildir 2>&1 5>&1

However, using port 995 for POP3S services, the daemon makes use of the following script (mich may be used parallel to the one above):

#!/bin/sh HOSTNAME=`hostname` . /var/qmail/ssl/ssl.env exec env PATH="/var/qmail/bin:$PATH" \ sslserver -seV -Rp -l $HOSTNAME 0 pop3s \ qmail-popup $HOSTNAME qmail-authuser true \ qmail-pop3d Maildir 2>&1 5>&1

In both cases, qmail-authuser is the PAM which fetches the identity information either from the /etc/passwd file as local IdP or others.

3.8.3 qmail-pop3d POP3 Toaster

If the virtual user mechanism like Vpopmail or VMailMgr is in place (POP3 Toaster), instead of qmail-authuser their own respective PAMs have to be used:

Only in case if qmail-authuser is used as a substitute for the checkpassword PAM, the respective environment is correctly set for POP3 authentication.

3.8.4 qmail-popup logging

The run scripts above show the redirection of file descriptor '5' to '1'. For qmail-popup the username for authentication can be redirected to the standard logs, sslserver provides and made visible together with some other information, as explained in chapter 12.

3.8.5 qmail-pop3d and the cdb

Since qmail-pop3d provides authenticated service only (by means of qmail-popup), strictly, no cdb is required. However, it provides the same level of control as ist does for the other services. Thus, in order to get rid of some notorious abusers, I recommend to provide a cdb in the run script just in case.

3.9 qmail-send (aka qmail-start)

While the daemons qmail-smtpd and qmail-qmtpd allow to insert messages into the queue, it is the task of qmail-send to actually process those files for remote and local delivery:

3.9.1 qmail-send environment variables

qmail-start is invoked in setup the qmail-send environment entirely. Thus, no additional environment variables are accepted.

3.9.2 qmail-send run scripts

The invokation of the qmail-start run script is pretty straightforward and only depends on the defaultdelivery:

#!/bin/sh exec env - PATH="/var/qmail/bin:$PATH" \ qmail-start ./Maildir/ #qmail-start '|preline -f /usr/local/libexec/dovecot/dovecot-lda'

This run script by default uses the standard ./Maildir/ delivery, but the commented line shows how to setup (in my case) Dovecot's local delivery agent dovecot-lda to be fed by preline with some additional information.

The defaultdelivery for qmail-start can be provided easily in s/qmail/'s conf-defaultdelivery file prior of installation.

3.9.3 qmail-send control files

qmail-send uses a rich set of control files for the following different purposes:

Usage File Default Meaning
Queue queuelifetime 604800 time in the queue for message before bouncing
Bounce doublebouncehost me FQDN of the double bounce host
doublebounceto postmaster recipient of the double bounces (to inspect)
bouncemaxbytes 0 maximum size of bounces
Delivery concurrencylocal 10 simultaneous local delivery
concurrencyremote 20 simultaneous remote delivery
Recognition me (FQDN) name of s/qmail instance
envnoathost me prepended name for emails without domain qualifier
locals me list of domains recognized for local delivery
percenthack list of domains where the percent hack schould be applied for
virtualdomains list of domains to be treated as locals but with prepended (virtual) user name

Note: In order to make changes in those control files effective, qmail-send needs to be restarted. The current settings of those control files can be checked via qmail-showctl.

If qmail-send receives an ALRM signal, it will immediately retry sending all pending messages in the queue.

3.9.10 s/qmail and systemd

All s/qmail services run smoothly under systemd.

You have two choices:

  1. Integrating s/qmail daemons directly into systemd.
  2. Using the provided run scripts coming with s/qmail to be called by systemd.

s/qmail services require typically environment variables which are not easy to facilitate with systemd and in particular the full path has to be provided upon call.

Generic setup of qmail-send:

#/etc/systemd/system/qmail-send.service [Unit] Description=qmail delivery daemon After=syslog.target After=local-fs.target network.target ConditionFileIsExecutable=/var/qmail/bin/qmail-start [Install] WantedBy=multi-user.target [Service] Type=simple Restart=always StandardOutput=syslog StandardError=inherit SyslogFacility=mail SyslogIdentifier=qmail-send Environment=PATH=/var/qmail/bin:/usr/local/bin ExecStart=/var/qmail/bin/qmail-start Maildir/

Using run scripts:

#!/bin/sh QMAILU=`/usr/bin/id -u qmaild` QMAILG=`/usr/bin/id -g qmaild` HOSTNAME=`hostname` export UCSPITLS="" export SPF="1" . /var/qmail/ssl/ssl.env exec /usr/bin/env PATH="/var/qmail/bin:$PATH" \ /usr/local/bin/sslserver -seVn -Rp -l $HOSTNAME \ -Xx /var/qmail/control/rules.smtpd.cdb \ -u $QMAILU -g $QMAILG 0 smtp \ qmail-smtpd 2>&1

As can be seen, generic shell commands like export do work, while the PATH for applications is missing; thus has to be provided explicitly.

In the last case, the run is located under /service/qmail-smtpd which is the default location, the s/qmail's setup, following the package/install, the package/service call respectively.

This run script is now used within systemd's services called /etc/systemd/system/qmail-smtpd.service:

#/etc/systemd/system/qmail-smtpd.service [Unit] Description=qmail delivery daemon After=syslog.target After=local-fs.target network.target ConditionFileIsExecutable=/var/qmail/bin/qmail-smtpd #ConditionFileIsExecutable=/var/qmail/bin/qmail-authuser [Install] WantedBy=multi-user.target [Service] Type=simple Restart=always StandardOutput=syslog StandardError=inherit SyslogFacility=mail SyslogIdentifier=qmail-smtpd Environment=PATH=/var/qmail/bin:/usr/local/bin:/bin:/usr/sbin:/sbin ExecStart=/service/qmail-smtpd/run #ExecReload=/var/qmail/bin/qmail-tcpok ; /bin/kill -ALRM ${MAINPID}

Enabling s/qmail's services under systemd:

Upon setup, a systemd service can enabled:

  1. temporary, simply calling systemd start qmail-smtpd (as an example), or
  2. while booting, generating symlinks in the under /etc/systemd/system/multi-user.target.wants

A temporary enabled service looks like the following:

Figure: qmail-smtpd running under systemd.

In order to persistently enable qmail-smtpd, the following step is required:

Figure: qmail-smtpd enabled at startup from systemd.

Using systemctl status service, the state of the daemaons are displayed:

Figure: qmail-smtpd and qmail-smtpd stared from from systemd. Here, qmail-smtpd has not been enabled persistently, thus is labelled as 'disabled'.

Given s/qmail's services are under control of systemd you can use all of it's generic diagnose and start/stop features. In particular:

Further reading: