你好,世界!
互联网是人类最伟大的发明之一。它让人能够足不出户就可以了解世界各地;它让人们相隔万里也能够互相通信;它让自由软件的理念和实践历久而弥新。然而,网络也带来了隐私和安全的困扰。
2025年初,自由软件基金会(FSF)的软件开发平台 Savannah 遭遇了一场持续数月的大规模攻击。攻击者并非为了破坏,而是为了“收集数据”——他们利用一个由数万台被感染的智能电视组成的“僵尸网络”,疯狂地爬取代码仓库,用来训练他们的大语言模型。这场攻击导致 Savannah 的 IP 黑名单一度达到了500万个。
这不是某个遥远的大公司才会遇到的麻烦。任何拥有自己网站、博客或家庭服务器的人,都可能成为类似攻击的目标。也许只是一次密码暴力破解,也许是一场突如其来的流量洪水。我们无法控制攻击者,但我们可以学习如何应对。而 FSF 系统管理员在对抗这场攻击中使用的工具和方法,普通用户经过学习也完全能够掌握。
攻击者的动机各不相同。早期主要是为了炫耀技术或进行勒索,但现在一个更普遍的原因是数据采集。像 Savannah 这样托管了大量开源代码的网站,成了 AI 公司免费且理想的数据源。他们的爬虫程序不会遵守网站的 robots.txt 规则,会以极高的频率发起请求,甚至动用僵尸网络来绕过封锁,这本质上就是一场 DDoS 攻击。 (p [对于个人网站,攻击动机可能更简单:测试弱密码、利用已知漏洞植入恶意程序,或者仅仅是把你当作更大规模攻击的“跳板”。
面对自动化攻击,手工封禁单个 IP 无异于杯水车薪。成熟的防御体系遵循一个闭环:持续观察(观察)→ 识别恶意模式(识别)→ 自动执行动作(反应)。这整个流程必须自动化。
FSF 团队最初使用经典的`fail2ban`工具。它通过扫描日志文件,发现多次失败尝试后,调用防火墙(如`iptables`)封锁 IP。但当需要管理的 IP 达到数万个时,传统防火墙规则会拖垮系统性能。这时就需要更强大的组合:ipset 和 reaction
下面的步骤将指导你安装和配置这套防御工具。请打开你的 GNU 服务器的终端。
在 Debian GNU 系统上,使用以下 'bash' 命令安装`ipset`和`reaction`:
sudo apt update
sudo apt install ipset reaction
reaction 的配置核心是告诉它三件事:启动时做什么、停止时做什么、遇到攻击时做什么。
首先,创建配置文件 `/etc/reaction/config.jsonnet`。这个文件使用一种叫 JSONnet 的格式,比普通 JSON 更灵活,允许我们定义“函数”来重复使用。
我们将采用“ipset 管理超时”的方式。这意味着封禁 IP 的“有效期”直接交给 ipset 处理,reaction 只负责添加,这样性能更好,重启服务时也能保留已有封禁。
配置文件的核心结构如下:
// 定义封禁动作:将 IP 加入 ipset,并设置超时时间(秒)
local banFor(seconds) = {
ban4: {
// 对 IPv4 执行:ipset -exist -A reaction4 <ip> timeout <seconds>
cmd: ['ipset', '-exist', '-A', 'reaction4', '<ip>', 'timeout', std.toString(seconds)],
ipv4only: true,
},
ban6: {
// 对 IPv6 类似
cmd: ['ipset', '-exist', '-A', 'reaction6', '<ip>', 'timeout', std.toString(seconds)],
ipv6only: true,
},
// 不需要 unban 动作,由 ipset 超时自动处理
};
{
state_directory: '/var/lib/reaction', // 存储 ipset 备份的目录
// 定义 IP 匹配规则,忽略本地地址
patterns: {
ip: {
type: 'ip',
ignorecidr: ['127.0.0.0/8', '::1/128'],
},
},
// --- 启动时执行:创建 ipset 并插入防火墙规则 ---
start: [
['touch', '/var/lib/reaction/reaction4.ipset'],
['touch', '/var/lib/reaction/reaction6.ipset'],
// 恢复之前保存的 ipset
['ipset', 'restore', '-!', '-f', '/var/lib/reaction/reaction4.ipset'],
['ipset', 'restore', '-!', '-f', '/var/lib/reaction/reaction6.ipset'],
// 创建 ipset,最大容纳300万个条目
['ipset', '-exist', '-N', 'reaction4', 'hash:net', 'family', 'inet', 'maxelem', '3000000', 'timeout', '0'],
['ipset', '-exist', '-N', 'reaction6', 'hash:net', 'family', 'inet6', 'maxelem', '3000000', 'timeout', '0'],
// 在防火墙的 INPUT 和 FORWARD 链最前面插入规则:丢弃所有来自 reaction4/6集合中 IP 的数据包
['iptables', '-w', '10', '-I', 'INPUT', '1', '-m', 'set', '--match-set', 'reaction4', 'src', '-j', 'DROP'],
['iptables', '-w', '10', '-I', 'FORWARD', '1', '-m', 'set', '--match-set', 'reaction4', 'src', '-j', 'DROP'],
['ip6tables', '-w', '10', '-I', 'INPUT', '1', '-m', 'set', '--match-set', 'reaction6', 'src', '-j', 'DROP'],
['ip6tables', '-w', '10', '-I', 'FORWARD', '1', '-m', 'set', '--match-set', 'reaction6', 'src', '-j', 'DROP'],
],
// --- 停止时执行:清理防火墙规则并保存 ipset ---
stop: [
// 删除刚才插入的防火墙规则
['iptables', '-w', '10', '-D', 'INPUT', '-m', 'set', '--match-set', 'reaction4', 'src', '-j', 'DROP'],
['iptables', '-w', '10', '-D', 'FORWARD', '-m', 'set', '--match-set', 'reaction4', 'src', '-j', 'DROP'],
['ip6tables', '-w', '10', '-D', 'INPUT', '-m', 'set', '--match-set', 'reaction6', 'src', '-j', 'DROP'],
['ip6tables', '-w', '10', '-D', 'FORWARD', '-m', 'set', '--match-set', 'reaction6', 'src', '-j', 'DROP'],
// 保存 ipset 到磁盘
['ipset', 'save', 'reaction4', '-f', '/var/lib/reaction/reaction4.ipset'],
['ipset', 'save', 'reaction6', '-f', '/var/lib/reaction/reaction6.ipset'],
// 删除 ipset
['ipset', '-X', 'reaction4'],
['ipset', '-X', 'reaction6'],
],
// --- 定义监控源和匹配规则(这是防御重点) ---
streams: {
// 示例1:监控 SSH 登录日志,防止暴力破解
ssh: {
// 实时读取 systemd 的 sshd 服务日志
cmd: ['journalctl', '-fn0', '-u', 'sshd.service'],
filters: {
failedlogin: {
regex: [
// 匹配失败的密码尝试
@'Failed password for .* from <ip>',
// 匹配无效用户尝试
@'Invalid user .* from <ip>',
],
retry: 3, // 连续失败3次
retryperiod: '1h', // 在1小时内
actions: banFor(48 * 3600), // 封禁48小时
},
},
},
// 示例2:监控你的网站日志(需更改路径)
// 保护你的 WordPress 或其它 Web 应用免受扫描
/*
nginx_web: {
cmd: ['tail', '-fn0', '/var/log/nginx/access.log'],
filters: {
// 阻止对常见敏感路径的扫描
badbots: {
regex: [
// 匹配请求路径中包含 /wp-admin 或 /xmlrpc.php 的请求
@'(GET|POST) .*(/wp-admin|/xmlrpc.php) .* <ip>',
],
retry: 2,
retryperiod: '10m',
actions: banFor(24 * 3600),
},
},
},
*/
},
}
配置完成后,启动 reaction 服务并设置开机自启:
sudo systemctl start reaction
sudo systemctl enable reaction
测试你的配置:故意输错几次 SSH 密码,然后检查 ipset 是否生效:
sudo ipset list reaction4
你应该会看到你的客户端 IP 地址出现在列表中,并带有超时时间。
通过`journalctl -u reaction -f`可以随时查看 reaction 的工作日志,它会显示匹配到的模式和执行的封禁命令。
除了安装自动防御工具,你还可以通过调整一些行为来大幅降低风险:
我们无法阻止所有攻击,但通过观察学习、识别攻击模式,并使用像`reaction`和`ipset`这样强大的自动化工具,我们完全可以建立一个自己的“数字防线”,让恶意流量止步于门外。这套系统并非高深莫测,它只是将系统管理员的最佳实践经验,封装成了你也能掌握的具体步骤。现在,就从保护你自己的小天地开始吧。
如果你希望自己的互联网基础坚固耐用,对你的隐私和安全保护充分,那么 立伯乐 或许可以帮你。
让自由软件带你进入的美好自由世界!