549 lines
20 KiB
Plaintext
549 lines
20 KiB
Plaintext
1 - Postfix LMTP support
|
|
========================
|
|
|
|
LMTP stands for Local Mail Transfer Protocol, and is detailed in
|
|
RFC2033. Postfix uses this protocol to communicate with the final
|
|
delivery agent, which may run on the local host or a remote host.
|
|
|
|
This protocol opens up interesting possibilities: one Postfix front
|
|
end machine can drive multiple mailbox back end machines over LMTP.
|
|
As the mail load increases, you add more Postfix front end systems
|
|
and more LMTP mailbox back end systems. This is the model that
|
|
Wietse had in mind when he began drafting the design for Postfix
|
|
- a scalable architecture that allows you to keep adding SMTP
|
|
servers and mailbox servers painlessly.
|
|
|
|
Such a distributed architecture needs glue to keep things together.
|
|
You can use a networked database (LDAP or mysql) to share the user
|
|
database among the front end and back end systems. Use a replicated
|
|
database so that no machine becomes a single point of failure for
|
|
the entire mail infrastructure. Or you can use rsync when files
|
|
are small and/or when information does not change often.
|
|
|
|
Postfix LMTP support is based on a modified version of the Postfix
|
|
SMTP client. The initial version was by Philip A. Prindeville of
|
|
Mirapoint, Inc., USA. This code was modified further by Amos Gouaux
|
|
of University of Texas at Dallas, Richardson, USA, who also revised
|
|
much of the documentation. Wietse Venema reduced the code to its
|
|
present shape.
|
|
|
|
|
|
2 - Overview
|
|
============
|
|
|
|
Most of the examples in this document involve the CMU Cyrus IMAP/POP
|
|
server, available from:
|
|
|
|
http://asg.web.cmu.edu/cyrus/
|
|
|
|
While certainly not the only application that could make use of
|
|
LMTP, it tends to be the most discussed. These examples are based
|
|
on Cyrus 2.1.5. The 2.x branch of Cyrus places greater emphasis on
|
|
LMTP delivery than the previous releases. Those using older releases
|
|
of Cyrus can find a discussion in the appendix of this document.
|
|
|
|
There are a variety of ways LMTP delivery can be configured in
|
|
Postfix. The two basic flavors are delivery over UNIX-domain
|
|
sockets and delivery over TCP sockets.
|
|
|
|
o Connections from the Postfix LMTP client over UNIX-domain
|
|
sockets allow you to deliver to non-Postfix LMTP servers running
|
|
on the same machine.
|
|
|
|
o Connections from the Postfix LMTP client over TCP sockets allow
|
|
you to deliver to non-Postfix LMTP servers across a local
|
|
network.
|
|
|
|
Note: the above is not to be confused with the UNIX-domain sockets
|
|
that Postfix uses internally to speak its own protocols with the
|
|
Postfix LMTP client.
|
|
|
|
The precise syntax for UNIX-domain and TCP connection endpoints is
|
|
given in the lmtp(8) manual page. Examples are also given in the
|
|
text below.
|
|
|
|
Both socket flavors can be specified in either the Postfix main.cf
|
|
file (see section 5) or in a Postfix transport map (section 6).
|
|
What is the best approach for you depends upon the arrangement of
|
|
your servers.
|
|
|
|
|
|
3 - LMTP over UNIX-domain sockets
|
|
=================================
|
|
|
|
Use this to deliver mail from the Postfix LMTP client to an LMTP
|
|
server that is running on the same system.
|
|
|
|
A UNIX-domain socket is specified as the socket type ("unix") and
|
|
a name in the local file system:
|
|
|
|
unix:/path/name
|
|
|
|
The "/path/name" part should be the name of a socket created by
|
|
the LMTP server on the local machine. See the specific examples
|
|
later in this document.
|
|
|
|
NOTE:
|
|
|
|
If you run the Postfix LMTP client chrooted, the interpretation
|
|
of the /path/name is relative to the Postfix queue directory
|
|
(typically, /var/spool/postfix).
|
|
|
|
By default, the Postfix LMTP client does not run chrooted.
|
|
With LMTP delivery to the local machine there is no good reason
|
|
to run the Postfix LMTP client chrooted.
|
|
|
|
|
|
4 - LMTP over TCP sockets
|
|
=========================
|
|
|
|
Use this to deliver mail from the Postfix LMTP client to an LMTP
|
|
server that is running on the same system or on a different system.
|
|
|
|
A TCP destination is specified as the socket type ("inet"), the
|
|
destination hostname and the TCP port:
|
|
|
|
inet:hostname:port
|
|
|
|
The "inet:" part can be omitted, as it is the default socket type.
|
|
|
|
The destination port can be omitted as well. Currently the default
|
|
TCP port number for this type of connection is 24, but this can be
|
|
customized in the /etc/services file. Specific examples are
|
|
given later in this document.
|
|
|
|
NOTE:
|
|
|
|
With connections over TCP sockets, Cyrus 2.0.x LMTP server
|
|
implementations insisted on SASL-style authentication. This
|
|
meant that Postfix had to be built with SASL support (see
|
|
SASL_README). While newer Cyrus releases offer an option to
|
|
turn off this requirement, you must exercise great care in
|
|
both determining the approach used and the configuration of
|
|
your selection. It is imperative that you do not allow
|
|
unauthorized access to your LMTP server. The examples below
|
|
show both approaches.
|
|
|
|
Some Cyrus LMTP server implementations do not allow SASL-style
|
|
authentication via plaintext passwords over unencrypted
|
|
connections. This is not the case with 2.1.5. However, you
|
|
must realize that this could make your LMTP link vulnerable.
|
|
If your LMTP communications traverse exposed networks, you
|
|
should either use an encrypted connection or enable MD5 SASL
|
|
mechanisms.
|
|
|
|
|
|
5 - Configuring LMTP using main.cf configuration
|
|
================================================
|
|
|
|
This is the simplest LMTP configuration.
|
|
|
|
5.1 - Delivery mechanisms
|
|
-------------------------
|
|
|
|
Postfix main.cf supports three mechanisms to deliver mail to an
|
|
LMTP server. Each method can use UNIX-domain or TCP sockets as
|
|
described in a later section.
|
|
|
|
main.cf mechanism 1
|
|
-------------------
|
|
|
|
mailbox_transport = lmtp:unix:/path/name (UNIX-domain socket example)
|
|
mailbox_transport = lmtp:hostname:port (TCP socket example)
|
|
|
|
Mail that resolves as local (domain is listed in $mydestination)
|
|
is given to the Postfix local delivery agent. The Postfix local
|
|
delivery agent expands aliases and .forward files, and delegates
|
|
mailbox delivery to the Postfix LMTP client which then sends it to
|
|
the non-Postfix LMTP server.
|
|
|
|
main.cf mechanism 2
|
|
-------------------
|
|
|
|
local_transport = lmtp:unix:/path/name (UNIX-domain socket example)
|
|
local_transport = lmtp:hostname:port (TCP socket example)
|
|
|
|
Mail that resolves as local (domain is listed in $mydestination)
|
|
is directly given to the Postfix LMTP client which then sends it
|
|
to the non-Postfix LMTP server. The mail is not processed by the
|
|
Postfix local delivery agent; therefore aliases and .forward files
|
|
are not processed.
|
|
|
|
main.cf mechanism 3
|
|
-------------------
|
|
|
|
fallback_transport = lmtp:unix:/path/name (UNIX-domain socket example)
|
|
fallback_transport = lmtp:hostname:port (TCP socket example)
|
|
|
|
Mail that resolves as local (domain is listed in $mydestination)
|
|
is given to the Postfix local delivery agent. The Postfix local
|
|
delivery agent processes aliases and .forward files, and delivers
|
|
to /var[/spool]/mail/$user for users that have a UNIX account.
|
|
Mail for other local users is delegated to the Postfix LMTP client
|
|
which then sends it to the non-Postfix LMTP server.
|
|
|
|
5.2 - Examples
|
|
--------------
|
|
|
|
5.2.1 - LMTP over UNIX-domain sockets
|
|
-------------------------------------
|
|
|
|
To utilize UNIX-domain sockets for the communication between
|
|
Postfix and Cyrus, the corresponding configuration files should
|
|
look something like this:
|
|
|
|
/etc/cyrus.conf:
|
|
SERVICES {
|
|
...
|
|
lmtpunix cmd="lmtpd" listen="/var/imap/socket/lmtp" prefork=1
|
|
...
|
|
}
|
|
|
|
/etc/postfix/main.cf:
|
|
mailbox_transport = lmtp:unix:/var/imap/socket/lmtp
|
|
|
|
/etc/postfix/master.cf:
|
|
lmtp unix - - n - - lmtp
|
|
|
|
In this case, the Postfix local delivery agent expands aliases
|
|
and .forward files, and delegates mailbox delivery to the Cyrus
|
|
lmtpd server via the socket "/var/imap/socket/lmtp".
|
|
|
|
NOTE:
|
|
|
|
Make sure that both the user id that Cyrus runs under and the
|
|
Postfix user id can access the socket "/var/imap/socket/lmtp".
|
|
While this is implied by the example above, it is often
|
|
overlooked and so warrants emphasis.
|
|
|
|
5.2.2 - LMTP over TCP sockets (non-SASL)
|
|
----------------------------------------
|
|
|
|
For this example, suppose the following files are configured
|
|
thusly:
|
|
|
|
/etc/cyrus.conf:
|
|
SERVICES {
|
|
...
|
|
lmtp cmd="lmtpd -a" listen="127.0.0.1:lmtp" prefork=1
|
|
...
|
|
}
|
|
|
|
/etc/services:
|
|
lmtp 2003/tcp
|
|
|
|
/etc/postfix/main.cf:
|
|
mailbox_transport = lmtp:localhost
|
|
|
|
/etc/postfix/master.cf:
|
|
lmtp unix - - n - - lmtp
|
|
|
|
With the above settings, the Postfix local delivery agent expands
|
|
aliases and .forward files, and delegates mailbox delivery to the
|
|
Cyrus LMTP server. Postfix makes a connection to port 2003 on the
|
|
local host, subsequently transmitting the message to the lmtpd
|
|
server managed by the Cyrus master process. The port number has
|
|
been changed in /etc/services from 24 to 2003 as that is what the
|
|
Cyrus LMTP server is now using.
|
|
|
|
See the Cyrus lmtpd(8) man page to verify that the version you
|
|
have supports the "-a" option.
|
|
|
|
NOTE:
|
|
|
|
Consider this approach if and only if this particular host
|
|
does not allow direct user logins or user-controlled
|
|
processes. Otherwise, this LMTP server may be abused!
|
|
|
|
If the Cyrus lmtp service is to listen on a network other
|
|
than the local loop-back (127.0.0.1), be sure to install
|
|
Cyrus with tcp_wrappers support. Then use tcp_wrappers
|
|
to only allow access to the "lmtp" service from trusted
|
|
hosts. Otherwise, this LMTP server may be abused!
|
|
|
|
Section 10 contains an example using tcp_wrappers. For the
|
|
configuration above, replace "deliver" with "lmtp" in the
|
|
/etc/hosts.allow shown in that example.
|
|
|
|
5.2.3 - LMTP over TCP sockets (SASL)
|
|
------------------------------------
|
|
|
|
In the following example "cyhost.my.domain" is the name of the Cyrus
|
|
IMAP/POP server. It is important that you use this name consistently
|
|
in the Postfix configuration settings. The first approach uses the
|
|
PLAIN authentication mechanism (see the Cyrus SASL documentation.)
|
|
|
|
Suppose the Cyrus server has the following files configured thusly:
|
|
|
|
/etc/cyrus.conf:
|
|
SERVICES {
|
|
...
|
|
lmtp cmd="lmtpd" listen="cyhost.my.domain:lmtp" prefork=1
|
|
...
|
|
}
|
|
|
|
/etc/imapd.conf:
|
|
lmtp_admins: lmtpuser
|
|
|
|
/etc/services:
|
|
lmtp 2003/tcp
|
|
|
|
The Postfix host (may be same box) has the following configuration:
|
|
|
|
/etc/postfix/main.cf:
|
|
mailbox_transport = lmtp:cyhost.my.domain
|
|
lmtp_sasl_auth_enable = yes
|
|
lmtp_sasl_password_maps = hash:/etc/postfix/lmtp_sasl_pass
|
|
lmtp_sasl_security_options = noanonymous
|
|
|
|
/etc/postfix/lmtp_sasl_pass:
|
|
cyhost.my.domain lmtpuser:password
|
|
|
|
/etc/services:
|
|
lmtp 2003/tcp
|
|
|
|
/etc/postfix/master.cf:
|
|
lmtp unix - - n - - lmtp
|
|
|
|
Instead of "hash", use the map type of your choice. Some systems
|
|
use "dbm" instead. Use "postconf -m" to find out what map types
|
|
are supported.
|
|
|
|
If your version of Cyrus does not support "lmtp_admins" as a
|
|
setting in imapd.conf, use "admins" instead.
|
|
|
|
With the above settings, the Postfix local delivery agent expands
|
|
aliases and .forward files, and delegates mailbox delivery to the
|
|
Cyrus LMTP server. Postfix makes a connection to port 2003 on the
|
|
local host, subsequently transmitting the message to the lmtpd
|
|
server managed by the Cyrus master process. The port number has
|
|
been changed in /etc/services from 24 to 2003 as that is what the
|
|
Cyrus LMTP server is now using. The SASL configuration on the Cyrus
|
|
server will need to accept the user "lmtpuser" using the password
|
|
specified in /etc/postfix/lmtp_sasl_pass on the Postfix host.
|
|
|
|
If this LMTP conduit exists over an exposed network, you should
|
|
compile Postfix with MD5 (CRAM or DIGEST) password support. See
|
|
SASL_README for more details. Then configure Postfix as follows:
|
|
|
|
/etc/postfix/main.cf:
|
|
lmtp_sasl_security_options = noanonymous, noplaintext
|
|
|
|
On the Cyrus host you should also set:
|
|
|
|
/etc/imapd.conf:
|
|
lmtp_allowplaintext: no
|
|
|
|
You will need to make sure the "lmtpuser" is in the appropriate
|
|
SASL database. As an example, the following would add "lmtpuser"
|
|
to /etc/sasldb2:
|
|
|
|
saslpasswd2 -c -u cyhost.my.domain lmtpuser
|
|
|
|
If you encounter difficulties with "lmtpuser" not being permitted
|
|
to authenticate to the LMTP server, try the above command with the
|
|
un-qualified hostname:
|
|
|
|
saslpasswd2 -c -u cyhost lmtpuser
|
|
|
|
Also make sure the Cyrus user has read permission of the SASL
|
|
database, /etc/sasldb2 in the example above.
|
|
|
|
Incidentally, it is very likely that the Cyrus server and the
|
|
Postfix server will need to use the same SASL backend databases
|
|
(e.g., auxprop or saslauthd.) Currently it is not possible to
|
|
assign different SASL backends for different Cyrus services.
|
|
Only TLS (SSL) or STARTTLS can be used in conjunction with
|
|
saslauthd. Since none of these encryption methods are available
|
|
for LMTP, if you need to encrypt your LMTP connections, you will
|
|
very likely have to use auxprop throughout.
|
|
|
|
|
|
6 - Configuring LMTP using transport map configuration
|
|
======================================================
|
|
|
|
This approach is quite similar to specifying the LMTP service in
|
|
the Postfix main.cf configuration file. However, now we will use
|
|
a transport map to route mail to the appropriate LMTP server,
|
|
instead of depending on delegation by the Postfix local delivery
|
|
agent.
|
|
|
|
Why might this approach be useful? This could be handy if you wish
|
|
to route mail for multiple domains to their respective mail retrieval
|
|
(IMAP/POP) server. Example:
|
|
|
|
/etc/postfix/transport:
|
|
domain1.tld lmtp1:unix:/path/name
|
|
domain2.tld lmtp2:lmtp2host
|
|
|
|
/etc/postfix/master.cf:
|
|
lmtp1 unix - - n - - lmtp
|
|
lmtp2 unix - - n - - lmtp
|
|
|
|
/etc/postfix/main.cf:
|
|
transport_maps = hash:/etc/postfix/transport
|
|
|
|
For details of the Cyrus LMTP server configuration, see section 5.
|
|
|
|
Instead of "hash", use the map type of your choice. Some systems use
|
|
"dbm" instead. Use "postconf -m" to find out what map types are
|
|
supported.
|
|
|
|
|
|
7 - Performance considerations
|
|
==============================
|
|
|
|
Hopefully the preceding discussion has seemed pretty straight
|
|
forward. Now things get interesting. After reading the following
|
|
you will see that there are more factors to consider when setting
|
|
up LMTP services.
|
|
|
|
|
|
8 - Single instance message store
|
|
=================================
|
|
|
|
Presently this topic is more pertinent to sites running Cyrus, but
|
|
may be a factor with other applications as well.
|
|
|
|
Since 1.6.22, Cyrus has had the feature that if a message containing
|
|
multiple recipients is received via the LMTP protocol, and all
|
|
these recipients were on the same Cyrus partition, only one instance
|
|
of this message would be written to the file system. The other
|
|
recipients would then see a hard link of this single instance.
|
|
Depending on your user base, this can be considerable motivation
|
|
to using LMTP.
|
|
|
|
With the examples in section 5.2, we can increase the number of
|
|
recipients (to $mydestination) that can be handled at once:
|
|
|
|
/etc/postfix/main.cf:
|
|
local_destination_recipient_limit = 300
|
|
|
|
The 300 was arbitrarily chosen for this example. Be sure to pick a
|
|
number that is appropriate for the capabilities of your hardware.
|
|
The bigger the number, the more you can leverage the single instance
|
|
message store. However, if it is too big the LMTP server will need
|
|
too much time to deliver a message and Postfix will experience
|
|
timeout errors. Choose this value very carefully.
|
|
|
|
NOTE:
|
|
|
|
Not all local delivery agent transports can support a recipient
|
|
limit greater than 1. Be sure to check the man page of the
|
|
specific transport before attempting this with anything but the
|
|
Postfix LMTP client.
|
|
|
|
If we wish to apply this single instance message store technique
|
|
with the configuration example in section 6, the setting would be:
|
|
|
|
/etc/postfix/main.cf:
|
|
lmtp1_destination_recipient_limit = 300
|
|
lmtp2_destination_recipient_limit = 300
|
|
|
|
As previously mentioned, exercise tremendous care backed by
|
|
extensive analysis of your systems before setting the recipient
|
|
limit like this.
|
|
|
|
|
|
9 - Improving connection caching performance
|
|
============================================
|
|
|
|
After delivering a message via LMTP, Postfix will keep the connection
|
|
open for a while, so that it can be reused for a subsequent delivery.
|
|
This reduces overhead of LMTP servers that create one process per
|
|
connection.
|
|
|
|
For LMTP connection caching to work, the Postfix LMTP client should
|
|
not switch destination hosts. This is no problem when you run only
|
|
one LMTP server. However, if you run multiple LMTP servers, this
|
|
can be an issue.
|
|
|
|
You can prevent the LMTP client from switching between servers by
|
|
configuring a separate LMTP delivery transport for each LMTP server:
|
|
|
|
/etc/postfix/master.cf:
|
|
lmtp1 unix - - n - - lmtp
|
|
lmtp2 unix - - n - - lmtp
|
|
. . . . . . . .
|
|
|
|
Configure transport table entries such that the lmtp1 mail delivery
|
|
transport is used for all deliveries to the LMTP server #1, the
|
|
mail lmtp2 transport for the LMTP server #2, and so on.
|
|
|
|
/etc/postfix/transport:
|
|
foo.com lmtp1:lmtp1host
|
|
bar.com lmtp2:lmtp2host
|
|
|
|
|
|
10 - Appendix: Older Cyrus versions
|
|
===================================
|
|
|
|
First of all, if you are using a Cyrus 2.x version prior to 2.1.4,
|
|
you should really consider upgrading. There have been numerous bug
|
|
fixes and performance improvements since the early 2.0 releases.
|
|
|
|
Further back, 1.6.24 was the last pre-2.x production release.
|
|
(Actually, there was a 1.6.25-BETA, but it is uncertain whether this
|
|
will be released officially as CMU is now focusing support on the 2.x
|
|
branch.) The following discussion touches on how to configure the
|
|
Postfix LMTP facilities with Cyrus 1.6.24.
|
|
|
|
One of the significant differences between Cyrus 1.x and 2.x is the
|
|
inclusion of the "master" process in 2.x. This "master" process is
|
|
responsible for running the various components of Cyrus, such as
|
|
imapd, pop3d, and lmtpd. Prior to 2.x, these services were managed
|
|
by inetd, the Internet services daemon.
|
|
|
|
To utilize LMTP delivery with Cyrus 1.6.24, the first thing to do is
|
|
configure inetd. This involves the following file edits:
|
|
|
|
/etc/services:
|
|
lmtp 2003/tcp
|
|
|
|
/etc/inetd.conf:
|
|
lmtp stream tcp nowait cyrus /usr/sbin/tcpd /usr/cyrus/bin/deliver -e -l
|
|
|
|
/etc/hosts.allow:
|
|
deliver : localhost : ALLOW
|
|
deliver : ALL@ALL : DENY
|
|
|
|
The "/usr/sbin/tcpd" is from the tcp_wrappers package, which is
|
|
discussed in the example "LMTP over TCP sockets, using hosts.allow."
|
|
It is important that you wrap this LMTP port to protect it from
|
|
unauthorized access.
|
|
|
|
On some systems, tcpd is built into inetd, so you do not have to
|
|
specify tcpd in the inetd.conf file. Instead of tcpd/inetd, xinetd
|
|
can do a similar job of logging and access control.
|
|
|
|
Now comes the Postfix configuration. Basically, the Cyrus 2.x
|
|
discussions regarding LMTP delivery over TCP are also applicable to
|
|
Cyrus 1.x, with the exception of the /etc/cyrus.conf file. A
|
|
typical Postfix configuration might look like this:
|
|
|
|
/etc/postfix/master.cf:
|
|
lmtp unix - - n - - lmtp
|
|
|
|
/etc/postfix/main.cf:
|
|
mailbox_transport = lmtp
|
|
|
|
It is also possible to use the transport map to route mail to your
|
|
Cyrus 1.6.24 LMTP server:
|
|
|
|
/etc/postfix/transport:
|
|
domain1.tld lmtp1:lmtp1host
|
|
domain2.tld lmtp2:lmtp2host
|
|
|
|
/etc/postfix/master.cf:
|
|
lmtp1 unix - - n - - lmtp
|
|
lmtp2 unix - - n - - lmtp
|
|
|
|
/etc/postfix/main.cf:
|
|
transport_maps = hash:/etc/postfix/transport
|
|
|
|
If you have read the discussion covering the Cyrus 2.x installation,
|
|
you will notice the one significant difference with the Postfix
|
|
configuration is the lack of mention of the UNIX-domain sockets.
|
|
That is because delivery over UNIX-domain sockets is new with Cyrus
|
|
2.x, yet another reason to upgrade. :-)
|