第五章:IMAP和提交Dovecot用户密码密码算法密码文件Dovecot用户查询Internet Message Access Protocol使用 OpenSSL 测试IMAP使用 Mutt 测试IMAP提交服务Dovecot SASL设置Postfix SASL将SASL连接到提交:master.cf提交测试和故障排除询问提交服务使用Mutt提交邮件提交和标题
您的服务器可以发送和接收邮件,但您可能不想使用 cat(1)
和 rm(1)
作为客户端。是时候配置您的服务器以支持适当的电子邮件客户端了。互联网消息访问协议(Internet Message Access Protocol —— IMAP)允许客户端在客户端和服务器之间同步消息。它用于桌面和手机客户端,如Thunderdbird和Outlook,以及基于web的电子邮件系统,如Roundcube。
虽然在客户端和服务器之间同步邮件文件夹很好,但大多数用户也希望发送邮件。Postfix的 submission 服务允许经过身份验证的客户端通过服务器发送邮件。如果您提供未经身份验证的提交服务,垃圾邮件发送者将利用您销售Wookie增强补充,因此我们将在接受邮件之前,让Postfix根据Dovecot IMAP用户数据库对SMTP提交进行身份验证。经过身份验证的SMTP通常称为 SMTP AUTH 。
我们将了解如何配置IMAP的用户帐户、配置和测试IMAP以及配置提交服务。
在第4章中,我们向Dovecot介绍了虚拟主机帐户。不过,要通过IMAP访问邮件,这些帐户必须有密码。虽然Dovecot可以从LDAP或SQL访问用户帐户信息,但目前我们使用的是密码文件。第6章讨论了使用数据库后端。
与所有合规的密码系统一样,Dovecot存储的是密码哈希值,而不是实际密码。永远不要存储用户的实际密码,只存储哈希值!
doveadm-pw(1)
命令是密码管理界面。Dovecot支持许多不同的流行和晦涩的密码算法,具体取决于你的包是如何构建的。要获得完整的算法列表,请运行 doveadm-pw -l
:
xxxxxxxxxx
$ doveadm pw -l
SHA1 SSHA512 SCRAM-SHA-256 BLF-CRYPT PLAIN HMAC-MD5 OTP SHA512 SHA DES-CRYPT CRYPT SSHA MD5-CRYPT PLAIN-MD4 PLAIN-MD5 SCRAM-SHA-1 SHA512-CRYPT CLEAR CLEARTEXT SSHA256 MD5 PBKDF2 SHA256 CRAM-MD5 PLAIN-TRUNC SHA256-CRYPT SMD5 DIGEST-MD5 LDAP-MD5
这些算法是什么,你为什么关心?大多数时候,你不会。
你只需要选择一个在你的服务器上运行。(客户端不在乎服务器使用什么算法。)
Dovecot在本书出版时的文件声明ARGON2I或ARGON2ID是首选算法。接下来是Blowfish(BLF-CRYPT)。2010年,NIST推荐了PBKDF2算法,尽管2023年NIST宣布他们将修改他们的建议。如果没有别的,几乎所有地方都支持加盐的SHA512方案SSHA512。受支持的许多其他算法直接来自OpenSSL,不适合生产使用。除非你的组织的安全策略坚持你遵循危险过时的标准,否则不要使用它们。我的一些服务器不支持ARGON2I算法,所以我们将使用Blowfish。
使用 dovedam -pw
将密码转换为哈希值。使用 -s
指定算法:
xxxxxxxxxx
Enter new password:
在系统提示时输入密码,进行验证,doveadm
将返回密码哈希值:
xxxxxxxxxx
{BLF-CRYPT}$2y$05$I1DVk0hpTBKE.ZCfY4AJcujHv/U9l/0OlWSTwwpipmspGOJ2NkFFW
如果您想在命令本身中输入密码,请知道纯文本密码将出现在系统的进程列表、shell历史记录以及跟踪哪些命令运行的任何其他内容中。这是一种糟糕的做法,但你可以通过添加 -p
标志和密码来实现:
xxxxxxxxxx
{BLF-CRYPT}$2y$05$7H9wb7ptU0qQ7WRTRRxrZOMyzdmreK59wofg5zbNBxXSxlCgLXU9a
一旦你有了密码哈希,你会用它做什么?
我们在第4章中设置了一个密码文件,但它只包含地址。现在我们将添加密码。
如果您是系统上唯一的用户,那么在密码文件中管理密码并非不合理。然而,如果你有多个用户,将密码哈希存储在真实的数据库中并提供基于网络的前端将更易于维护。我们将使用密码文件向您展示系统的工作原理,然后稍后迁移到数据库。
密码哈希是Dovecot密码文件中的第二个条目。取哈希密码并将其放入帐户行:
xxxxxxxxxx
mwl@ratoperatedvehicle.com:{BLF-CRYPT}$2y$05$36zhhB3...::::
有了这个,帐户现在可以进行身份验证。有希望。
现在此帐户有了密码,您可以在Dovecot级别测试身份验证。使用 dovedam-auth(1)
lookup
功能验证dovecot密码数据库是否看到该帐户:
xxxxxxxxxx
passdb: mwl@ratoperatedvehicle.com
user : mwl@ratoperatedvehicle.com
该帐户位于密码文件中。我正确地完成了那部分。不过,Dovecot对用户和密码数据库有单独的配置,所以我们也应该对此进行验证。使用 doveadm-user(1)
检查用户数据库:
xxxxxxxxxx
field value
uid 5000
gid 5000
home /vhosts/ratoperatedvehicle.com/mwl
mail maildir:~
它存在,信息看起来是正确的。UID和GID来自系统的 vmail
用户,除了作为占位符外,与虚拟用户无关。
现在让我们看看我们是否使用 auth test
子命令正确设置了密码。提供用户名作为参数:
xxxxxxxxxx
Password:
输入密码,doveadm将进行验证:
xxxxxxxxxx
passdb: mwl@ratoperatedvehicle.com auth succeeded
extra fields:
user=mwl@ratoperatedvehicle.com
如果你愿意忽略风险,你也可以把密码作为最后的参数:
xxxxxxxxxx
要从密码和用户数据库中读取用户信息,请使用 auth login
子命令模拟完全登录:
xxxxxxxxxx
Password:
passdb: mwl@ratoperatedvehicle.com auth succeeded
extra fields:
user=mwl@ratoperatedvehicle.com
userdb extra fields:
mwl@ratoperatedvehicle.com
uid=5000
gid=5000
home=/vhosts/ratoperatedvehicle.com/mwl
auth_mech=PLAIN
这正是我们在Dovecot配置和密码文件中设置的。如果实际的客户端无法进行身份验证,我们知道密码是正确的,但客户端和数据库之间的管道被破坏了。
我们现在就安装管道吧。
Dovecot提供IMAP,让客户端访问他们的邮件。它也支持POP3,但这已经过时了几十年,如果有人要求它,告诉他们是时候扔掉他们的PalmPilot了。一旦您的虚拟主机拥有带密码的帐户,启用IMAP就很简单了。
在 doveco.conf 中找到 protocols
语句。将 imap
添加到列表中:
xxxxxxxxxx
protocols = lmtp imap
不要重新启动 dovecot
!与telnet和FTP一样,IMAP最初是未加密的,在端口143上运行。加密连接,通过TLS隧道传输IMAP,被称为IMAPS,在端口993上运行。您有X.509证书,因此您应该只允许通过TLS进行连接。我们在第3章中配置了TLS,因此Dovecot将自动启用您打开的任何协议的TLS版本。通过告诉Dovecot在端口 0
上运行该服务来禁用未加密的IMAP:
xxxxxxxxxx
service imap-login {
inet_listener imap {
port=0
}
}
Dovecot的 imap-login
服务处理用户连接。inet_listener
选项控制Dovecot如何接受网络连接。将未加密的IMAP设置为在端口 0
上侦听会禁用它。
Dovecot支持多种用户身份验证方法。它们中的大多数是在X.509证书太昂贵而无法部署到任何地方时创建的,并且使用复杂的加密技术来保护凭据。通过只允许通过TLS的客户端连接,您可以允许简单的身份验证方法。最常见的IMAP身份验证方法称为PLAIN,是Dovecot的默认方法。Microsoft Outlook和Microsoft Mail等Microsoft客户端不支持此标准;相反,他们有一个名为LOGIN的调整版本。Dovecot支持登录,但默认情况下不支持。如果支持Microsoft客户端,请使用 auth_mechanisms
选项启用登录。
xxxxxxxxxx
auth_mechanisms = plain login
就是这样。重新启动Dovecot,它应该监听TCP端口993上的客户端,而不是143。
仔细检查您的帐户中是否还有一些测试邮件,然后继续测试。
与大多数电子邮件相关协议一样,IMAP是基于文本的。您可以使用 netcat
或OpenSSL连接到服务,进行身份验证,并在没有客户端的情况下读取消息。不同的 netcat
客户端通过多种命令行标志为TLS连接提供不同的支持,甚至可能根本不支持TLS,因此我们将使用始终一致的 openssl(1)
与IMAP服务器进行通信。该命令的格式如下:
xxxxxxxxxx
s_client
关键字是一个OpenSSL子命令,它告诉OpenSSL它正在连接到受TLS保护的服务。 -quiet
命令告诉OpenSSL跳过打印所有TLS详细信息。我只想知道TLS是有效的。 -connect
选项允许我们将OpenSSL指向TCP端口。最后,给出目标主机名和端口。我想在IMAPS端口993上连接到 mail.ratoperatedvehicle.com
:
xxxxxxxxxx
depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = R3
verify return:1
depth=0 CN = mail.ratoperatedvehicle.com
verify return:1
我告诉OpenSSL对TLS的细节保持沉默,但它坚持打印其中的一些细节,所以我尽量忽略它们。然后我们得到实际的IMAP信息:
xxxxxxxxxx
* OK [CAPABILITY IMAP4rev1 SASL-IR LOGIN-REFERRALS ID ENABLE IDLE LITERAL+ AUTH=PLAIN] Dovecot ready.
OK表示Dovecot已准备好并愿意满足我的要求。接下来,我们列出了此服务器支持的功能。协议版本(IMAP4rev1)对于调试其他服务器可能很重要。目前,AUTH=PLAIN语句声明服务器接受通过文本用户名和密码登录。
IMAP不提供命令提示符。如果有一个空行,服务器要么在等待你做某事,要么超载到无法回答你。请发出命令。命令不区分大小写。
每个IMAP命令都以 tag 开头。tab(标签)是标识此命令的文本字符串。IMAP允许异步提供多路复用命令。您可以将所有测试命令放在一个长命令中,并让服务器按顺序执行它们。简化调试。别胡思乱想。一次发出一个命令。我习惯用 tag 这个词作为我的标签,但它可以是任何东西。如果您在会话中重复使用标签,一些IMAP服务器甚至会感到恼火。
首先,登录。 login
命令有两个参数,帐户和密码。我的账户是 mwl@ratoperatedvehicle.com
,我提供密码:
xxxxxxxxxx
tag login mwl@ratoperatedvehicle.com MyRealPasswordIPromise
tag OK [CAPABILITY IMAP4rev1 SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS BINARY MOVE SNIPPET=FUZZY PREVIEW=FUZZY PREVIEW STATUS=SIZE SAVEDATE LITERAL+ NOTIFY] Logged in
我们现在知道基本的登录功能是有效的。客户端可以进行身份验证。但既然我们在这里,让我们看看这个邮箱里有什么。LIST命令有两个参数,要列出的文件夹和其中的消息。我想看看一切:
xxxxxxxxxx
tagg list "" "*"
我拼错了标签?哎呀。标签名并不重要,记得吗?IMAP服务器返回邮箱列表:
xxxxxxxxxx
* LIST (\HasNoChildren) "." futurepain
* LIST (\HasNoChildren) "." errors
* LIST (\HasNoChildren \UnMarked) "." ignore
* LIST (\HasNoChildren) "." Trash
* LIST (\HasNoChildren) "." INBOX
tagg OK List completed (0.001 + 0.000 secs).
使用IMAP,每个用户都有一个INBOX文件夹,即使它是空的。即使该目录在服务器上不存在。其他文件夹是存储或已经存储邮件的目录。让我们看看收件箱,看看有什么新消息:
xxxxxxxxxx
ttag select INBOX
* FLAGS (\Answered \Flagged \Deleted \Seen \Draft Old)
* OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft Old \*)] Flags permitted.
Dovecot会记住客户可以设置的标志。标记是客户端如何将某些消息标记为已查看、已回复、草稿等。
xxxxxxxxxx
* 3 EXISTS
* 0 RECENT
我有三条信息。自上次客户端访问此邮箱以来,出现了“Recent”的消息。
xxxxxxxxxx
* OK [UNSEEN 3] First unseen.
* OK [UIDVALIDITY 1691091894] UIDs valid
* OK [UIDNEXT 8] Predicted next UID
ttag OK [READ-WRITE] Select completed (0.001 + 0.000 secs).
然而,消息3尚未被看到。UID的详细信息与我们无关。我想看到消息3,所以我使用FETCH命令。FETCH允许您查询标头、仅抓取消息正文或其他任何内容,但RFC822选项允许您查看整个消息:
xxxxxxxxxx
tag fetch 3 rfc822
* 3 FETCH (FLAGS (\Seen) RFC822 {843}
The response tells us that Dovecot understands the command and will comply.
Return-Path: <mwlucas@mail.ratoperatedvehicle.com>
Delivered-To: mwl@ratoperatedvehicle.com
...
Subject: yet another test
Message-ID: <ZPoCFqXn5zyx6OEx@mail.ratoperatedvehicle.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Did you really create this message just so you'd have something to show in the book?
)
tag OK Fetch completed (0.001 + 0.000 secs).
是的,是的,我做到了。
这足以验证IMAP服务器是否接受登录并检索邮件。您可以确信,正确配置的客户端将正常工作。
Outlook和Thunderbird等电子邮件客户端希望与功能齐全的邮件系统进行通信。你还没有。测试IMAP配置需要一个单独处理IMAP和发送邮件的客户端。如果你已经习惯了你喜欢的邮件客户端,并且可以让它单独测试接收和发送,那么就使用它。在你的客户端中配置一个IMAP帐户,尝试连接,看看会发生什么。
如果你没有这样的客户端,我推荐mutt
(http://www.mutt.org)。mutt相对于其他邮件客户端的一个优势是,您可以在服务器上运行它,让您测试IMAP和邮件提交等功能,而无需担心桌面和服务器之间的网络。您应该已经按照第1章中的讨论配置了数据包过滤器,但只有在这些端口上有东西在监听时才能对其进行测试。
Mutt是一个命令行电子邮件客户端,默认情况下只显示文本。这很好——问题不是“我们可以查看漂亮的垃圾邮件吗?”而是“我们可以登录IMAP并查看我们的邮件吗?”Mutt从主目录中的 .muttrc 文件读取其配置。如果您已经在为现有帐户使用mutt,请创建一个新的 .muttrc 进行测试。设置选项 imap_user
、 spoolfile
和 folder
以使用IMAP:
xxxxxxxxxx
set imap_user = mwl@ratoperatedvehicle.com
set spoolfile = imaps://mail.ratoperatedvehicle.com/
set folder = imaps://mail.ratoperatedvehicle.com/
imap_user
选项提供您的用户名。
spoolfile
是系统存储新邮件的位置。年长的系统管理员会知道这是 /var/mail/username 。imaps
方案告诉mutt后台文件在您的IMAP服务器上。
folder
选项告诉mutt在哪里查找邮箱。再次指示它查看IMAP服务器。
这些选项应该足够了,但我们谈论的是计算机,所以会出问题。在Dovecot日志(可能是邮件日志,但如果有问题,请参阅第3章)上运行 tail -f
。在另一个终端中,运行 mutt
。您应该看到mutt声明它与服务器协商了哪些加密算法,然后收到密码提示。输入您的密码,您的邮箱应该会出现:
xxxxxxxxxx
q:Quit d:Del u:Undel s:Save m:Mail r:Reply g:Group ?:He
1 Aug 07 Lucas (0.5K) default maildir test 2
---Mutt: =INBOX [Msgs:1 0.5K]---(date/date)-----------(all)---
顶部的行列出了有用的命令。下面,每条邮件都会显示在自己的行中。此邮箱有一封邮件,是之前的测试。Mutt列出了邮件的发送日期、发件人姓名、邮件大小、邮箱和邮件主题。使用上下箭头在消息之间移动,按 ENTER
键查看消息,按 i
键返回此索引。删除带有 d
的邮件。
Mutt在文件夹名称前加上等号。要将此测试消息保存到文件夹中,请使用 s
命令,然后给出一个文件夹名称,如 =test
。通过给出 c
命令和目标文件夹名称,可以在文件夹之间移动。如果你想查看所有文件夹,请使用 c
,然后使用问号。然后,你可以在文件夹之间上下箭头。
如果您可以看到您的邮箱,则表示您正确配置了客户端。如果不能,请阅读mutt和Dovecot的错误日志和故障排除中的错误消息。IMAP工作后,您可以继续使用Postfix的提交服务。
MTA的一个关键功能是 拒绝 (refusing)邮件。
标准MTA接受发往本地主机上帐户的邮件。如果我发邮件到 mwl@solveamurder.org
当它到达 solveamurder.org
的MTA时,MTA应该接受邮件或声明该帐户不存在。MTA还有一个IP地址列表,它将为其转发邮件。如果我在网络 2001:db8:bad:code:cafe::/64
上有一群电子商务服务器,并且我设置了一个MTA来处理这些邮件,那么MTA需要接受来自这些地址的邮件并将其发送给收件人。(在客户端上安装一个真正的邮件程序,并让他们使用SMTP AUTH会更好。)
问题出在其他人身上。您组织的成员应通过您的MTA发送正式邮件。在远程办公和旅行之间,他们的IP地址不稳定。你需要一种方法来告诉你的服务器接受和转发来自这些客户端的邮件,但仍然拒绝垃圾邮件发送者。
这就是 submission 服务的来源。
提交——submission,是“常规SMTP加用户身份验证”。它在端口465上运行TLS,在端口587上运行STARTTLS。每个客户端都提供一个特殊编码的用户名和密码。如果MTA可以验证它们,则客户端可以发送其消息。如果MTA无法验证凭据,则客户端将被拒绝。提交服务通常应用与接受公众邮件的MTA不同的过滤和处理规则。
提交的诀窍在于,Postfix对用户或密码一无所知。只有Dovecot有这些信息。当Postfix收到其控制的域的电子邮件时,它会询问Dovecot帐户是否存在。任何处理身份验证超过一周的人都知道,在一个地方维护用户身份验证数据是不加入黑暗面的唯一方法。Postfix必须接受客户端的身份验证信息,并询问Dovecot是否有效。
这正是简单身份验证和安全层(Simple Authentication and Security Layer —— SASL)的用途。我们将配置Dovecot来应答SASL请求,然后让Postfix发出请求。
Dovecot包括一个示例SASL配置,但我们将从头开始构建一个。与LMTP一样,让Dovecot通过Unix套接字与Postfix通信,并用权限保护该套接字。
xxxxxxxxxx
service auth {
unix_listener /var/spool/postfix/private/dovecot-sasl {
mode = 0600
user = postfix
group = postfix
}
}
这看起来几乎与LMTP条目完全相同。 service
条目声明这是一个 auth
(authentication)服务。 unix_listener
条目告诉Dovecot在哪里创建套接字。 mode
、 user
和 group
选项设置该套接字的权限。只有用户 postfix
可以访问套接字,尽管它应该是 setuid
。重新启动 dovecot
,您应该会看到套接字出现。
xxxxxxxxxx
srw------- 1 postfix postfix 0 Mar 31 09:54 dovecot-sasl
如果权限看起来不像这样,请验证您在mode中包含了前导零。
一旦套接字存在,使用 doveadm(1)
验证SASL是否正常工作,以及此套接字是否可以提供身份验证:
xxxxxxxxxx
$ doveadm auth test -a /var/spool/postfix/private/dovecot-sasl user
在这里,我用我的帐户测试SASL身份验证:
xxxxxxxxxx
$ doveadm auth test -a dovecot-sasl mwl@ratoperatedvehicle.com
Password:
passdb: mwl@ratoperatedvehicle.com auth succeeded
SASL工作!如果我不介意我的密码出现在进程列表和shell历史记录中,我可以把密码放在命令行末尾。Dovecot部分工作后,我可以继续进行Postfix。
通过SASL进行Postfix检查Dovecot涉及告诉Postfix应该使用什么SASL实现以及在哪里找到身份验证套接字。这不会启用SASL来提交电子邮件,但只是简单地告诉Postfix该设施存在以及在哪里可以找到它。
许多在线示例显示,仅通过 master.cf 为提交服务设置这些值。我更喜欢在 main.cf 中配置SASL提供程序(和任何其他服务),这样它们在可能需要它们的任何服务中都保持一致。如果我以后需要将SASL添加到Postfix的其他部分,我将从一致的配置开始。
xxxxxxxxxx
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/dovecot-sasl
smtpd_sasl_security_options=noanonymous
smtpd_sasl_local_domain=$myhostname
smtpd_sender_login_maps=$virtual_alias_maps
smptd_sasl_type
选项告诉Postfix它正在与哪个sasl实现对话。虽然sasl是一个标准,但每个实现都有自己的怪癖。
Postfix需要知道如何联系SASL提供商。选项 smtpd_sasl_path
给出了提供者的Unix套接字的位置。此路径与queue_directory
设置相关,该设置默认为 /var/spool/postfix 。我们将Dovecot配置为在 /var/spool/postfix/private/dovicot-sasl 处创建其身份验证套接字,因此将其设置为 private/dovicot-scasl 。(有些Linux会不安,需要完整路径,或者拒绝完整路径,所以如果你有问题,可以查看Linux变体的文档,或者只是弄乱路径,看看会发生什么。)
变量 smtpd_sasl_security_options
允许您调整sasl协议中的开关。您可以执行诸如要求相互身份验证、禁止明文以及其他一些很少有用的功能之类的操作。SASL支持匿名身份验证。与Windows的“guest”帐户和LDAP的匿名绑定一样,这被证明是一个可以预见的坏主意。将 smtpd_sasl_security_options
设置为 noanonymous 以禁用此历史弱点。
每个SASL提供商都知道其权限范围。Dovecot默认使用本地主机名。这与其说是为了访问控制,不如说是为了验证客户端是否与正确的安全提供商进行了通信。要使Postfix与之匹配,请将 smtpd_sasl_loccal_domain
设置为本地主机名。
允许经过身份验证的连接是必要的,但还不够。您还需要验证发送邮件的人是否拥有他们发送邮件的帐户。我不想 flunky@ratoperatedvehicle.com
以 ceo@ratoperatedvehicle.com
身份发送电子邮件!smtpd_sender_login_maps
选项将Dovecot帐户连接到电子邮件帐户。在第4章中,我们使用 virtual_alias_maps
提供了有效电子邮件帐户的列表。目前,这是 /etc/postfix/virtual 邮箱文件。我们将双重使用该文件,将Dovecot帐户映射到Postfix地址。看看那个文件中的条目。
xxxxxxxxxx
mwl@ratoperatedvehicle.com mwl@ratoperatedvehicle.com
每个地址列出两次。部分原因是哈希文件希望看到一个键和一个值。另一个原因是,我们可以使用它来映射Dovecot和Postfix帐户。第一列定义了Postfix虚拟邮箱。第二列给出了拥有该帐户的Dovecot登录名。文件格式确实是:
postfix-account-name dovecot-user
此条目表示Postfix地址 mwl@ratoperatedvehicle.com
由Dovecot用户 mwl@ratoperatedvehicle.com
拥有。
您可以将 smtpd_sender_login_maps
直接指向别名文件,但如果您从密码文件迁移到数据库,则必须更新多个 main.cf 条目。最好将 virtual_alias_maps
指向权威列表,并将需要该列表的任何其他内容指向 $virtual_alias-maps
,以便更改透明地流过配置。
现在,您可以配置提交服务本身。
Dovecot现在提供SASL,Postfix也知道这一点。我们还没有将SASL附加到Postfix的任何组件服务中。我们不想每次MTA收到来自公共互联网的电子邮件时都给SASL打电话。相反,我们希望SASL在电子邮件到达提交服务时随时被调用。到目前为止,我们已经在 main.cf 中配置了Postfix。是时候通过 master.cf 调整 master(8)
守护进程了。
Postfix包括许多较小的守护进程和服务。默认情况下,安装提交不在其中,但请使用 postconf(1)
在您的系统上进行验证。
xxxxxxxxxx
postconf: warning: unmatched request: "submission"
如果提交已在运行,则需要查找并编辑配置。
master.cf 中的条目与 postconf -M
中显示的八列相同。这是smtp的默认条目,smtp是一种在端口25上监听并接受来自外部世界的可接受的电子邮件的服务。
xxxxxxxxxx
smtp inet n - n - - smtpd
我们浏览了第3章中的条目,但作为提醒,它们依次是:
此条目显示smtp服务通过互联网通信,不是私有的,并使用命令 smtpd
。它可能是最明显的Postfix服务,默认情况下大多正常工作。smtpd(8)
进程从 main.cf 读取其选项。
Postfix的提交服务由处理外部邮件的 smtpd(8)
程序提供。毕竟,他们都说SMTP。问题是,我们需要Postfix以与MTA到MTA邮件交换非常不同的方式处理提交。此 smtpd
进程必须侦听其他端口并允许来自任何IP地址的连接,但任何连接客户端都必须进行身份验证。我们必须广泛覆盖Postfix的默认值和 main.cf 设置。使用 -o
选项强制执行这些覆盖。现在,不要在任何等号周围加空格。
与许多Unix配置文件一样,在 master.cf 中,井号标记(#)表示注释的开头,带有文本的行是配置条目。Postfix略有不同,以空格开头的行是前一行的延续。服务条目可能非常长,允许条目换行到下一行是保持理智的唯一方法。遗憾的是,空格规则仅适用于完整语句。将长语句拆分为多行需要大括号,我们稍后会看到。
默认的 master.cf 包含一个注释掉的提交服务示例,其中包含各种有用的可能性。请随意浏览以了解可用选项,但我们将构建一个简单的提交服务,以满足大多数用户的需求。出于不久将变得显而易见的原因,我建议将其添加到 master.cf 的末尾。
xxxxxxxxxx
smtpds inet n - n - - smtpd
-o syslog_name=postfix-submission
-o smtpd_tls_wrappermode=yes
-o { smtpd_client_restrictions=permit_mynetworks,
permit_sasl_authenticated,reject }
-o smtpd_sender_restrictions=reject_sender_login_mismatch
-o smtpd_recipient_restrictions=reject_non_fqdn_recipient,
reject_unknown_recipient_domain,permit_sasl_authenticated,reject
第一行是标准的 master.cf 条目。该服务称为 submission 。它监听网络。它不是私有的,它以无特权的方式运行,也不是chroote的。此服务持续运行,因此不会被唤醒,并且可以使用的进程数量没有限制。最后一个条目是要运行的命令 smtpd
。
到目前为止,这是与 smtp
服务相同的命令,smtp
服务是 master.cf 中的第一个条目。下面所有缩进的 -o
行都是 smtpd(8)
实例的参数。前导空格表示每个空格可以在自己的行上。
通过设置 syslog_name
,您可以告诉Postfix在邮件日志中使用其他名称。这简化了故障排除。
smtpd_tls_wrappermode
选项告诉Postfix用tls包裹所有连接,周期。
默认情况下,提交服务接受来自任何人的邮件。smtpd_client_restrictions
选项允许您收紧该限制。规则按顺序应用,第一个获胜。Postfix支持许多客户端限制,让您可以微调谁可以使用它。您可以根据身份验证、IP地址、客户端TLS证书等允许访问。如果您必须限制对提交服务的访问,请务必在手册中调查此选项。这个小型邮件系统应用了三条规则。
首先,permit_mynetworks
声明mynetworks中的主机可以通过提交服务发送邮件。这些主机已经可以通过标准SMTP服务发送邮件,但某些软件希望使用提交。
permit_sasl_authenticated
选项传递来自通过sasl进行身份验证的客户端的消息。最后, reject
表示拒绝所有其他客户。
smtpd_client_restrictions
选项出现在大括号中。大括号允许在选项语句中使用空格,包括换行符。如果选项语句很长,请用大括号将其拆分。
即使你知道用户可以发送邮件,你也需要额外的完整性和健全性检查。 smtpd_sender_sessions
选项允许您对发件人施加规则。您应该始终在此处使用 reject_sender_login_mismatch
来验证提交邮件中的发件人电子邮件地址是否与Dovecot SASL用户名匹配,正如 main.cf 在 smtpd_sender_login_maps
中定义的那样。这可以防止看门人以首席执行官的身份发送邮件。Postfix支持许多大型组织感兴趣的选项,但对于大多数组织来说,这是必须的。如果你真的是这个系统的唯一用户,并且你想用你的任何帐户或别名发送邮件,你可以放弃这个。
您还应该使用选项 smtpd_recipient_restrictions
检查收到的邮件是否明显愚蠢。这使您能够尽快拒绝明显无法投递的邮件,从而减少系统负载。与其他Postfix选项一样,第一个匹配选项获胜。首先,电子邮件地址应该是完整的,比如 LordVader@galacticempire.gov
。如果用户输入了一个截断的地址,如 LordReader
,服务器应立即拒绝它。
reject_non_fqdn_recipient
设置可以做到这一点。同样,如果发件人试图向不存在的域发送邮件,服务器应拒绝接受。使用 reject_unknown_recipient_domain
启用该检查。然后,我们允许经过身份验证的客户端发送带有 permit_sasl_authenticated
的消息,并确定拒绝其他所有内容。
重新加载Postfix。现在,您可以测试来自客户端的邮件提交。
如果你完美地配置了所有内容,并且Unix的Postfix包维护者没有对默认设置进行太多更改,那么你的电子邮件客户端应该能够向MTA提交邮件。您还不能向公众发送邮件,但您有一个具有已知工作地址的第二个测试服务器。如果我的账户 mwl@ratoperatedvehicle.com
可以通过电子邮件发送我的帐户 mwl@mail.solveamurder.org
,提交成功。
如果它不起作用,事情就会变得有趣。
首先,检查错误日志。提交使用与MTA到MTA日志相同的邮件日志。查看日志,捕捉错误消息,并尝试找出原因。如果失败,则放弃客户端并直接询问提交服务。
不要直接跳到OpenSSL或支持TLS的netcat。提交不需要直接的用户名和密码。相反,您需要一个登录字符串。如果您支持Microsoft客户端,则需要两个。login string 或 authentication string 是一个格式精确的用户名和/或密码,以base64编码。Base64不是一种加密方法,而是一种以明文形式透明传输二进制文件的方法。密码不是二进制数据,但它们应该包含协议可能会考虑转义的特殊字符。在开始调试之前,先弄清楚您的身份验证字符串。
Postfix的默认身份验证方法称为PLAIN。PLAIN登录字符串是编码为base64的单行。您将看到许多使用echo的示例,但echo在shell之间是不可移植的,更不用说在操作系统之间了。使用 printf(1)
——不是shell的内置 printf
及其扩展和不兼容性,而是独立的POSIX兼容程序。您可能必须按完整路径指定它。
您需要一个程序将输出转换为base64。每个Unix都有一个,如果没有别的的话,在一个包里。我使用的是 base64(1)
,但您可以在 uuencode(1)
和OpenSSL以及其他地方找到该功能。
xxxxxxxxxx
$ /usr/bin/printf '\0username\0password' | base64
使用我的帐户名和示例密码,我将运行:
xxxxxxxxxx
$ /usr/bin/printf '\0mwl@ratoperatedvehicle.com\0ThisIsFoolish?!' | base64
AG13bEByYXRvcGVyYXRlZHZlaGljbGUuY29tAFRoaXNJc0Zvb2xpc2g/IQ==
记录身份验证字符串以备后用。
Microsoft客户端使用LOGIN身份验证方法。它也使用base64,但分别对用户名和密码进行编码。它也不需要那些讨厌的空字节。
xxxxxxxxxx
$ /usr/bin/printf 'mwl@ratoperatedvehicle.com' | base64
bXdsQHJhdG9wZXJhdGVkdmVoaWNsZS5jb20=
$ /usr/bin/printf 'ThisIsFoolish?!' | base64
VGhpc0lzRm9vbGlzaD8h
记录这些。
记住,base64不是加密。它是 编码 。这是描述完全相同字符的另一种方式,并且是可逆的:
xxxxxxxxxx
$ echo 'AG13bEByYXRvcGVyYXRlZHZlaGljbGUuY29tAFRoaXNJc0Zvb2xpc2g/IQ==' | base64 -d
mwl@ratoperatedvehicle.comThisIsFoolish?!
现在您有了身份验证字符串,就可以连接到提交服务了:
xxxxxxxxxx
$ openssl s_client -quiet -connect host:port
这里我们使用OpenSSL的 s_client
,就像测试IMAPS一样。然后,我们连接到主机和端口。要在 mail.ratooperatedvehicle.com
上测试提交,我们将运行:
xxxxxxxxxx
$ openssl s_client -quiet -connect mail.ratoperatedvehicle.com:465
我们将得到几行OpenSSL输出,然后是来自提交服务器的消息:
xxxxxxxxxx
220 mail.ratoperatedvehicle.com ESMTP Postfix
到目前为止,这看起来像是正常的SMTP。介绍您正在连接的主机。
xxxxxxxxxx
ehlo desktop.mwl.io
250-mail.ratoperatedvehicle.com
250-PIPELINING
...
250 CHUNKING
在尝试其他任何操作之前进行身份验证。要使用PLAIN方法登录,请使用命令 auth plain
和预先计算的登录字符串。
xxxxxxxxxx
auth plain AG13bEByYXRvcGVyYXRlZHZlaGljbGUuY29tADk5
235 2.7.0 Authentication successful
要测试Microsoft友好的LOGIN方法,请输入 auth login
:
xxxxxxxxxx
auth login
334 VXNlcm5hbWU6
根据微软标准,Postfix已切换到base64。这将解码为 Username:
并需要您的用户名。输入它:
xxxxxxxxxx
bXdsQHJhdG9wZXJhdGVkdmVoaWNsZS5jb20=
334 UGFzc3dvcmQ6
Postfix会以base64 Password:
提示您。输入您的base64密码。
xxxxxxxxxx
VGhpc0lzRm9vbGlzaD8h
235 2.7.0 Authentication successful
无论您使用何种方法,获得“Authentication successful”消息意味着Postfix的提交过程可以与Dovecot的身份验证套接字通信,Dovecot可以识别您的密码。该系统的大部分功能正常工作。继续从此帐户发送电子邮件。
xxxxxxxxxx
mail from:<mwl@ratoperatedvehicle.com>
250 2.1.0 Ok
rcpt to:<mwl@mwl.io>
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
submit by hand.
.
250 2.0.0 Ok: queued as 77D1C81A6
quit
221 2.0.0 Bye
如果手动提交有效并且消息已发送,但您的花哨桌面客户端无法发送邮件,请尝试mutt。
正如mutt可以在不穿越网络的情况下使用IMAP一样,它也可以通过提交服务发送邮件。Mutt默认通过 sendmail(8)
传输邮件,但使用 smtp_url
选项,您可以指示它使用提交服务。
xxxxxxxxxx
set smtp_url = "smtp://*username*@*host*:*port*"
username 是您的IMAP用户名。 host 是运行提交服务的主机。 port 将是465。此选项应直接出现在IMAP配置之后,如下所示:
xxxxxxxxxx
set imap_user = mwl@ratoperatedvehicle.com
set spoolfile = imaps://mail.ratoperatedvehicle.com/
set folder = imaps://mail.ratoperatedvehicle.com/
set smtp_url = "smtps://$imap_user@mail.ratoperatedvehicle.com"
set ssl_starttls = no
我在 .muttrc
的前部定义了 $imap_user
,所以我在 smtp_url
中重用了它。我的邮件交换器是 mail.ratooperatedvehicle.com
。有了这个条目,我可以通过mutt发送邮件。
打开mutt并登录到您的IMAP邮箱。按 m
以撰写信息。系统会询问收件人。在另一台服务器上输入您的测试帐户——在我的例子中,mwl@mail.solveamurder.org
。然后mutt问了一个问题。当您输入一个时,mutt会将您转储到文本编辑器中。写一条短信并退出编辑器。Mutt将您放入一个屏幕,您可以在其中仔细检查收件人和主题。如果一切正常,按 y
发送邮件。根据您的杂种狗的包装方式,它可能会再次提示您输入密码,也可能不会。按 q
退出mutt。
如果你可以从服务器通过mutt发送邮件,但不能从你的花哨的桌面客户端发送邮件,要么你的客户端配置错误,有某种网络过滤器阻止你与服务器通信,要么你偶然发现了系统管理中常见的一种奇妙的边缘情况。深入挖掘原木。
邮件使用 Received
标头记录它们经过的每个SMTP服务器。看看你的测试消息头,你应该会看到这样的东西:
xxxxxxxxxx
Received: from [203.0.113.65] (ceodesktop.mwl.io [198.51.100.9]) by mail.ratoperatedvehicle.com (Postfix) with ESMTPSA id 36ACB49F29 for <mwl@ratoperatedvehicle.com>; Fri, 15 Dec 2023 12:36:06 -0500 (EST)
除了通常的日期和时间以及消息ID外,您还将看到没有任何NAT的原始IP(203.0.113.65)和服务器视为连接源的地址(198.51.100.9)。还有一个新的协议关键字ESMTPSA。不,没有一个全新的提交协议。此关键字表示邮件是如何提交的。ESMTPA表示邮件通过SMTP AUTH到达。ESMTPS表示邮件通过TLS加密的SMTP连接到达。ESMTPSA声明提交使用了TLS和SMTP AUTH。
现在,让我们设置管理多个用户。