如何使用 Postfix 进行垃圾邮件陷阱?

sh-*_*eta 6 freebsd postfix spam openbsd

如何使用 Postfix 设置垃圾邮件陷阱,以防止发送到受困地址的客户端向我发送更多垃圾邮件?

sh-*_*eta 6

概述

贝叶斯过滤器、模式匹配和 RBL 都是打击垃圾邮件的一部分。此设置旨在增强而不是替换它们。

请注意,我不是灰名单。灰名单在理论上很好,但实际上对您的用户来说非常烦人。有些人在这方面取得了巨大的成功。我不是那些人中的一员。

我所做的是设置一些电子邮件地址(我有大约 10,000 个,但您可以使用几百个)来充当垃圾邮件陷阱。这些地址的列表与各种高流量站点离散链接,机器人会在这些站点找到它们,但人们不会。这些地址被收集起来,卖给垃圾邮件发送者,现在我知道垃圾邮件会从哪里进来。

Postfix 被配置为将消息重定向到这些地址中的任何一个到我的 spamtrap 脚本,该脚本将它们添加到 PF 中的表中,以便来自该客户端的任何进一步消息最终进入我的 tarpit。

优点:

  • 零误报率(或尽可能接近,至少)
  • 资源便宜
  • 在第一次违规后在防火墙层阻止垃圾邮件发送者
  • 自我修复(被困地址在 24 小时后过期)

缺点:

  • 不是即插即用
  • 相当多的活动部件

如何?

您的邮件服务器必须能够运行 PF 和 spamd。据我所知,这意味着 OpenBSD 或 FreeBSD。我确信这些说明可以适应 Linux 及其防火墙的风格,但这超出了我的回答范围。

我已经为 FreeBSD 编写了这个。OpenBSD 用户应该能够主要通过更改路径来适应这些步骤。

最后,这就是 Postfix 2.5+ 的全部内容

表 <spamd> 持久化
表 <local-whitelist> 持久化文件“/usr/local/etc/spamd/local-whitelist.txt”
  • 从端口安装 spamd
  • 创建 /usr/local/etc/spamd/local-whitelist.txt。PF 将读取此文件以生成 <local-whitelist> 表。我建议参考http://www.greylisting.org/whitelisting.shtml获取永远不应该被 tarpitted 的地址。一个示例文件:
127.0.0.1
10.0.0.0/8

# 亚马逊
207.171.168.0/24
207.171.180.0/24
207.171.187.0/24
207.171.188.0/24
207.171.190.0/24

#美国在线
64.12.137.0/24
64.12.138.0/24
152.163.225.0/24
205.188.139.0/24
205.188.144.0/24
205.188.156.66
205.188.157.0/24
205.188.159.7

# 苹果
17.254.6.0/24

#易趣
66.135.197.0/24
66.135.209.0/24

# gmail
64.68.80.0/21
64.233.160.0/19
64.233.162.192/28
64.233.170.192/28
64.233.182.192/28
64.233.184.192/28
66.249.82.192/28
66.249.92.192/28
66.249.64.0/19
66.102.0.0/20
70.89.39.152/29
70.90.219.48/29
70.90.219.72/29
72.14.192.0/18
74.125.0.0/16
209.85.128.0/17
216.239.32.0/19
216.239.56.240/28

# postini
63.146.199.13/32
63.146.199.14/32
63.71.11.123/32
63.71.11.124/32
64.18.0.0/20
67.114.133.222/32
68.123.185.46/32
74.125.148.0/22
204.14.232.0/22
207.126.144.0/20
208.111.151.5/32
208.74.204.5/32

#天网.be
195.238.2.0/24
195.238.3.0/24

#雅虎
64.94.237.0/24
66.163.160.0/19
66.196.64.0/18
66.218.64.0/19
66.218.66.0/24 
66.218.67.0/24
66.218.69.0/24
69.147.92.0/24
73.30.0.0/16
74.6.0.0/16
206.190.32.0/19
216.34.77.0/25
216.136.226.0/24
  • 重装PF

  • 创建 /usr/local/scripts/get-spamtrapped:

#!/bin/sh
/usr/local/sbin/spamdb | grep TRAPPED | cut -d '|' -f 2
Run Code Online (Sandbox Code Playgroud)
  • 创建 /usr/local/etc/spamd/spamd.conf。我建议也使用 nixspam 和 ualbert.ca 列表,但至少您需要 spamtramped 和 override 列表。(注意:我知道 PF 的 rdr 规则覆盖是多余的 - 我移动的东西足够多,我想要这种双重保护):
全部:uatraps:覆盖:nixspam:覆盖:垃圾邮件陷阱:覆盖:

#阿尔伯塔大学greytrap命中。
# 地址会在其行为不端后保留 24 小时。
uatrap:\
        :黑色的:\
        :msg="您的地址 %A 已将邮件发送到 ualberta.ca 垃圾邮件陷阱\n\
        过去 24 小时内":\
        :方法=http:\
        :file=www.openbsd.org/spamd/traplist.gz:

# Nixspam 最近的来源列表。
# 镜像自 http://www.heise.de/ix/nixspam
垃圾邮件:\
        :黑色的:\
        :msg="您的地址 %A 在 nixspam 列表中\n\
        有关详细信息,请参阅 http://www.heise.de/ix/nixspam/dnsbl_en/":\
        :方法=http:\
        :file=www.openbsd.org/spamd/nixspam.gz:

