第六章:数据库后端

第六章:数据库后端安装 PostfixAdminPostfixAdmin用户数据库设置Dovecot 帐户作者web服务器和PHP设置PostfixAdmin设置密码PostfixAdmin后端配置PostfixAdmin设置为数据库配置 PostfixPostfix 代理映射Postfix数据库配置main.cf 和数据库为数据库配置Dovecot连接信息迭代查询密码查询用户查询向Dovecot介绍数据库测试Dovecot数据库

文本文件配置对于很少更改的设置非常有效。如果你的邮件系统真的只适合你,那么文本文件可能也没问题。然而,当你有更多的用户或更动态的环境时,你需要更灵活的管理。这意味着一个数据库。以及管理该数据库的前端,因为常规运行原始SQL命令需要记住数据库结构,这会消耗大脑空间,更好地用于其他事情。别的。

开始之前,请验证您的Postfix安装是否支持您选择的数据库。运行 postconf -m 列出所有支持的查找表类型,并检查所选的数据库引擎。还要验证 proxy 是否是受支持的查找表。

许多人编写了数据库驱动的Postfix管理系统。其中一些甚至是足够的。本书将使用PostfixAdmin(https://postfixadmin.github.io/postfixadmin/),但主要是为了说明数据库支持的Postfix和Dovecot。我们不会讨论web界面,因为web界面经常变化。一旦你从通过文本文件管理Postfix迁移,你最常见的问题是“他们在哪里隐藏了此设置的菜单?”

PostfixAdmin的一个令人愉快的功能是,它允许您将域的控制权委托给用户。如果你有一个半技术伙伴想要为他们的域名发送电子邮件,你可以给他们一个帐户,让他们负责。一个不愉快的PostfixAdmin功能是,它允许你将域名的控制权委托给用户。他们会感到困惑,随意更改设置,无可救药地扰乱他们的域名,并乞求帮助。我们不会介绍将域的控制权委托给其他用户,但web界面使其变得简单明了。不过,我们将提到功能何时与委派域相关。

安装 PostfixAdmin

PostfixAdmin在PHP和数据库上运行。我们将使用MariaDB,如第0章所述。但是,在安装之前,请检查PostfixAdmin网站上的当前版本,并将其与操作系统包存储库中的版本进行比较。与所有系统管理软件一样,PostfixAdmin对安全性很敏感,安装过时的版本是向入侵者和垃圾邮件发送者提供资源的好方法。如果该包是最新的,请使用它;如果没有,请从网站上获取最新的稳定版本。

您可以在他们的网站上找到安装PostfixAdmin的官方最新说明,许多软件包都包含这些官方说明。在本书中发布一个演练会邀请他们更改整个过程,但我们会尝试一下。

PostfixAdmin用户

PostfixAdmin有四层用户。每个级别的用户只能看到与他们相关的功能。

数据库设置

PostfixAdmin需要一个数据库、一个数据库用户和该用户的密码。在开始之前把这些写下来。我们将使用数据库名称 slurry 、用户 garbage 和密码 MailIsTheWorst!1

创建数据库和用户,然后将两者联系在一起。以管理员身份登录数据库并运行以下命令:

我们将通过PostfixAdmin界面设置数据库表,但不要丢失记录数据库信息的注释。

Dovecot 帐户作者

Dovecot保存统计数据和日志,PostfixAdmin需要访问权限才能添加到其中。Dovecot的默认配置创建Unix套接字 /var/run/dovicot/stats-writer ,以接收Dovecot程序的报告。该套接字通常只能由 root 用户和组 dovecot 访问,并且只有他们可以写入套接字。您的web服务器可能以类似wwwwww-data 的方式运行,因此无法连接到套接字。互联网上充斥着让套接字世界变得可写的可怕建议。不要那样做。永远不要那样做。

授予具有组权限的访问权限。不,不要将 www 添加到 dovecot 组!这使得网络服务器对Dovecot的内部有太多的访问权限。创建一个包含 dovecotwww 的新组,然后将该组权限授予套接字。我创建了组 mailglue 。这是一个 doveco.conf 代码片段,用于更改套接字上的组所有权:

这授予了PostfixAdmin所需的访问权限,仅此而已。

web服务器和PHP设置

PostfixAdmin包应该引入所有必要的PHP模块,尽管您可能需要验证它是否包含所选数据库引擎的模块。配置您的web服务器以解析PHP并安装您喜欢的任何PHP加速器。验证 php.ini 是否设置了与主机相同的时区。否则,PostfixAdmin登录将失败。

web界面是指web服务器。如果您正在使用ACME获取X.509证书,那么您可能已经拥有了一个。如果没有,就买一个。让未加密的站点重定向到受TLS保护的站点。

该软件包将在您的磁盘上的某个位置安装PostfixAdmin。找出它在哪里。对于我的主机,它是 /usr/local/www/postfixadmin 。此目录包含配置文件、函数等。子目录 public 包含PostfixAdmin的web部分,必须在您的网站上的某个地方可用,或者作为其自己的虚拟主机。我避免使用明显的位置,比如https://example.com/postfixadmin,更喜欢对我有意义但对外人不透明的地方。这是一个Apache httpd.conf代码片段,可以在我的网站上访问PostfixAdmin:

重新启动您的web服务器,并验证您在所选的URL上是否获得了PostfixAdmin页面。该页面将充满错误。在修复它们之前,不要尝试配置PostfixAdmin。

PostfixAdmin设置密码

为了保护新安装,PostfixAdmin要求您在安装前定义安装密码。虽然其他所有密码都会进入数据库,但此密码会进入配置文件。如果您还没有数据库,则无法将密码存储在数据库中。

设置密码必须以哈希形式存储。您可以使用PostfixAdmin设置页面生成哈希,或者只使用 php(1) 命令:

输出末尾没有换行符,因此您的命令提示符将附加到末尾。在没有提示的情况下复制哈希,并在配置PostfixAdmin之前将其放在手边。

PostfixAdmin后端配置

PostfixAdmin主目录有一个配置文件 config.inc.php ,其中包含所有选项及其默认设置。升级会替换它,因此您所做的任何更改都会消失。相反,创建 config.local.php 并将您的配置放入其中。您的本地配置必须包括:

配置文件使用标准的PHP语法。以下是使用本章早些时候创建的数据库、我们刚刚生成的设置密码的哈希值以及第5章中选择的盐水SHA512算法的最小配置:

database_typedatabase_hostdatabase_name 选项告诉PostfixAdmin如何查询数据库,在哪里找到它,而 database_userdatabase_password 提供身份验证凭据。

encrypt 选项选择一种算法来对数据库的密码记录进行哈希运算。我们正在使用Dovecot工具和Blowfish算法。您可以稍后更改算法,但与系统密码文件一样,它只会影响新帐户和更改的密码。现有的哈希值不会改变。

setup_password 选项需要以前生成的密码哈希。

configured 选项告诉PostfixAdmin设置例程,系统管理员已经查看了配置选项并设置了非默认选项,因此可以安全地初始化数据库。

有了这个基础设施设置,我们可以设置PostfixAdmin。

PostfixAdmin设置

浏览到PostfixAdmin目录中的 setup.php 页面。输入设置密码。PostfixAdmin将检查您的环境,创建数据库表,并验证它是否可以访问所需的一切。

在继续之前,您必须解决任何错误。你可能会犯什么样的错误?这完全取决于您的操作系统和软件包维护者。仔细阅读错误。PostfixAdmin试图提供帮助,并为错误提供上下文,但有时该上下文与您的特定错误无关。一些错误可以通过 config.local.php 选项来解决。有关可用选项及其默认设置的完整列表,请参阅 config.inc.php

许多PostfixAdmin安装程序都希望运行 dovepw(1) 命令,但Dovecot将其替换为 doveadm pw。检查 config.inc.php 会发现 dovecotpw 选项,您可以使用该选项来更正此问题。

doveadm(1) 命令期望解析 doveco.conf ,包括它引用的所有文件。这就是为什么第5章中的TLS配置是容错的。

一旦清除了所有错误,只留下关于不使用的数据库支持的警告,您就可以创建Superadmin帐户。这基本上是PostfixAdmin的 root 。这是您将用于创建虚拟主机和第一个用户的帐户。创建用户,然后以他们的身份登录。

作为Superadmin,您可以创建一个域,然后在该域中创建一个用户。此时,数据库尚未连接到Postfix,因此您将看不到您的测试域或您在第4章中创建的用户。在这里重建它们。建议的限制是将域的控制权委托给其他用户。你可以将它们设置为你喜欢的任何值。我将添加域名 ratoperatedvehicle.com 和用户 mwl@ratoperatedvehicle.com 。PostfixAdmin允许您定义密码有效期,但研究表明,计划的密码轮换会降低安全性。将有效期设置为0 不需要密码轮换。

2017年NIST文件800-63b附录A详细讨论了为什么密码过期是不好的,但我预计企业不会改变他们的做法,直到几乎永远不会。此外,从2023年开始,PCI DSS 4.0宣布密码必须每90天更改一次。我们都注定要失败。

同时创建第二个帐户。您将使用它来验证Postfix是否正在从数据库读取,而不是从文本文件读取。我将添加 drivers@ratoperatedvehicle.com

此时,PostfixAdmin已为Postfix准备好了。如果你愿意,现在也是研究数据库的好时机。查看存在哪些表以及它们如何存储数据。当你感到舒适时,继续进行Postfix。

为数据库配置 Postfix

Postfix的文本配置文件格式简单但严格。信息必须以一定的顺序出现,并用不可转让的标签标记。用数据库替换它们意味着要精心制作再现这些配置文件的查询。Postfix接受微小的更改,例如不需要分隔符,但总体而言,数据库查询必须与它们替换的文本文件相似。

请注意,用数据库“替换”文本文件有点用词不当。如果将Postfix的虚拟主机存储在数据库中,Postfix仍将有一个外部虚拟主机文件。该文件包含连接到数据库的说明和生成虚拟主机表所需的查询。但是,添加和删除条目不会更改这些文件。

Postfix 代理映射

代理映射——proxymap

繁忙的Postfix服务器可能会不断查询数据库。即使是小型服务器偶尔也会受到攻击。在现代硬件上,启动单个数据库连接的计算成本并不高,但如果你的主机每次将电子邮件从堆栈的一个部分移动到另一个部分时都启动一个新的数据库查询,那么它们就会加起来。Postfix使用 proxymap(8) 聚合数据库查询。proxymap 程序打开一个数据库连接,并处理各种Postfix程序的所有查询。

配置条目中的单词 proxy 告诉Postfix通过代理路由这些请求。

Postfix还可以使用 proxymap(8) 绕过指定表的chroot限制,并聚合写入以避免文件锁定问题。

默认情况下,master.cf 中启用了Proxymap。

Postfix数据库配置

PostfixAdmin在文件 POSTFIX_CONF.txt 中包含有关配置Postfix以与其数据库通信的信息。该文件不是让您手工制作Postfix配置文件,而是一个bash脚本,它要求您提供数据库信息,并将建议的文件写入临时目录。(这些文件与MySQL兼容,如果您使用的是Postgres或SQLite,则需要对查询字符串进行细微更改。)大多数软件包都将 POSTFIX_CONF.txt 安装在文档目录中。

这是写入文件的临时目录。然后系统会提示您输入数据库详细信息:

查看其中几个文件。您将看到数据库连接信息,然后是一个生成Postfix所需信息的查询。

这些文件包含纯文本数据库密码,因此世界不应该读取它们。我也不希望Postfix能够写入这些文件,但它必须能够读取它们。创建 /etc/postfix/sql 目录,并赋予其适当的保护权限:

这些文件在Unix允许的范围内是安全的。现在配置Postfix以读取它们。

main.cf 和数据库

我们使用 main.cf 选项 virtual_mailbox_domainsvirtual_alias_mapsvirtual_mailbox_maps 定义了虚拟域。将所有这些更改为使用数据库支持的配置。PostfixAdmin为我们创建的数据库配置文件的名称与它们所属的选项相似。不要盲目遵循我的指示;请务必查看 POSTFIX_CONF.txt 的顶部,了解您的版本说明。(它们会很接近,但会发生一些小变化。)

virtual_mailbox_domains 选项列出了此主机接受邮件的虚拟域。将其指向文件 mysql_virtual_domain_maps.cf

让我们把它拆开。代理语句告诉Postfix通过 proxymap(8) 聚合数据库查询。mysql 语句通知Postfix此数据源与MySQL兼容。然后,我们就有了包含查询详细信息的文件的路径。

virtual_alias_maps 选项为虚拟主机提供别名。别名有几种类型,可以通过使用多个数据库表来最好地表达。

virtual_mailbox_maps 中的邮箱定义可以放入两个数据库表中,一个用于帐户,另一个用于与这些帐户绑定的别名。

查看错误日志并重新启动Postfix。如果你没有看到异常的错误消息,它应该可以工作。启动你的测试邮件客户端,看看你是否可以将邮件发送到你的主测试地址。

如果有效,请将邮件发送到您在PostfixAdmin中创建的全新帐户。它应该反弹,但反弹消息应包含Dovecot错误。请记住,必须在Postfix和Dovecot中配置虚拟帐户。我们已经告诉Postfix检查数据库中的用户帐户。带有Dovecot错误的反弹意味着Postfix接受了该消息,但Dovecot没有。Postfix正在读取数据库。

这让我们可以配置Dovecot。

为数据库配置Dovecot

Dovecot使用具有预认证信息的密码数据库和具有后认证信息的用户数据库。虽然Dovecot使用Unix兼容的密码文件,但当它查询数据库时,它只需要与每个函数相关的信息。

为您的数据库配置创建一个单独的配置文件 /etc/dovecot/dovecot-sql.conf 。由于此文件包含安全敏感的密码,因此它应该由用户 root 和组 dovecot 拥有,而不是全世界可读的。

SQL配置文件需要四个部分:连接信息、密码查询、用户查询和迭代查询。

连接信息

Dovecot需要知道数据库信息、数据库类型和默认密码哈希算法。首先用 connect 语句定义数据库:

connect = host=hostname dbname=database user=username password=password

填写我们数据库的信息。您不需要转义密码中的特殊字符,但要仔细测试空格:

使用 driver 选项设置数据库类型。Dovecot可以使用Postgres、SQLite或MySQL:

方便命名的 default_pass_scheme 选项设置默认密码哈希算法。这个堆栈中的其他所有内容都使用Dovecot的Blowfish支持,但我们在Dovecot,所以我们不必指定应用程序:

之后,您将开始使用SQL。Dovecot的文档提供了MySQL和Postgres的示例SQL查询。只要你严格遵循他们推荐的设置,它们就可以正常工作。没有任何应用程序的推荐与任何其他应用程序的建议完全匹配。没关系。修改查询并不可怕。

迭代查询

迭代查询返回所有活动用户的列表。这在PostfixAdmin安装中是相当标准的。

登录MySQL客户端并自己运行此查询,以验证其是否有效。

密码查询

密码查询应返回特定的用户名和密码哈希值。它可以使用第3章中讨论的所有Dovecot变量,如 %u%d 等。Dovecot用户名是完整的电子邮件地址,或 %u 。(查询结果不会检查这些变量,所以如果你的用户名碰巧包含 %d ,它就不会被扩展。)

次要的问题是用户名字段必须称为“user”,哈希 “password”。PostfixAdmin数据库将用户存储在“username”字段中。SQL查询必须使用别名来重新映射查询。PostfixAdmin设计者无法使数据库列名与Postfix和Dovecot的期望相匹配。

登录到您的数据库,并使用 %u 的测试用户运行此查询。如果您没有更改PostfixAdmin数据库,它应该按原样工作。用户查询更麻烦。

用户查询

用户查询需要返回一个格式正确的用户数据库条目,包括主目录、用户和组ID以及任何配额。这部分取决于您选择将虚拟邮箱存储在何处以及哪些系统用户拥有它们。该示例提供了您需要的所有SQL逻辑,但您必须更新系统的常量。

这是一个查询骨架:

mailbox-location 是存储邮箱的目录。这与Postfix的 main.cf 中的 virtual_mailbox_base 相同。我的安装使用 /vhosts 。Dovecot将用户的邮件目录作为变量 maildir 提供。查询将这些文件粘贴到磁盘上用户文件的路径中。

owner-uidowner-gid 是拥有邮箱文件和目录的系统用户。

这是本书中使用的配置的最后一个查询:

一定要和你的测试用户一起手动运行你的查询。根据您的系统检查路径、UID和GID。

将这三个查询放在 dovecot-sql.conf 中。

向Dovecot介绍数据库

doveco.conf 中的 passdbuserdb 选项告诉Dovecot如何查找用户和密码数据库。删除指向密码文件的条目。当您切换到使用实际数据库时,两者都可以使用相同的配置。

driver 选项告诉Dovecot使用SQL, args 选项提供配置的路径。重新启动Dovecot,您就可以开始了!

除了你搞砸了什么。

测试Dovecot数据库

使用 tail -f 查看Dovecot日志。在本地系统上打开 mutt 并尝试使用IMAP登录。它应该需要您在PostfixAdmin的web界面中输入的密码。如果您的查询不正确或存在其他配置错误,您将无法登录,并将收到一条日志消息。

如果有效,请使用 mutt 向您通过PostfixAdmin创建的新测试帐户发送一封邮件。日志应显示已交付。

一旦您可以在本地系统上将消息从一个帐户发送到另一个帐户,请将新的测试帐户添加到您的桌面客户端。桌面客户端应该能够登录并下载该测试消息。这将验证IMAP是否正常工作。

您的桌面客户端应该能够从服务器的一个帐户向其他帐户发送邮件,证明基本的SMTP仍然有效。如果该功能正常,请通过让该帐户在您的其他测试主机上邮寄一个帐户来进行测试提交和中继。Postfix是否抱怨您的帐户不拥有您的帐户?您可能将 smtpd_sender_login_maps 选项设置为密码文件,而不是像我告诉您的那样设置 $virtual_alias_maps

当任何测试失败时,立即停止。阅读日志。在继续之前调试问题。

一旦数据库支持的邮件系统的所有部分都工作正常,您就可以开始准备您的邮件系统以面对世界。