我正在使用带有假期功能的 postfixadmin。support@mail-server.cc 是我用来通过 smtp auth 从不同服务发送电子邮件的常规邮件帐户 - 在这种情况下,在假期.pl 文件中用于发送外出消息用户发件人地址。一切都好,除非我启用 smtpd_sender_login_maps。
根据 postfix 文档,smtpd_sender_login_maps 可以有多个查找表。我正在尝试使用两个,mysql 和一个散列的 db 文件,其中我使用了 support@mail-server.cc 但使用了不同的 FROM 地址。他们每个人都在工作,但是当我指定他们两个时,只有第一个表在工作。
因此,当首先进行 mysql 查询时,只有来自 mysql db 的别名可以用作 FROM 地址:
smtpd_sender_login_maps =
mysql:/etc/postfix/virtual_alias.cf,
hash:/etc/postfix/allowed_sender_aliases.cf
Run Code Online (Sandbox Code Playgroud)
并且假期自动回复失败:
Jan 10 00:34:01 mx1 postfix/submission/smtpd[16856]: NOQUEUE: reject: RCPT from mx1.mail-server.cc[195.88.238.11]: 553 5.7.1 <alex@mail-server.cc>: Sender address rejected: not owned by user support@mail-server.cc; from=<alex@mail-server.cc> to=<alex5000@gmx.net> proto=ESMTP helo=<localhost.localdomain>
Run Code Online (Sandbox Code Playgroud)
当我首先指定散列的 db 文件时,假期自动回复正在工作,但用户不再能够使用他的帐户或别名发送电子邮件:
smtpd_sender_login_maps =
hash:/etc/postfix/allowed_sender_aliases.cf,
mysql:/etc/postfix/virtual_alias.cf
Run Code Online (Sandbox Code Playgroud)
日志条目:
Jan 10 00:49:40 mx1 postfix/submission/smtpd[26589]: NOQUEUE: reject: RCPT from unknown[192.168.200.100]: 553 5.7.1 <alex@mail-server.cc>: Sender address rejected: not owned by user alex@mail-server.cc; from=<alex@mail-server.cc> to=<alex5000@gmx.net> proto=ESMTP helo=<[192.168.200.100]>
Run Code Online (Sandbox Code Playgroud)
/etc/postfix/allowed_sender_aliases.cf 的内容:
@mail-server.cc support@mail-server.cc
Run Code Online (Sandbox Code Playgroud)
/etc/postfix/virtual_alias.cf 的内容:
# alias mapping
hosts = 127.0.0.1
user = vmail
password = xxxxx
dbname = mail
query = SELECT goto FROM alias WHERE address = '%s' AND active = '1'
Run Code Online (Sandbox Code Playgroud)
有什么问题还是真的只使用了第一个表?奇怪的是,当使用哈希表时,用户不能再发送电子邮件了。
经过一番折腾,我想我找到了答案。Postfix 在搜索时定义了一个“匹配”sender_login_maps作为任何成功的查找,但不考虑该查找的结果。
tl; dr:如果您打算使用 中所有映射的结果的联合smtpd_sender_login_maps,而不是仅采用第一个后续查找结果,则必须以某种方式组合这些映射(例如,通过 SQLUNION或unionmap)。
从本质上讲,这是一个令人惊讶的简单问题,由 Postfix 在进行映射查找时的短路行为引起。系好安全带,这是一个很长的答案......
来自关于发件人登录地图的 Postfix 文档:
smtpd_sender_login_maps(默认值:空)...
指定零个或多个“type:name”查找表,用空格或逗号分隔。
将按指定的顺序搜索表,直到找到匹配项。
http://www.postfix.org/postconf.5.html#smtpd_sender_login_maps
使用的目的smtpd_sender_login_maps是验证是否允许当前经过身份验证的 SMTP 用户从其邮件中的给定 FROM 地址发送。这是一项强大的功能,可以根据经过身份验证的 SMTP 用户的身份来限制客户端可以发送的地址。
smtpd_sender_login_maps 有很多用例,例如:
阻止用户以其他人的身份登录和发送消息
> Bob 可以发送为bob@example.com,但不能发送为alice@example.com
允许多个用户从他们都不拥有的单个共享地址发送
> Bob 和 Alice 都可以发送marketing@example.com
允许单个用户从他们拥有的多个地址
发送 > Alice 可以同时发送alice@example.com和发送alice.smith@example.com
允许管理员从多个地址发送消息(甚至为他人所有)
> Tracy,IT 管理员可以作为任何人发送.*@example.com
还有更多...(请记住,可以通过 TCP 套接字、SQL 查询、正则表达式等进行查找)
我们将特别调查这个用例:
- 允许管理员从多个地址发送消息(甚至为他人所有)
> Tracy,IT 管理员可以作为任何人发送.*@example.com
想象一下我们在邮件服务器上运行 Postfix 和 MySQL 的设置。有 3 个用户存储在数据库中,他们可以通过带有 postfix 的 SMTP 进行身份验证:
alice@example.com: 只能从alice@example.com,发送alice.smith@example.combob@example.com: 只能从bob@example.com,发送bob.jones@example.comadmin@example.com: 应该可以从任何 .*@example.com地址发送普通用户只能从他们的主要地址和他们的别名发送,但我们希望允许管理员能够无限制地伪装成任何发件人。在现实生活中,当用户需要.*@example.com仅使用一次 SMTP 登录就能够从多个地址发送信息时(例如,如果地址是动态生成的或属于其他用户),这种类型的设置非常有用。
正常的做法是使用smtpd_sender_login_maps这种设置来实现。
示例配置
/etc/postfix/main.cf:Run Code Online (Sandbox Code Playgroud)... smtpd_sender_login_maps = mysql:/etc/postfix/sender_logins.cf, pcre:/etc/postfix/sender_overrides.cf ...首先检查 MySQL,然后仅当 mysql 查找返回 0 结果时才检查 pcre。
/etc/postfix/sender_logins.cf(mysql):Run Code Online (Sandbox Code Playgroud)hosts = 127.0.0.1 user = postfix password = yourDatabasePasswordHere dbname = mail query = SELECT email FROM users WHERE email='%s'此映射检查数据库并返回给定 FROM addr 的普通 SMTP 用户,例如:
alice@example.com -> alice@example.com
bob.jones@example.com -> bob@example.com
/etc/postfix/sender_overrides.cf(pcre):Run Code Online (Sandbox Code Playgroud)/.*@example.com/ admin@example.com此映射匹配所有
@example.comFROM 地址并返回管理员 SMTP 用户,例如:
.*@example.com -> admin@example.com
用户期望的行为:
sender_login_mapsdb 中查找 FROM addrsender_login_mapsdb 中查找 FROM addr实际发生的情况:
sender_login_mapsdb 中查找 FROM addr问题在于 Postfix 不会检查两个映射并合并结果,而是在遇到返回任何 SMTP 用户的第一个匹配查找时停止查找过程。
如果返回的 SMTP 用户与当前经过身份验证的用户不匹配,它不会继续在下一个数据库中查找地址,它会立即查找DENY。
任何两个共享密钥的映射都可能发生相同的查找冲突,例如两个 mysql 数据库mysql:...,mysql:...,不一定只是pcrewith/.*/或/.*@example.com/。@example.com someuser@example.com第一个映射中的任何完全匹配或通配符匹配都将优先,并完全阻止查询第二个映射。
alice@example.com尝试从alice@example.com? 这工作正常,发送电子邮件是因为地址按预期与发件人匹配。
alice@example.com 通过 SMTP 登录以从 alice@example.comalice@example.com在smtpd_sender_login_maps返回中查找alice@example.comalice@example.com== SMTP 认证用户alice@example.comadmin@example.com尝试从alice@example.com? 这不起作用,电子邮件被拒绝,因为 SMTP 身份验证用户admin@example.com与第一个查找结果不匹配alice@example.com。
admin@example.com 通过 SMTP 登录以从 alice@example.comalice@example.com在smtpd_sender_login_maps返回中查找alice@example.comalice@example.com!= SMTP 认证用户admin@example.compostfix/smtpd[16645]: NOQUEUE: reject: RCPT from webmail.mailserver[192.168.1.5]: 553 5.7.1 <alice@example.com>: Sender address rejected: not owned by user admin@example.com; from=<alice@example.com> to=<bob@example.com> proto=ESMTP helo=<mail.example.com>smtpd_sender_login_maps =
pcre:..., # moving the pcre mapping above mysql makes it worse
mysql:...
Run Code Online (Sandbox Code Playgroud)
翻转映射的顺序,以便在 mysql 无法解决问题之前检查 pcre 文件。它甚至使情况变得更糟,因为包罗万象.*@example.com将掩盖 MySQL 中的所有真实用户,并阻止除admin@example.com发送电子邮件之外的任何用户。
当它alice@example.com在 pcre 文件中查找时,它admin@example.com作为唯一允许的用户返回,并在检查 mysql 数据库之前失败。
smtpd_sender_login_maps不相交如果映射中的键不包含任何重叠,则顺序无关紧要,任何与第一个数据库不匹配的查找都将按预期继续检查后续的。
列表中较早的映射不能有任何“catchall”或通配符键,否则它们将匹配所有内容并掩盖后面映射的结果。
UNION如果您使用mysql表类型进行smtpd_sender_login_maps映射,那么您可以在执行地址查找时控制 SQL 查询运行,并且您可以在 SQL 级别加入多个映射。
假设您的所有映射都可以在同一个 MySQL 数据库中访问,您可以使用如下UNION语句在 SQL 级别连接多个地址查找的结果:
main.cf:
smtpd_sender_login_maps = mysql:/etc/postfix/sender_logins.cf
Run Code Online (Sandbox Code Playgroud)
sender_logins.cf:
hosts = 127.0.0.1
user = postfix
password = yourDatabasePasswordHere
dbname = mail
query = SELECT email
FROM users
WHERE email='%s'
UNION SELECT destination
FROM aliases
WHERE source='%s'
UNION SELECT email
FROM users
WHERE wildcard_sending=1
Run Code Online (Sandbox Code Playgroud)
在这个例子中,我们将在 SQL 中设置admin@example.com为 have wildcard_sending=1,然后它将与每个查找结果以及普通用户和别名匹配一起返回,例如
alice.smith@example.com -> alice@example.com,admin@example.com
bob@example.com -> bob@example.com,admin@example.com
Run Code Online (Sandbox Code Playgroud)
unionmap用于组合多个映射如果您使用的是 Postfix 3.0 或更高版本,您或许可以尝试使用新unionmap功能,该功能会一次查找所有映射并将结果连接在一起。
smtpd_sender_login_maps = unionmap:{
mysql:/etc/postfix/sender_logins.cf,
pcre:/etc/postfix/sender_overrides.cf }
Run Code Online (Sandbox Code Playgroud)
使用此设置,mysql 结果将与 pcre 查找结果连接,例如
alice.smith@example.com -> alice@example.com,admin@example.com
bob@example.com -> bob@example.com,admin@example.com
Run Code Online (Sandbox Code Playgroud)
有关更多信息,请参阅http://www.postfix.org/DATABASE_README.html#types unionmap。
因此,这里的“匹配”一词是最狭义的:只是匹配的地址,而不是匹配的(地址、登录名)对。此外,当找到匹配的地址时,查找链会立即停止,并做出二元拒绝/接受决定。
| 归档时间: |
|
| 查看次数: |
1858 次 |
| 最近记录: |