# 被困 IP - 所以我们可以在不使用灰名单的情况下阻止它们
垃圾邮件:\
        :黑色的:\
        :msg="您的地址 %A 已将邮件发送到此服务器上的垃圾邮件陷阱\n\
        过去 24 小时内":\
        :方法=执行:\
        :file=/usr/local/scripts/get-spamtrapped:

覆盖:\
        :白色的:\
        :方法=文件:\
        :file=/usr/local/etc/spamd/local-whitelist.txt:
  • 将 spamd 设置为在启动时运行。请注意,您不是在仅黑名单模式下运行,并且当有人尝试发送到黑名单时,您会抛出 5xx 错误。前者是 spamdb 将处理存储/过期被困地址。后者是礼貌。添加到/etc/rc.conf:
obspamd_enable="是"
obspamd_flags="-5"
  • 启动垃圾邮件:/usr/local/etc/rc.d/obspamd start

  • Cronjob 在仅黑名单模式下每小时运行一次 spamd-setup。黑名单模式强制它更新 <spamd> pf 表而不是 spamd 的内部表。由于 spamd 只是缓送和存储数据,因此其他所有内容都需要在 PF 中。(用您希望它运行的任何一分钟替换 XX)

# 垃圾邮件设置
XX * * * * root /usr/local/sbin/spamd-setup -b
  • 在您的机器上创建一个 spamtrap 用户。我给他一个主目录以供将来扩展:
$ sudo pw useradd spamtrap -s /sbin/lologin -d /home/spamtrap -m -c "垃圾邮件收集器"
  • 创建 /usr/local/scripts/spamtrap:
#!/usr/local/bin/bash

# rudimentary checking - more complex checking will be done by 
# the pfctl and spamdb commands
ADDRESS=${1%%[!0-9.]*}
if [[ ! ${#ADDRESS} = ${#1} ]]
then
        echo "Invalid characters in IP address"
        exit 1
fi
if [ ! ${ADDRESS} ]
then
        echo "Usage: $0 <address>"
        exit 1
fi



/usr/local/sbin/spamdb -t -a ${ADDRESS}
if [ "$?" -ne 0 ]
then
        echo "Failed to add ${ADDRESS} to spamdb"
        exit 1
fi
/sbin/pfctl -qt spamd -T add ${ADDRESS}
if [ "$?" -ne 0 ]
then
        echo "Failed to add ${ADDRESS} to pf"
        exit 1
fi
/usr/bin/logger -t spamtrap "Spamtrap caught ${ADDRESS}"
Run Code Online (Sandbox Code Playgroud)
  • 在 Postfix 的 /usr/local/etc/postfix/master.cf 中配置一个新的传输服务。X 标志告诉 Postfix 考虑邮件的最终传递,以便垃圾邮件发送者收到成功邮件。请注意用户 - 它需要对脚本的 sudo 访问权限。
# 垃圾邮件陷阱
垃圾邮件捕手 unix - nn - - 管道
  flags=X user=nobody argv=/usr/local/bin/sudo /usr/local/scripts/spamtrap ${client_address}
  • 添加到sudoers:
没有人 ALL= NOPASSWD: /usr/local/scripts/spamtrap
  • 创建一个传输规则,将发送到 spamtrap@localhost 的所有邮件发送到 spamtrapper 服务。请参阅“postconf transport_maps”以了解要编辑的文件。默认为 /usr/local/etc/postfix/transport:
spamtrap@localhost spamtrapper
  • 重新启动后缀。向 spamtrap@localhost 发送几条消息,并验证发送客户端是否已加载到 spamdb 和 <spamd> pf 表中。
$ echo "测试" | 垃圾邮件陷阱@localhost
$ spamdb | grep 127.0.0.1
被困|127.0.0.1|1253655172
$ sudo pfctl -qt spamd -T 显示
   127.0.0.1
$

每个垃圾邮件地址都需要做两件事。首先,它必须解析为实际邮箱,以便在 SMTP 对话期间不会被拒绝。我使用别名为 spamtrap@localhost 的虚拟用户。其次,它需要匹配 Postfix 中的 check_recipient_access 规则并重定向到 spamtrap@localhost,这样收件人列表中的合法用户就不必看到它。我是如何做这部分的:

  • 添加到/usr/local/etc/postfix/main.cf:
virtual_maps = hash:/usr/local/etc/postfix/spamtrap_maps
smtpd_recipient_restrictions = check_recipient_access 哈希:/usr/local/etc/postfix/spamtrap_recipients
  • spamtrap_maps 的格式:
spamtrappedaddress@domain.tld spamtrap
  • spamtrap_recipients 的格式:
spamtrappedaddress@domain.tld 重定向 spamtrap@localhost
  • 将这些文件添加到您的 Makefile 中并进行测试。

此时,所有向您的垃圾邮件陷阱地址发送邮件的客户端都应添加到 spamdb 和 <spamd>。尚未向 spamd 发送任何内容。要使整个阻塞机制生效,请添加到 /etc/pf.conf 并重新加载 pf:

没有从 <local-whitelist> 到端口 25 的 rdr proto tcp
rdr 将 proto tcp 从 <spamd> 传递到端口 25 -> 127.0.0.1 端口 8025

就是这样。

可能的扩展

  • 修改 spamtrap 脚本以在贝叶斯垃圾邮件语料库中存储邮件副本是微不足道的。

  • 如果您订阅了任何 RBL rsync 服务,那么将这些消息的反弹卸载到垃圾邮件是很简单的。