在 FreeBSD 上配置 Anubis 反 AI 爬虫工具
最近我注意到,我的Forgejo服务器多次触发监控系统的警报,响应速度不如平时快。结果发现——竟是AI爬虫在为自身需求抓取服务每个细微环节时,导致服务器彻底瘫痪。
为此我部署了Anubis来缓解此问题。
Anubis现已入驻FreeBSD Ports!
撰写本文后得知,Anubis已正式纳入FreeBSD端口库。我认为这应成为在FreeBSD系统上安装Anubis的事实标准方案。
具体操作如下:
# 同步端口库
git clone --depth 1 https://git.FreeBSD.org/ports.git /usr/ports
# 切换至Anubis端口目录
cd /usr/ports/www/go-anubis
# 编译并安装Anubis
make install
# 在rc.conf中配置并启用Anubis
sysrc anubis_args="-target http://localhost:3000 -bind :8923" # ...按需添加参数"
sysrc anubis_enable=YES
若您希望自行编译,或像我一样偏好通过配置文件调整参数,以及/或需要更多配置策略信息,请继续阅读。
服务器配置
对于不了解Forgejo的用户,它是一款软件锻造平台;可将其视为可自主托管的Git…枢纽。我的Forgejo实例运行于FreeBSD监狱环境服务器中,并通过同样部署在监狱环境的HAProxy反向代理进行访问。
我使用Gatus监控该服务及其他众多服务的运行时长。这是套设计精妙的简易基础设施监控系统,能根据多种因素(如网络连接中断、证书过期,以及关键的响应时间)触发警报。
问题所在
近几个月来,我注意到因响应时间过长触发的警报显著增加。快速检查 HAProxy 日志发现,大量流量来自 AI 爬虫程序,日志内容如下所示:
...数千行日志省略...
Feb 19 21:47:39 192.168.200.5 haproxy[2334]: 20.171.207.150:41308 [19/Feb/2025:21:47:39.115] ft_in_https~ be_forgejo/forgejo 0/0/1/273/279 200 17290 - - --- - 6/6/0/0/0 0/0 “GET https://forge.notnull.space/psw/web/commit/078833d79049280fcc13bfc790b2835d9819de28.patch HTTP/2.0” hdrs:"host: forge.notnull.space^M x-openai-host-hash: 132087407^M accept: _/_^M from: gptbot(at)openai.com^M user-agent: Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; GPTBot/1.2; +https://openai.com/gptbot)^M accept-encoding: gzip, br, deflate^M ^M "
...数千行之后...
这些数千次请求都在抓取我的代码库数据,导致服务器负载激增,响应速度越来越慢。
基础防御
我的当务之急自然是阻止当前这些AI垃圾爬虫,以减轻服务器负载,使其能正常履行本职工作。
robots.txt文件虽有一定效果,但事实证明某些AI爬虫要么无视该文件,要么在未被明确禁止(即不遵循*通配符规则)时便自认合法继续爬取。
作为额外防御措施,我在 HAProxy 中设置了基于正则表达式的基础封禁列表,对符合特定模式的来源流量返回 403 HTTP 响应
# /etc/haproxy.conf
frontend ft_in_https
# 拦截恶意机器人
acl is-blockedagent hdr_sub(user-agent) -m reg -i -f /opt/haproxy-blocklist-agent.txt
http-request deny if is-blockedagent
... 其余配置
并配置了大量正则表达式模式进行拦截——无论是旧版浏览器还是AI爬虫名称。
# /opt/haproxy-blocklist-agent.txt
WImagesiftBotW
WBytespiderW
WPetalBotW
WAmazonBotW
WAndroid [0-8].0W
WChrome/[0-7][0-8]W
WChrome/11[0-9]W
WFirefox/[0-7][0-8]W
W47.82W
Wx-openai-host-hashW
Wgptbot
Wgptbot(at)openai.com
WGPTBot/1.2;W
...等等...
这招确实管用…算是吧。它消除了对Forgejo服务器的请求压力,这点确实好多了,但这些机器人仍在持续发送请求——只不过被HAProxy拦截了。HAProxy轻松就能处理这些请求,但日志里满屏的拦截记录终究不太美观。
阿努比斯(Anubis)登场
阿努比斯(Anubis)是由Techaro近期开发的卓越反人工智能软件产品。其运作原理是向连接计算机发起工作量证明挑战,设备必须完成解题才能访问请求内容。该项目正迅速普及,包括联合国,Linux 在内的机构均已采用。
对于您我这样的普通访客,网站加载前会显示“验证非机器人身份”的简短提示界面,通过验证后即可正常使用。
但针对人工智能,我们可配置阿努比斯生成更复杂的挑战任务,大幅延长其解决时间,从而显著抑制机器人向服务端发送请求的速度。
这极大降低了 HAProxy 需处理的连接数,显著减轻了整体负载。
构建 Anubis
Anubis目前尚未提供原生FreeBSD二进制文件,但这不成问题——作为Go语言和NPM构建的产品,我们可轻松自行编译。
首先在系统中安装Go环境:
# 撰写本文时Go 1.24.2为最新版本,请按需调整。
$ wget https://go.dev./dl/go1.24.2.freebsd-amd64.tar.gz
# 解压
$ tar xf go1.24.2.freebsd-amd64.tar.gz
# 将下载的go文件夹复制到/usr/local/(后续GOROOT设置所需)
$ cp go /usr/local/
# 按需设置PATH和GOROOT环境变量
$ export GOROOT=/usr/local/go
$ export PATH=$PATH;$GOROOT/bin
现在,我们可通过下载 Anubis 的预编译包省去大量麻烦,该包已包含 Go 模块依赖项,并预先编译了静态 JS、CSS 等资源。
可通过以下命令构建 Anubis:
# 撰写本文时,Anubis最新版本为v1.16.0
$ wget https://github.com/TecharoHQ/anubis/releases/download/v1.16.0/anubis-src-vendor-npm-1.16.0.tar.gz
# 解压
$ tar xf anubis-src-vendor-npm-1.16.0.tar.gz
$ cd anubis-src-vendor-npm-1.16.0
# 构建
$ make prebaked-build
若一切顺利,您将获得可直接使用的二进制文件 ./var/anubis。
以守护进程模式运行 Anubis
我为FreeBSD编写了一个基础的rc.d脚本。该脚本通过[daemon]机制运行Anubis,确保程序崩溃时自动重启,并将日志输出至/var/log目录。
若需使用,可从存档目录复制至 rc.d 目录:
$ cp anubis.freebsd /usr/local/etc/rc.d/anubis
$ chmod +x /usr/local/etc/rc.d/anubis
随后启用并设置配置路径:
$ sysrc “anubis_enable=YES”
$ sysrc “anubis_environment_file=/etc/anubis.env”
需创建anubis用户账户(如adduser anubis)或正确设置anubis_user变量。
配置 Anubis
软件准备就绪后,需进行基础配置以满足需求。
首先需设置基础环境变量——完整列表详见Anubis官网。例如:vim /etc/anubis.env
# Anubis监听端口
BIND=:8923
# 服务端点地址,本地服务器默认端口为3000
TARGET=http://localhost:3000
# Cookie域名:重要提示:此处仅需填写服务根域名。若服务运行于forgejo.example.com,则填写example.com
# Cookie域名:重要提示:此处仅需填写服务根域名。若服务运行于forgejo.example.com,则填写example.com
COOKIE_DOMAIN=example.com
# 自定义策略文件路径 - 后续详述
POLICY_FNAME=/etc/forgejo.json
# 十六进制编码的私钥。若未设置,每次重启Anubis时将生成新密钥
ED25519_PRIVATE_KEY_HEX=""######### ################ - 运行 `openssl rand -hex 32` 生成密钥
创建自定义策略
Anubis默认会对所有可能的浏览器进行激进的身份验证,这在某些场景下可行,但通常并非如此。因此我们可以创建自定义策略文件,对友好对象采取宽松策略,对恶意对象实施严格策略。
Anubis官方文档中的示例在此场景下相当适用:
{"bots":
[
{
"name": "generic-bot-catchall",
"user_agent_regex": "(?i:bot|crawler|gpt)",
"action": "CHALLENGE",
"challenge": {
"difficulty": 16,
"report_as": 4,
"algorithm": "slow"
}
},
{
"name": "well-known",
"path_regex": "^/.well-known/.*$",
"action": "ALLOW"
},
{
"name": "favicon",
"path_regex": "^/favicon.ico$",
"action": "ALLOW"
},
{
"name": "robots-txt",
"path_regex": "^/robots.txt$",
"action": "ALLOW"
},
{
"name": "generic-browser",
"user_agent_regex": "Mozilla",
"action": "CHALLENGE"
}
]
}
首个规则定义要求所有包含“bot”、“crawler”或“gpt”字符串的用户代理连接,必须接受高难度慢速验证挑战。
接下来的3条规则表明,允许访问.well-known文件夹、favicon或robots.txt文件的请求直接通过。我们不希望对这些请求进行验证。例如,certbot/letsencrypt需要访问.well-known/acme-challenge目录来验证证书——我们不希望破坏这个流程。
最后,“generic-browser”定义为其他所有请求设置了基础验证。这是普通访客首次访问时短暂看到的验证页面,用于确认其非机器人身份。
准备就绪
至此配置完成。现在我们可以启动Anubis,将HAProxy指向Anubis的监听端口,让它投入工作!
启动Anubis
$ service anubis start
配置 HAProxy
其余配置
backend be_forgejo
mode http
# server forgejo 192.168.200.10:3000 # 旧版直连 forgejo 路由(已禁用)
server forgejo 192.168.200.10:8923 # 新版转发至 anubis 的路由
监控与扩展功能
提供的rc.d脚本会将标准输出和错误输出记录至/var/log/anubis.log,以便查看运行状态及错误信息。
当前每个终端节点必须单独运行Anubis实例。例如若需同时为Forgejo和网站运行Anubis,则至少需启动两个实例。
我目前仅运行单个实例,但另设有一个用于更新和构建Anubis的监狱环境。该监狱环境将Anubis二进制文件输出至共享目录,其他监狱环境可独立调用运行。这使我能同时运行多个实例,却只需在单一位置更新二进制文件。
最终说明
若您正在使用Anubis且条件允许,我强烈建议您尽己所能捐助该项目,以支持其未来持续维护。
