如果你在 Clash、Mihomo、Sing-box、Surge 这类代理工具里开启了 TUN / TProxy + Fake-IP,再用 Hermes Agent 的浏览器或网页抓取工具访问普通网站,可能会遇到:
Blocked: URL targets a private or internal address
奇怪的是,同一个网址用系统浏览器、curl 或普通客户端都能打开,只有 Hermes 的 browser_navigate、web_extract 等 URL 工具被拦。
这篇文章基于 NousResearch/hermes-agent issue #3777,解释为什么 RFC 2544 benchmark 网段 198.18.0.0/15 会被安全检查误判成 private address,以及 TUN Fake-IP 用户该如何在 SSRF 防护和可用性之间取平衡。
典型现象:普通网站被当成内网地址
复现环境通常长这样:
# Clash / Mihomo 类配置示意
tun:
enable: true
dns:
enhanced-mode: fake-ip
然后在 Hermes 里访问公开网站:
browser_navigate(url="https://www.baidu.com")
# 或 web_extract / web_search / browser_vision 等 URL 工具
结果不是网络超时,也不是 DNS 失败,而是直接被 URL safety 拦截:
Blocked: URL targets a private or internal address
这意味着请求还没真正走到代理隧道,就在 Hermes 的 SSRF 保护层被挡住了。
Fake-IP 是怎么工作的?
现代代理软件为了优化 DNS 和透明代理,常用 Fake-IP:
1. 应用查询 github.com; 2. 代理 DNS 返回一个虚拟 IP,例如 198.18.0.131; 3. 应用连接这个 Fake-IP; 4. TUN 接口捕获流量; 5. 代理根据映射表把流量转发到真实目标。
常见映射可能类似:
| 域名 | Fake-IP | 实际目标 |
www.baidu.com | 198.18.4.114 | 公网网站,经代理转发 |
google.com | 198.18.2.84 | 公网网站,经代理转发 |
github.com | 198.18.0.131 | 公网网站,经代理转发 |
所以 198.18.x.x 不是用户真的想访问某台内网服务器,而是本机代理栈里的“临时路标”。
为什么 Hermes 会拦?
issue 指向 Hermes 的 URL 安全检查逻辑:
if ip.is_private or ip.is_loopback or ip.is_link_local or ip.is_reserved:
return True
而 Python 的 ipaddress 对 198.18.0.0/15 的判断会让人踩坑:
import ipaddress
ip = ipaddress.ip_address("198.18.4.114")
print(ip.is_private) # True
print(ip.is_reserved) # False
print(ip.is_global) # False
RFC 2544 把 198.18.0.0/15 定义为 benchmarking test range,不是传统意义上的 RFC1918 私网:
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
但 URL safety 层只看到 ip.is_private=True,于是把它当成内网风险拦掉。
这为什么会影响很多中国用户?
Clash / Mihomo / Clash Verge Rev / Sing-box / Surge 用户中,TUN + Fake-IP 是很常见的模式,尤其在需要透明代理、系统级代理或复杂分流规则时。
这类用户的 DNS 结果经常是 198.18.0.0/15。
因此受影响的不只是一个网站,而是所有依赖 URL 安全检查的工具:
browser_navigateweb_extractweb_search- 浏览器相关截图/视觉工具
- 远程附件或媒体下载路径
- 其他复用
url_safety的平台 adapter
issue 评论里也明确补充:这不只是 browser navigation,web_extract 也会在 Fake-IP DNS 下触发同样误拦。
安全难点:不能简单把所有 private URL 放开
有人会说:既然拦错了,那直接允许 private URL 不就行了?
Hermes 后续提供了全局开关:
security:
allow_private_urls: true
或者通过环境变量类似:
HERMES_ALLOW_PRIVATE_URLS=true
但这类开关必须谨慎。
SSRF 防护的意义,是阻止工具访问:
127.0.0.1localhost192.168.0.0/1610.0.0.0/8169.254.169.254云 metadata- 内网管理面板
- link-local / loopback / multicast 等敏感地址
如果全局放开 private URL,确实能让 Fake-IP 通过,但也扩大了攻击面。
所以它更适合作为“我知道当前运行环境风险,并且需要可用性”的显式运维开关,而不是默认行为。
更细的方案:只信任 TUN Fake-IP CIDR
评论中有人提出更窄的配置思路:
browser:
allow_private_urls: false
trusted_tun_cidrs:
- 198.18.0.0/15
设计思路是:
- 默认仍然阻止 private URL;
- 只在特定工具路径(例如 browser)允许特定 CIDR;
192.168.1.10、127.0.0.1、169.254.169.254仍然阻止;- pre-navigation 和 post-redirect SSRF 检查都要传入该 allowlist;
- 避免把
198.18.0.0/15全局当成安全。
这比粗暴开 allow_private_urls: true 更符合最小权限原则。
不过维护者后来指出,合并的处理路径是 security.allow_private_urls 全局 toggle,并让多个 URL call sites 继承该开关,同时保留对云 metadata 地址的特殊保护。
另一个坑:不要随便改 Fake-IP 到 28.0.0.0/8
issue 里有人问:把 Fake-IP range 改成 28.0.0.0/8 安全吗?
这个问题很关键。28.0.0.0/8 并不是给你本地随便用的私有网段,它属于真实分配地址空间。随便把 Fake-IP 池改到真实公网段,可能制造更诡异的路由冲突。
因此优先级通常是:
1. 用代理软件默认推荐的 Fake-IP 池; 2. 在应用侧配置明确的安全例外; 3. 不要随意占用真实公网地址段做假 IP 池。
排查步骤:确认是不是 Fake-IP 误拦
1. 看 DNS 解析结果
在受影响环境里确认目标域名是否解析到:
198.18.x.x
198.19.x.x
只要落在:
198.18.0.0/15
就符合 RFC 2544 benchmark range。
2. 对比普通客户端
如果:
- 系统浏览器能打开;
- curl 能打开;
- 但 Hermes URL 工具被
Blocked: URL targets a private or internal address拦;
那就更像 SSRF 检查误拦,而不是网站不可达。
3. 检查代理模式
重点看:
- TUN 是否开启;
- TProxy 是否开启;
- DNS 是否是 fake-ip/enhanced-mode;
- Fake-IP 池是否使用
198.18.0.0/15。
4. 选择 workaround
短期可以考虑:
- 关闭 TUN,改用 HTTP/HTTPS proxy 环境变量;
- 关闭 Fake-IP,改 real-ip 模式;
- 显式启用
security.allow_private_urls,但理解 SSRF 风险; - 等待或使用更细粒度的 trusted CIDR 配置方案。
和 DeepAI API 中转站的关系
DeepAI API 中转站常见配置是:
Base URL: https://api.deepai.wang/v1
API Key: 你的 DeepAI Key
Model: 以 DeepAI 控制台为准
但本文问题不在模型 API,而在 Hermes 的 URL 工具访问外部网页时,被 SSRF 防护提前拦截。
如果你的任务是让 Hermes 调用 DeepAI 模型,通常不会触发这个 Fake-IP URL safety 问题;但如果你让 Hermes 同时使用浏览器、网页提取、搜索或远程媒体下载,就可能遇到。
分层判断:
- 模型调用失败:看 DeepAI / OpenAI-compatible API 日志;
- 网页访问被
Blocked:看 URL safety / SSRF / DNS Fake-IP; - 代理可用但工具不可用:看 Hermes 是否把 Fake-IP 当成 private。
FAQ
198.18.0.0/15 是私网吗?
它是 RFC 2544 benchmarking test range,不是 RFC1918 私网,但 Python ipaddress.is_private 会把它归为 True,导致安全检查容易误拦。
为什么浏览器能打开,Hermes 不行?
浏览器请求会走 TUN 代理映射;Hermes 在请求前做 SSRF 检查,DNS 解析到 Fake-IP 后就提前拦掉了。
直接开 security.allow_private_urls: true 安全吗?
能解决可用性,但会扩大 SSRF 风险。只应在你理解运行环境和信任调用者时启用。
更推荐的方案是什么?
理想上是 scoped allowlist,例如只允许 198.18.0.0/15 作为 TUN Fake-IP,并保留对 loopback、link-local、云 metadata 的拦截。
DeepAI API 中转站会受影响吗?
模型 API 本身通常不受这个问题影响;受影响的是 Hermes 的网页访问、浏览器、抓取等 URL 工具路径。
总结
Hermes 在 TUN + Fake-IP 代理环境下访问普通网站时报:
Blocked: URL targets a private or internal address
核心原因通常是:域名被代理 DNS 解析到 198.18.0.0/15,而 URL safety 把该 benchmark range 当成 private/internal address 拦截。
一句话:这不是网站真的在内网,而是 Fake-IP 与 SSRF 防护的边界冲突;修复时要兼顾代理可用性和内网访问安全。