Postfix sasl 密码数据库映射文件的正确格式是什么?

Postfix sasl 密码数据库映射文件的正确格式是什么?

可以请求 postfix 从数据库获取其中继服务器的 sasl 登录信息。然后我让此中继服务器获取相同的登录信息。

我们如何格式化这个配置文件以便正确获取?

我们知道这些信息:

  1. 中继的域名。
  2. 邮箱的用户名。
  3. Postfix 服务器上的域名(可能有多个)。

现在,仅包含密码的纯文本文件将被格式化如下(每行),假设使用密码mailbox发送:domain2mailpass

smtp.relay.tld [email protected]:mailpass

我验证了纯文本文件方法适用于数据库中的特定用户和密码。现在我想使用 .cf 文件连接数据库。

给定一个域表如下1

+----+----------+-------------+----------+
| id | username |   domain    | password |
+----+----------+-------------+----------+
|  1 | mailbox  | domain2.tld | mailpass |
+----+----------+-------------+----------+

一般来说,这样的文件的格式如下;

user = sqluser
password = dbpass
hosts = localhost
dbname = maildb
query = SELECT password FROM accounts WHERE username = '%u' AND domain = '%d'

我不确定“查询”参数中到底要放什么。官方文档对此非常糟糕:它声明可以使用 SQL 数据库进行配置,但根本没有说明如何配置,也没有给出具体示例。

现在我尝试使用简单的方法;创建一个查询,该查询仅返回与纯文本文件中的行完全相同的值。我还尝试返回该行的各种子集,但没有成功。每次尝试都只会生成“访问被拒绝”错误。

1:我知道以这种方式将实际用户的密码存储在数据库中是一种馊主意。这里使用的密码仅仅是为了两个特定服务器之间的通信。

想要使用数据库的原因是可移植性和可扩展性的结合。例如,当且仅当某个域想要使用多个邮件服务器,或者迁移到另一个电子邮件提供商时。不只使用一个密码的原因是为了能够区分关注点(每个用户都配置了一个单独的中继密码,他们自己并不知道,但每个邮件服务器上的 postfix 用户通过查看某个数据库表知道该密码。这是一种与 openstack keystone 相当的机制,但复杂程度要低得多)。

进一步挖掘:启用 L4 级日志记录并查看服务器的连接记录,它似乎从未发送过 AUTH 消息(因此它甚至没有弄清楚如何“找到”用户)。可以在邮件日志中找到以下消息(域名等已删除);

postfix/smtp[6494]: maps_find: smtp_sasl_password_maps: smtp.relay.tld: not  found
postfix/smtp[6494]: maps_find: smtp_sasl_password_maps: smtp.relay.tld:587:  not found
postfix/smtp[6494]: smtp_sasl_passwd_lookup: no auth info found 
(sender=`[email protected]', host=`smtp.relay.tld')

但是,执行这个命令:

postmap -q [email protected] mysql:/etc/postfix/mysql-map.cf

生产

smtp.relay.tld [email protected]:mailpass 

换句话说,配置是有效的,但是后缀程序正在执行一些奇怪的查询以便从数据库中获取密码,并且没有指定实际上是什么,也没有记录。

答案1

有两件事是必要的:

首先,smtp_sender_dependent_authentication = yes必须在 postfix 主配置文件中启用该选项(通常位于/etc/postfix/main.cf)。如果没有此选项,服务器将仅根据中继主机的域名进行搜索,该域名对于每个用户都相同。

其次,正确的查询应该是这样的:

query = SELECT CONCAT(username, "@", domain, ":", password) FROM accounts \
        WHERE username = '%u' AND domain = '%d'

注意:配置文件不支持这种方式的多行;因此删除 \ 和换行符

答案2

只是在这里做一个大胆的猜测(我没有混合 Postfix 和 SQL),但我将从以下内容开始:

  1. 电子邮件地址的“本地部分”不会自动成为中继身份验证的“用户名”。因此,即使在你的数据库中它们都是相同的,Postfix 无法自动做出这种假设,因此用户名字段无论如何都必须归还。

  2. 所有 Postfix 表都以相同的方式执行查找:一个输入产生一个输出,并且 Postfix 核心实际上并不关心特定表后端是否支持多列。我认为它需要单个字符串并在所有情况下以相同的方式解析它。

根据第2点,如果纯文本表存储[email protected]:mailpass,那么SQL查询应该可能返回以相同方式格式化的单个列。所以我会尝试这样做:

query = SELECT CONCAT(username, ":", password) FROM accounts WHERE username = '%u' AND domain = '%d'

但如果这不正确,那么应该使用两个单独的列:

query = SELECT username, password FROM accounts WHERE username = '%u' AND domain = '%d'

相关内容