第四章:虚拟域Postfix 表本地数据库查询数据库Postfix别名文件IP地址表外部文件Postfix CIDR表Postfix 访问表本地配送代理虚拟主机配置一个虚拟主机Postfix和虚拟主机Dovecot密码文件Dovecot用户数据库本地邮件传输协议(LMTP)Postfix虚拟交付代理测试你的虚拟邮箱标头中的LMTP
现在,您已经在两台机器之间建立了基本的SMTP,并且可以理解Postfix的投诉,让我们扩展您的配置,以接受域的真实邮件。我们将考虑Postfix如何管理表(tables)和列表(lists)。有了它,我们可以配置一个虚拟域并为其设置DNS记录。在第6章中,我们将把虚拟域移动到数据库中,以便于大规模管理。
管理虚拟电子邮件域需要通过Postfix表进行仔细的数据管理。
虽然您几乎可以在 main.cf 中完全配置Postfix,但将独立部分移动到单独的文件中可以提高可管理性。一个大型邮件系统可能有数千个帐户,或者允许数十个IP地址通过它进行中继,或者接收数百个域的邮件。在 main.cf 中包含所有这些细节会压倒其他配置选项。将这些设置移动到单独的文件中是有意义的。外部文件可以是 tables (表)或 lists (列表)。列表包含单个值,而表是某种键值数组。我将用“table”这个词来指代这两者。
表可以是文本文件或数据库。
在过去的四分之一个世纪里,Unix已经实现了许多不同的文件格式和数据源,Postfix几乎支持所有这些格式。许多格式适用于本地文件。Postfix包括 postmap(1)
来创建这些格式的文件。您还可以使用远程数据库,如MariaDB、LDAP或(如果您已经放弃)NIS。要查看您的安装支持哪些格式,请运行 postconf -m
。
xxxxxxxxxx
btree
cidr
environ
...
你经常会听到这些本地数据库被称为 hash files (哈希文件)。哈希文件最初是一种特定的格式,但几十年来,这个术语被灾难性地扭曲了,直到人们将其应用于几乎任何类型的本地数据库文件。有原始的Berkeley db文件、btree文件、DBM文件、SDBM文件等等。在喝酒时,人们可能会可信地辩称sqlite是由哈希文件支持的,但这时有人拔出爆能枪,整个酒吧都爆发了,你必须为这场混乱道歉。Postfix支持许多本地哈希文件格式,但您的安装可能不支持。Berkeley db文件或 hash files 几乎适用于所有用途。哈希文件通常具有 .db 扩展名,尽管文件扩展名是危险的,不能被信任。
大多数操作系统上的大多数软件包都支持几十种不同的类型。本书预计您的软件将支持MySQL
(MariaDB)和 proxy
格式以及哈希文件。
我们将使用别名文件作为示例。我们在第一章中讨论了 aliases 。别名是一种系统范围的消息转发,因此发送到主机上一个地址的电子邮件可以重定向到真实帐户。每当更新别名文件时,都必须运行 postalias
以重新生成数据库。这是一个经典的Unix功能,但Postfix扩展了这一概念,并将大多数表存储为本地数据库。
Postfix更喜欢数据库文件,因为它们可读性和预解析性很强。读取文本文件的速度非常慢,以至于Postfix仅在启动时读取和解析文件。对文本文件的更改意味着需要重新加载Postfix。数据库文件可以像数据库一样进行查询,因此可以在不干扰正在运行的守护进程的情况下进行更改。一切都需要数据库吗?不一定。我的主机只接受来自本地主机的邮件,而且永远不会改变,所以我不用费心使用数据库。我们的示例从文本文件开始,然后进入数据库。
Postfix数据库是键值存储。考虑别名文件中的示例行。
xxxxxxxxxx
root: mwl
键是 root
,值是 mwl
。发往 root
用户的邮件会被重定向至 mwl
用户。
选项 default_database_type
设置默认的本地数据库格式。用 postnf -d
检查该设置:
xxxxxxxxxx
$ postconf -d default_database_type
default_database_type = hash
此安装默认为Berkeley db文件。使用 postmap(1)
命令将文本文件转换为默认数据库类型。文件 bad-domains 包含一个我们不想接受邮件的网站列表,我们稍后会讨论。
xxxxxxxxxx
filthyewokwhowontshutup@gmail.com REJECT
@mwl.io REJECT
…
使用 postmap
将其转换为哈希文件:
xxxxxxxxxx
这将创建文件 bad-domains.db ,Postfix可以在不重新加载的情况下读取该文件。
使用 postmap
的 -q
选项查询数据库。给 -q
两个参数,你要检查的项目和表。虽然postfix有管理别名文件的特殊工具,但 postmap
可以执行基本的查找。在这里,我想知道别名数据库中 root
的值:
xxxxxxxxxx
mwl
要转储整个数据库,请使用 -s
选项:
xxxxxxxxxx
127.0.0.0/8 OK
[::1]/128 OK
…
您将看到 postmap
能够编辑数据库的引用。如果你想在数据库中添加或删除条目,你可以!问题是,这些操作只影响数据库文件,而不影响源文本文件。下次运行 postmap
将文本文件转换为数据库文件时,这些编辑将被覆盖。始终更新文本文件并将其转换为数据库文件。如果要在数据库中管理这些表,请使用第6章中讨论的真实数据库。
Postfix包括根据传统Unix实践管理别名文件的特定工具。
我们在第一章中谈到了别名文件的格式。使用 postconf -d
查看Postfix期望在哪里找到别名文件以及它将如何使用它。
xxxxxxxxxx
$ postconf -d | grep aliases
alias_database = hash:/etc/aliases
alias_maps = hash:/etc/aliases
newaliases_path = /usr/local/bin/newaliases
alias_database
选项显示别名文件的路径。这是传统的 /etc/aliases 。alias_maps
选项给出了本地数据库的格式和位置。当你更改这些文件的位置时,一些操作系统的行为会很奇怪。如果你想把别名文件放在 /etc/postfix 中,那么来自预期位置的链接或符号链接会有所帮助。
最后,newaliases_path
让您知道Postfix在哪里安装了 newaliases
。每次编辑文本别名文件时,运行Postfix的 newaliases
以更新相应的哈希文件。许多Unix工具都可以更新哈希文件,但最好使用Postfix的原生支持。如果 newaliases
给您带来了麻烦,请验证您的系统没有多个 newaliase
命令,或者您正在运行正确的命令。
postalias
命令还可以搜索别名数据库,就像 postmap(1)
一样。如果你想知道Postfix将在哪里为本地地址发送邮件,请使用 -q
选项并提供帐户。该系统具有 sshd(8)
的无特权帐户 sshd
。如果我向该帐户发送邮件,谁会收到?
xxxxxxxxxx
$ postalias -q sshd aliases
root
好吧,它去了某个地方。但我非常清楚,没有人会在这个系统上阅读电子邮件。希望它能发送给真正的用户?
xxxxxxxxxx
$ postalias -q root aliases
mwl@solveamurder.org
啊。我真的必须把这件事委托给有能力的人。
使用 -s
选项转储整个数据库:
xxxxxxxxxx
$ postalias -s aliases
root: mwl@mwl.io
postmaster: root
_dhcp: root
...
与 postmap
一样,您将看到对 postalias
的引用能够编辑数据库。与 postmap
一样,这些更改仅影响数据库文件,而不影响源文本文件。
在第3章中,我们使用 mynetworks_style
选项表示远程主机不能通过此主机自由中继。
xxxxxxxxxx
mynetworks_style = host
您经常会有其他主机需要通过您的系统中继消息。您的电子商务web服务器场必须向客户发送收据,但您可能不想在每台服务器上管理一个完整的邮件系统。配置这些服务器以通过MTA中继所有内容。配置您的邮件系统,使用 mynetworks
选项接受和转发来自这些地址的邮件。
当你有一个不太可能更改的IP地址短列表时,你可以直接将它们包含在 main.cf 中。在这里,我通过在配置文件中指定 localhost
IP地址列表,使用 mynetworks_style=host
进行复制。
xxxxxxxxxx
mynetworks = 127.0.0.0/8 [::1]/128
127.0.0.0/8
是IPv4本地主机地址块,而 ::1/128
是IPv6本地主机地址。IPv6地址必须出现在方括号中,前缀长度在括号外。您不知道客户端可能更喜欢哪种IP堆栈,因此请将两者都包括在内。所有IP地址必须采用 Classless Inter-Domain Routing (CIDR——无类域间路由)格式。不在列表中的任何内容都将被拒绝通过Postfix中继消息的权限。
假设您的电子商务服务器使用地址 198.51.100.128/26
和 2001:db8:bad:c0de::/64
。您希望您的邮件系统中继来自这些主机的邮件。将这些添加到 mynetworks
:
xxxxxxxxxx
mynetworks = 127.0.0.0/8 [::1]/128 198.51.100.128/26 [2001:db8:bad:c0de::]/64
重新加载Postfix并使用 postnf
检查您的工作:
xxxxxxxxxx
mynetworks = 127.0.0.0/8 [::1]/128 198.51.100.128/26 [2001:db8:bad:c0de::]/64
也许 198.51.100.136/29
的主机是用于测试的,不应该向外界发送邮件。您可以使用感叹号从列表中排除这些,同时仍然允许 198.51.100.128/26
的其余部分。列表从左向右读取,Postfix停止检查第一个匹配项,因此将排除项列在允许的地址之前:
xxxxxxxxxx
mynetworks = 127.0.0.0/8 [::1]/128 !198.51.100.136/29 198.51.100.128/26
[2001:db8:bad:c0de::]/64
对于配置文件条目来说,这变得非常长和复杂。我可以在单独的行中列出每个地址块,但这会使配置文件更长:
xxxxxxxxxx
mynetworks = 127.0.0.0/8
[::1]/128
!198.51.100.136/29
198.51.100.128/26
[2001:db8:bad:c0de::]/64
我们不断壮大的组织将增加额外的服务器。让我们把这份清单放到一个单独的文件里。
与其用一个长表把 main.cf 弄乱,我们可以告诉 main.cf 包含一个外部文件。此 main.cf 条目告诉Postfix检查文件 /etc/Postfix/reay-clients 以获取此选项的值。
xxxxxxxxxx
mynetworks = /etc/postfix/relay-clients
文件 relay-clients 包含允许的IP地址列表。您可以将它们全部放在一行中,但前提是您想降低文件的可读性。
xxxxxxxxxx
127.0.0.0/8
[::1]/128
!198.51.100.136/29
198.51.100.128/26
[2001:db8:bad:c0de::]/64
重新加载Postfix,它现在将从文件中读取表内容:
xxxxxxxxxx
mynetworks = /etc/postfix/relay-clients
Postfix程序仅在重新加载或启动时读取文本文件。如果您希望Postfix对外部文件中的更改做出动态反应,请使用哈希文件或数据库。
IP地址是一个非常常见的配置参数,Postfix对此有特定的支持。Postfix CIDR表仍然是一个文本文件,只有在重新加载或重新启动守护进程时才会重新读取。使用表类型、冒号和数据库文件的路径指定一个表:
xxxxxxxxxx
mynetworks = cidr:/etc/postfix/relay-clients.cidr
CIDR表每行包含一个网络块,并附有OK或REJECT语句。列表按顺序处理,并在第一个匹配时停止处理。不在列表中的地址将被拒绝。这是我们现有的这种格式的中继客户端列表:
xxxxxxxxxx
127.0.0.0/8 OK
[::1]/128 OK
198.51.100.136/29 REJECT
198.51.100.128/26 OK
[2001:db8:bad:c0de::]/64 OK
每当更改文本地址表时,都必须重新加载Postfix。在大多数环境中,客户端地址很少更改。不要使CIDR表成为哈希文件;它们工作不好。
我们刚才看到的CIDR表是 access database 的一个示例。列表中的每个项目都附在OK或REJECT上。访问数据库允许您决定接受或拒绝哪些消息。
Postfix包括配置项,允许您检查单个电子邮件地址、帐户、域等。也许您的服务器接受来自某个IP地址的邮件,但稍后的配置设置会根据特定消息使用的 MAIL FROM
拒绝它。这是一种重要的保护。假设一个垃圾邮件发送者闯入了你的一个网络服务器。服务器位于数据包过滤器之后,因此他们必须通过您的MTA中继垃圾。Postfix将接受来自该IP地址的邮件,但当垃圾邮件发送者将其出站域设置为自己的域时,Postfix将拒绝它。
每个访问表都有三种可能的设置,但您将主要看到 ACCEPT
(或 OK
)和 REJECT
。 OK 的意思是“这很好,传递下去。” REJECT 就是拒绝。
还有第三种选择,但几乎从未明确说明过,你可能永远不会在表格中看到它。 DUNNO 隐式出现在每个表的末尾。这意味着“此表对接受或拒绝此消息没有意见。”处理仍在继续,下一个选项有机会。上面的CIDR表以隐式DUNNO结尾。仅当表的文档明确声明有必要时,才在表中显式使用DUNNO。如果你深入研究调试输出,你可能会看到它。
假设你有一个表,上面写着“自动接受来自这些IP地址的邮件”,另一个表写着“拒绝来自这些IP的所有邮件”。如果源IP在两个列表上,会发生什么?假设一个域名出现两次,一次是ACCEPT,一次则是REJECT?这取决于上下文。
如果键值列表包含两次相同的键, postmap
会抱怨。根据数据库的使用方式,Postfix可能会使用第一个或最后一个条目。免去你的痛苦;当 postmap
抱怨时,请注意。
如果在 main.cf 中给出两次参数(或在 master.cf 中提供两次服务),Postfix会记录一个警告并使用最后一个。
如果您有一个非数据库键值文件,如CIDR表,则第一个获胜。
如果您使用多个访问数据库进行限制(例如在 smtpd_option_restrictions
设置中),则第一个获胜。
在配置服务器的整个过程中,我们将使用表和访问数据库。
正如第1章所讨论的,本地传递代理(Local Delivery Agent——LDA)接受来自MTA的消息并将其传递到用户的邮箱。Postfix附带了 local(8)
LDA,它在接受文件并将其粘贴到目录中方面做得非常出色。到目前为止,我们只需要这些。不过,如果你在生产环境中运行电子邮件,你可能需要过滤、邮箱扩展和虚拟域等功能。此时,我们将使用Dovecot提供的LDA,dovecot-lda(1)
。
有一个用户 dovecot-lda
无法将邮件传递到:root
。用户必须能够编辑和删除自己的消息,因此 dovecot-lda
以目标用户的身份运行。出于安全原因,它不会以 root
身份运行,因此无法将邮件传递给 root
。确保别名文件将邮件转发给 root
用户。
Postfix将多个环境变量导出到LDA。完整列表可在 postconf(5)
中找到,但关键列表是$SENDER(电子邮件的发件人)和$RECIPIENT(收件人)。
Postfix选项 mailbox_command
设置LDA。它通常为空,指示系统使用 local(8)
。请使用 dovecot-lda
的完整路径。使用 -f
标志指定发件人, -a
指定收件人:
xxxxxxxxxx
mailbox_command = /usr/libexec/dovecot-lda -f "$SENDER" -a "$RECIPIENT"
重新加载Postfix。在一个终端窗口中,在邮件日志上运行 tail -f
。在另一种情况下,发送一封测试邮件:
xxxxxxxxxx
$ echo "dovecot test" | mailx -s "dovecot test" mwlucas
您的邮件日志应显示Postfix使用您指定的参数调用 dovecot-lda
,然后 dovecot-lda
将其放入您的邮箱。检查你的邮件目录,你应该会看到一条新消息。如果邮件日志显示错误,要么是你错过了什么,要么是Unix的默认 doveco.conf 有不完整或不准确的crud,破坏了简单的本地交付。我们稍后将介绍如何配置 dovecot-lda(8)
。
有了Dovecot的LDA,我们可以查看虚拟主机。
与 server 一词完全一样,技术专业人员已经将 virtual server 这个词折叠、扭曲,并通常使其变得毫无意义。在他们看来,几十年来,系统能力呈指数级增长,1985年不可想象的梦想如今变得微不足道。
最初,主机只能接收发往它们的请求,无论是邮件、Gopher还是HTTP 0.9等超高级协议。新的、令人兴奋的“虚拟服务器”功能允许主机响应发往其主机名以外的主机名的传入请求。我的web服务器的主机名为 www.ratoperatedvehicle.com
,但它也接受对 ratoperatedvehicle.com
的请求。这是一个虚拟主机。商业网络服务器可能以这种方式托管数百或数千个网站。同样,我们一直在构建的邮件系统有一个像 mail.solveamurder.org
这样的主机名,但我们希望它接受发往裸 solveamurder.com
用户的邮件。这是一个虚拟电子邮件服务器。我们将像过去一样称之为“虚拟主机”,以将其与通常用于描述在虚拟机中运行的操作系统安装的术语“虚拟服务器”区分开来。
与我们一直使用的测试配置相比,为生产域使用虚拟主机具有优势。直接向主机发送邮件需要每个有效的电子邮件地址都有一个Unix帐户。您的通用电子邮件地址不应与系统帐户绑定。如果有人想攻击我的MTA,电子邮件地址 mwl@mwl.io
无法提供有关我的系统帐户名的任何线索。欢迎入侵者尽可能多地攻击不存在的shell帐户 mwl
;它将生成IP地址以馈送到我的数据包过滤器。
虚拟主机的配置完全独立于主主机(main host)的电子邮件,甚至主机的配置。一旦你设置了第一个虚拟电子邮件主机,配置就可以很容易地复制到其他域中。想要运行自己电子邮件的系统管理员几乎肯定已经注册了多个域名。
Postfix允许将虚拟域映射到Unix帐户,但对于缓慢增长的系统来说,这是一个权宜之计。您还可以使用它们来支持父域,即在 mail.ratooperatedvehicle.com
上接收 ratoperatedvewicle.com
的邮件。在大多数情况下,不与任何系统帐户绑定的纯虚拟域更具可持续性,因此我们将重点关注它们。主机可以同时拥有这两种类型的帐户。
电子邮件配置迅速变得复杂,有工具可以管理这种复杂性。我们将手动进行基本设置,以便您了解系统是如何连接在一起的,然后在第6章中切换到使用数据库支持的管理系统。
支持虚拟主机意味着通知Postfix虚拟主机和其中的电子邮件地址,为这些域和地址配置Dovecot,并配置代理向这些虚拟主机传递邮件。
当发往主机名的邮件将消息放置在用户的帐户中时,虚拟主机需要用户拥有接收到的消息和存储它们的目录。
我建议对邮件消息使用专用文件系统或ZFS数据集。每个虚拟主机在装载点下都有自己的目录。Postfix和Dovecot将管理邮箱内容。在这些示例中,虚拟域邮箱位于 /vhosts 下。
您需要一个无特权帐户才能拥有虚拟主机邮件。我们在第1章中创建了 vmail
用户,正是为了这个目的。
一旦你有了这些,在 main.cf 中配置虚拟主机。Postfix有30多个虚拟主机选项,都是从 virtual_
开始的。以下是在主机 mail.ratooperatedvehicle.com
上建立虚拟主机 ratoperatedveicle.com
所需的最小选项:
xxxxxxxxxx
virtual_mailbox_domains = ratoperatedvehicle.com
virtual_mailbox_base = /vhosts
virtual_mailbox_maps = hash:/etc/postfix/virtual-mailboxes
virtual_alias_maps = hash:/etc/postfix/virtual-aliases
virtual_mailbox_domains
选项列出了此Postfix安装接受邮件的虚拟主机。我们只有一个虚拟域,但以后可以添加更多。
使用 virtual_mailbox_base
,我们告诉Postfix在哪里存储传入邮件。每个域都将在此目录下获得一个目录,用户帐户位于其他子目录中。
virtual_mailbox_maps
提供的文件列出了每个虚拟主机的有效帐户,并存储为本地数据库。Postfix哈希文件需要一个键和一个值,因此此文件需要两列。从技术上讲,我们只需要一个列表,但稍后将利用此文件声明谁有权以该用户的身份发送邮件,因此添加第二列包含相同信息。(我们将在第5章中看到它是如何工作的。)在这里,我创建了一个帐户, mwl@ratoperatedvehicle.com.
,在 /etc/postfix/virtual-mailboxes 文件中。
xxxxxxxxxx
mwl@ratoperatedvehicle.com mwl@ratoperatedvehicle.com
每个域都需要别名。virtual_alias_maps
选项告诉Postfix在哪里可以找到每个域别名的信息。我的虚拟主机需要第1章中讨论的标准别名,它们应该发送到我在该域的帐户。 virtual_alias_maps
选项指向 /etc/postfix/virtual-alias 文件,因此我在那里创建了标准别名:
xxxxxxxxxx
postmaster@ratoperatedvehicle.com mwl@ratoperatedvehicle.com
hostmaster@ratoperatedvehicle.com mwl@ratoperatedvehicle.com
webmaster@ratoperatedvehicle.com mwl@ratoperatedvehicle.com
abuse@ratoperatedvehicle.com mwl@ratoperatedvehicle.com
编辑这些文件后更新数据库:
xxxxxxxxxx
您将看到对选项 virtual_uid_maps
和 virtual_gid_maps
的引用。这些支持Postfix的虚拟域交付代理,但我们将使用Dovecot的交付代理。
Postfix现在知道这些帐户,并可以接受它们的邮件。现在将它们发送到用户帐户。
从主机中删除电子邮件帐户可能会保护操作系统,但电子邮件帐户信息必须存在于某个地方。我们将把它存放在Dovecot。在电子邮件虚拟主机发明之前,Dovecot从 /etc/passwd 读取用户名和密码。今天,Dovecot密码数据库保留了与 /etc/passwd 的兼容性。在系统上使用实际文件会限制您的管理能力,但Dovecot通过“运行此查询并将结果格式化为 /etc/passwd ”这一历史悠久的方法,增加了对其他数据源的支持。我们将在第6章中部署SQL后端,但必须了解密码文件格式才能这样做。
密码文件包含八个字段。 /etc/passwd gecos(实名)和shell字段被忽略和未使用,但Dovecot保留了它们以保持兼容性。
username:password-hash:uid:gid:ignored:home:ignored:extras
username 是完整的电子邮件地址。用户名被规范为小写。你可以玩各种各样的Dovecot技巧来改变这一点,但将电子邮件地址作为帐户名是可以接受的做法。
您可以使用 dovecot-pw(1)
生成密码哈希,我们将在下一章中看到。
uid 和 gid 设置了磁盘上文件的所有者。此电子邮件帐户可能没有操作系统帐户,但文件需要所有者。在我们的示例中,我们将使用系统用户 vmail
作为UID和GID。
home 设置用户的主目录。
你可以在结尾添加额外内容,但不要。
您只需要电子邮件地址后跟五个冒号即可传递邮件。您的密码文件最终将需要实际的密码,但现在只声明电子邮件地址存在。你甚至不需要所有的冒号,因为Dovecot忽略了最后两个字段:
xxxxxxxxxx
mwl@ratoperatedvehicle.com:::::
在下一节中,我们将使用Dovecot的其他功能将其他几个字段设置为默认值。
Dovecot用户帐户需要三条信息:用户数据库、密码数据库和用户电子邮件的存储位置。我们将从最简单的系统开始,只需将邮件发送到您的帐户即可,稍后进行扩展。
Dovecot密码数据库包含用户的密码和任何预登录帐户详细信息。使用passdb选项在 /etc/dovecot/dovecot.conf 中定义密码数据库。
xxxxxxxxxx
passdb {
driver = passwd-file
args = /etc/dovecot/passwd
}
驱动程序选项定义了我们存储密码的系统类型。它可能是LDAP或SQL数据库、Redis等键值存储或外部程序。Dovecot甚至可以组合多个数据库。目前,我们使用的是与 /etc/passwd 兼容的密码文件,尽管我们将在第6章中用数据库替换它。
args
选项允许我们声明如何使用驱动程序。最后一个参数必须是包含密码数据库的文件,或者是连接到它的配置。我们不需要任何复杂的选项,所以只需给出密码文件的路径。
Dovecot用户数据库包含用户身份验证后所需的信息。它可以与密码数据库相同,也可以出于性能原因而拆分。同样,这是一个小型服务器,因此我们将使用相同的数据库。使用 dovecot.conf 中的 userdb
选项定义用户数据库。
xxxxxxxxxx
userdb {
driver = passwd-file
args = /etc/dovecot/passwd
default_fields = uid=vmail gid=vmail home=/vhosts/%d/%n
}
driver
和 args
选项与 passdb
中的完全相同。但是,default_fields
选项是新的。为了简化密码数据库,并帮助将存储管理与用户管理分开,您可以为用户帐户信息定义默认值。
uid
和 gid
选项允许您定义拥有磁盘上邮件文件的Unix帐户,从而省去了在主机密码文件中复制条目的麻烦。使用我们之前设置的系统 vmail
用户的UID和GID。
home
选项设置用户的主目录。您可以将主目录硬编码到用户数据库中,以覆盖选定用户的此设置,但设置默认值可确保文件存储的一致性。这个例子利用了Dovecot变量,如第3章所述。请记住,%n
表示电子邮件地址中@之前的部分,%d
表示之前的部分。每个用户的主目录将默认为 /vhosts/domain/name 。
如果我们使用相同的数据源,为什么有两个单独的选项?对于小型邮件系统来说,这并不重要。然而,一个需要为其web服务器和集群所有数据库提供负载平衡器的企业可能需要两个单独的数据库。
一旦用户有了主目录,您就可以告诉Dovecot将用户的邮件放在哪里以及使用什么格式。我们的虚拟用户不需要shell帐户获得的任何常见碎片;他们的主目录仅用于存储电子邮件。使用 mail_location
doveco.conf 选项告诉dovecot使用Maildir格式,并将邮件直接粘贴到用户的主目录中。
xxxxxxxxxx
mail_location = maildir:~
现在将Dovecot和Postfix焊接在一起。
Local Mail Transport Protocol ——本地邮件传输协议——LMTP
一旦你开始托管虚拟域并添加一些用户,你会发现有些人收到的消息比任何理智的人都多。 dovecot-lda(1)
程序非常适合处理单个消息,但它为每封收到的邮件都生成了一个新的进程。一旦多条消息开始同时到达,通过本地邮件传输协议(LMTP)使用专用守护进程进行本地传递会更有效率。
为什么本地电子邮件有单独的协议?LMTP是SMTP的大幅精简版本。LMTP不需要队列;它要么将消息传递到用户的收件箱并报告成功,要么无法传递并报告错误。SMTP守护进程处理任何排队。标准LMTP是为可信环境设计的,因此它没有访问控制。如果你能连接到LMTP服务器,你就可以使用它。如果你有单独的主机用于消息存储和邮件交换器,你可以在它们之间使用LMTP,并使用数据包过滤器、防火墙和一个手持六刃光剑的西斯尊主来保护服务。但是,对于单个服务器,请在Unix套接字上使用LMTP。
与Postfix非常相似,Dovecot包含许多小型服务。每个都是单独配置和启用的。这是一个 doveco.conf 配置,使Dovecot提供一个LMTP侦听器,Postfix可以在其中访问它,并用protocols
语句激活它:
xxxxxxxxxx
protocols lmtp
service = lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
group = postfix
mode = 0600
user = postfix
}
}
我们从 service
声明开始,通知Dovecot此配置适用于LMTP。
unix_listener
语句创建了一个unix套接字。目录 /var/spool/postfix 是 postfix
用户的主目录, private 子目录只能由该用户读取。套接字名为 dovecot-lmtp ,因为Postfix有自己的LMTP服务器,我们需要明确避免它。
接下来的三个条目定义了套接字上的用户、组和权限。只有Postfix可以与此侦听器通信。您必须在权限中包含前导零。
重新启动 dovecot
,套接字应该出现。如果没有,请验证 protocols
语句是否包含 lmtp
。Dovecot将在没有该语句的情况下解析此配置,但除非您声明它应该,否则它不会激活LMTP。一旦套接字存在,请配置Postfix。
虽然 mailbox_command
选项为具有关联Unix帐户的电子邮件地址设置传递代理,但Postfix使用 main.cf virtual_transport
选项为虚拟域设置传递代理。如下所示:
xxxxxxxxxx
virtual_transport = lmtp:unix:private/dovecot-lmtp
这个命令告诉Postfix通过位于 private/dovecot-lmtp 的Unix套接字使用LMTP。此路径与我主机上的Postfix的 queue_directory
设置 /var/spool/Postfix 有关。设置此选项并重新启动Postfix。
理论上,启用LMTP将使您从Postfix中删除有关用户帐户的所有知识。在实践中,这会产生反向散射。Postfix使用 virtual_mailbox_maps
和 virtual_alias_maps
选项来标识它应该接受哪些电子邮件地址的邮件。
配置虚拟主机需要一大堆东西,你可能在某个地方搞砸了。测试你的工作。在一个终端中,在你的邮件日志上运行 tail -f
。在另一个中,发送测试消息。
xxxxxxxxxx
如果这有效,邮件日志应显示已送达。Dovecot应创建目录 /vhosts/ratoperatedvehicle.com/mwl ,该目录应包含Maildir的 cur 、 new 和 tmp 文件夹。您还将看到Dovecot面向客户端服务所需的几个元数据文件。
如果你没有看到这个,停下来。查看日志。看看系统出了什么问题。在您的第一个帐户收到邮件之前,请不要继续。一旦您的第一个帐户正常工作,您就可以添加其他帐户。
LMTP是一个精简的SMTP,因此它在邮件顶部添加了一个 Received
标头。
xxxxxxxxxx
Received: from mail.ratoperatedvehicle.com
by mail.ratoperatedvehicle.com with LMTP
id ozleJvaMfGVmZwEAk08d9g
(envelope-from <mwlucas@mwl.io>)
for <mwl@ratoperatedvehicle.com>; Fri, 15 Dec 2023 12:29:26 -0500
标头明确声明此消息是通过LMTP传递的。
我们在本地主机上使用LMTP,所以很简单。如果您的LMTP配置涉及多个主机,您可能会看到LMTPA(用于带SMTP AUTH的LMTP)、LMTPS用于TLS上的LMTP,或LMTPSA用于带TLS和SMTP AUTH两者的LMTP。
如果一切正常,我们可以继续面向客户的服务。