步骤1

步骤1

我正在采取措施强化我的外发 postfix SMTP 服务器。我想防止用户伪造他们的发件人地址。

使用 Postfix SMTP 发送电子邮件时,可以通过三种方式识别发件人:

  1. 电子邮件本身有一个From:标题 - 定义在RFC 822
  2. 使用 SMTP 发送时,有一个MAIL FROM地址 - 定义在RFC 821
  3. 登录 Postfix (SMTP) 时,客户端指定一个用户名,该用户名也可以解释为发件人

查看手册,我相信拒绝发送者登录不匹配拒绝未列出的发件人将共同保证MAIL FROM电子邮件与 postifx 登录相关联。这就是上面的 2 和 3 匹配。

我不知道如何确保三者都匹配。如果结果只是重写消息而不是拒绝,我会很高兴,但两者都可以。然而,我看不出有什么办法可以做到这一点。我明白清理将添加一个丢失的From:标题,但我看不到任何方法可以检查并重写它。


感谢那些指出另一个类似的问题。不幸的是,这没有帮助,因为问题有两个答案,一个非常模糊,另一个似乎是错误的。

答案1

我花了一些时间研究这个问题,但找不到一种纯粹的后缀方法。建议使用的方法header_checks似乎不起作用,因为你不能(据我所知)将一个标题与另一个标题进行匹配。

可以编写自己的程序/脚本来为您执行检查,并将其用作内容过滤器


步骤1

下面是我用 Python 编写的简化版本。它从 stdin 读取电子邮件,MAIL from并将RECPT to地址作为参数。它检查From:邮件头,MAIL from如果不匹配,则替换它。我将其保存为/usr/share/mail_filter/filter.py

#! /usr/bin/python3

import sys
import subprocess
import email.parser
import email.policy

parser = email.parser.BytesParser(policy=email.policy.default)
message = parser.parse(sys.stdin.buffer)

envelope_from = sys.argv[1]
envelope_to = sys.argv[2]
# This if statement checks envelope from against message from
if message['From'].addresses[0].addr_spec != envelope_from:
    print(f"Replacing sender {message['from']} with {envelope_from}", file=sys.stderr)
    message.replace_header('From', envelope_from)

# sendmail -G -i -f sender@sender_domain.tld recipient@recipient_domain.tld
sendmail = subprocess.Popen(["/usr/sbin/sendmail", "-Gif", envelope_from, envelope_to], stdin=subprocess.PIPE)
with sendmail.stdin:
    sendmail.stdin.write(message.as_bytes())

# If sendmail returns an error, cascade it back to postfix
sys.exit(sendmail.wait())

第2步

更新/etc/postfix/master.cf

# added the -o content_filter...
smtp inet n       -       y       -       -       smtpd
  -o content_filter=filter:dummy

# Added this entire service
filter    unix  -       n       n       -       10      pipe
  flags=Rq user=filter null_sender=
  argv=/usr/share/mail_filter/filter.py ${sender} ${recipient}

请注意,这引用了步骤 1 中的脚本位置和步骤 3 中定义的用户

步骤3

filter我在一个组中添加了一个具有使用权限的OS 用户sendmail

useradd --system --gid postdrop filter

注意事项

根据指示简单过滤器(使用 传递sendmail)只能应用于 SMTP 客户端,无法过滤通过 sendmail 发送的消息。如果这对您来说是个问题,那么您需要编写一个高级内容过滤器

相关内容