FDE Times 数据在招 FDE 职位 824▼37 近 7 天在招职位数的变化(同口径比较):不计入本周新开始追踪的公司的职位近 7 天新增 76在招公司 153支持远程 25%美国薪资中位数 $202k招聘最多 Databricks 104
ENVI

前线部署工程师(FDE)的专业媒体

技能指南 · 指南

Agent 的 URL 抓取工具,就是通往客户内网的代理

黑名单挡不住 SSRF,只有固定解析 IP、经出口代理转发的抓取路径才能把门关上。

分享微博

要点速览

  • 在客户网络内运行、带 URL 抓取工具的 Agent,会让任何能控制提示词的人访问内部服务和元数据服务。
  • 黑名单和手写的 IP 检查很容易绕过;应使用白名单、固定 DNS 解析结果、检查每一次重定向,并加上出口代理。
  • 在 AWS 上,默认跳数限制 1 会让容器拿不到 IMDSv2 令牌;调到 2 则为沙箱打开了获取凭证的通路。
示意图展示为 Agent 拦截 SSRF 的三层防护。顶层是代码层,由白名单和 IP 检查组成,作为前置过滤;中间层以橙色粗体突出,是出口代理,负责解析域名、检查 IP 并固定连接,是主要防线;底层是网络与元数据层,由私有子网、IMDSv2 和跳数限制组成。
向客户安全团队汇报时要画的三层:代码内的检查只有在每个请求都经过它时才有效;出口代理在一个地方堵住检查与连接之间的时间差。来源:Model Context Protocol 安全最佳实践、OWASP、AWS 关于 IMDSv2 的文档。

设想你在客户现场的第三周。内部客服 Agent 运行顺利,用户提了一个小需求:“贴一个链接,Agent 读完给出摘要”。你用大约二十行代码加了一个 fetch_url 工具,演示很顺利,皆大欢喜。

但这个 Agent 运行在客户虚拟私有云(VPC)内的一台虚拟机上。这台机器能看到内部 wiki、管理后台、数据库,以及云元数据服务。

现在,任何能在聊天框里输入内容的人,或者能在 Agent 将要读取的网页里埋下指令的人,都可以从防火墙内部发出请求。赋予他们这种能力的,正是那二十行代码。

这个漏洞叫 SSRF。前线部署工程师(FDE)几乎一定会碰上它,因为这份工作就是把 Agent 放到离客户真实数据很近的地方。下文介绍攻击原理、安全的抓取路径应该是什么样,以及最常见的错误。

为什么 Agent 会让 SSRF 更严重?

在传统 Web 应用中,攻击者得先找到一个暴露在外的 URL 参数。而在 Agent 中,URL 由语言模型选择,模型会听从文本,包括别人埋下的文本。

模型上下文协议(Model Context Protocol,MCP)的安全最佳实践文档描述的正是这种场景。文中列出的后果里有一句话,每个 FDE 都应该牢记:服务端的 MCP 客户端会变成一个绕过网络边界控制的代理。

这种事已经真实发生过。CraftedSignal 在 2026 年 5 月发布的安全公告指出,auth-fetch-mcp 包的抓取工具存在 SSRF 漏洞,攻击者可以迫使服务器加载内部资源、云元数据端点或回环地址。

最有价值的目标就在机器本身

在云上,运行 Agent 的机器通常绑定了一个 IAM 角色。谁拿到 IMDSv2 会话令牌,谁就能用它从元数据服务读取该角色的临时凭证。到了这一步,对方已经不需要 Agent 了:他们握有这台机器的权限,可以直接调用客户的 API。

AWS 设计 IMDSv2,是为了在防火墙大开、反向代理配置错误或应用存在 SSRF 漏洞时多一层防御。关键机制是:携带令牌的响应在离开实例前,TTL 会被降为 0,因此只有实例本身能收到令牌。根据 AWS 文档,这个响应的默认跳数限制为 1。

当 Agent 运行在实例上的容器或沙箱里时,这个数字决定了沙箱能否拿到令牌。AWS 解释说,进入容器算多一跳,所以跳数限制为 1 时,容器可能根本收不到响应。

结果是:默认值 1 会让距离实例一跳的容器拿不到令牌;而调到 2(AWS 本身就建议容器环境这样做)则会让沙箱接触到机器的凭证。

如果有人为了“让它跑起来”调高了跳数限制,要问清原因。AWS 也给出了替代方案:把 Region 等配置直接传入容器,而不是向容器开放元数据服务。

安全的抓取路径是什么样

对客户提出的第一个问题永远是:Agent 真的需要读取任意 URL 吗?如果用户只会贴公司内部的 Confluence 和 GitHub 链接,就用白名单。但仅靠域名白名单挡不住 DNS 重绑定。

原因在于一个时间差,MCP 文档称之为 DNS TOCTOU(检查时间与使用时间不一致)。检查时,域名指向公网 IP;等到连接时,HTTP 库可能重新解析,拿到一个内网 IP。

OWASP 提醒,在校验和连接之间如果发生第二次未经检查的解析,就能绕过这些检查。

2026 年关于 MCP Atlassian 的安全公告就是真实案例:校验通过后,requests.get 又解析了一次 DNS,拿到 169.254.169.254,也就是元数据地址。MCP 建议的修复方法是固定解析结果:只解析一次,检查这个 IP,然后只连接这个 IP。

下面是检查逻辑的核心,用 Python 编写:

import ipaddress, socket
from urllib.parse import urlparse

class BlockedDestination(Exception):
    pass

def resolve_and_check(url: str):
    parsed = urlparse(url)
    if parsed.scheme not in ("http", "https"):
        raise BlockedDestination(f"不允许的协议 {parsed.scheme}")
    host = parsed.hostname
    ips = {ipaddress.ip_address(info[4][0])
           for info in socket.getaddrinfo(host, None)}
    for ip in ips:
        if ip.version == 6 and ip.ipv4_mapped:
            ip = ip.ipv4_mapped
        if (ip.is_private or ip.is_loopback or ip.is_link_local
                or ip.is_reserved or ip.is_multicast or ip.is_unspecified):
            raise BlockedDestination(f"{host} -> {ip}")
    return host, sorted(ips, key=str)[0]  # 连接时要固定使用的 IP

有三个细节值得注意。这个函数使用标准库,而不是手动切分 IP 字符串,因为 MCP 文档警告:攻击者会用八进制、十六进制或 IPv4 映射的 IPv6 格式书写 IP,绕过手写的解析器。

只要域名的任意一个 IP 落在私有、回环或链路本地网段,函数就拒绝。函数还会返回这个 IP,让下一步直接连接它,不再重新解析。

难点恰恰在于 URL 为 HTTPS 时的“直接连接 IP”这一步。你向固定的 IP 打开 socket,但 TLS 握手中的 SNI、证书校验和 Host 头仍然必须使用原始域名,否则服务器会返回错误的页面,或者证书会被拒绝。

OWASP 指出,并非每个 SDK 都内置了这类检查,开发者得自己处理边界情况。

datamodel-code-generator 的安全公告说明了代价:防护逻辑只检查了一次 IP,随后让 httpx 自行解析 DNS,于是没有任何机制把连接绑定到通过检查的那个 IP 上。

因此,把上面的函数当作应用内的前置过滤,把固定 IP 的工作交给下文介绍的出口代理。

接下来是重定向循环。关闭 HTTP 库的自动跟随重定向,例如设置 allow_redirects=False。每遇到一个 3xx 响应,就取出 Location 头,再次调用 resolve_and_check,并在几跳之后停止,因为第一个 URL 可能干干净净,第三个却指向内网。

代码写得再好,也不是主要防线

上面的函数是应用层防护。只有当每一条发送请求的路径都经过它时,它才有效,包括浏览器工具、第三方 MCP 服务器和 webhook。只要有一条路径忘了调用,就足以被突破。

所以 MCP 文档建议服务端部署使用 Smokescreen 这类出口代理(一种专为防范 SSRF 设计的代理),而不是逐个修补适配器。代理自己解析域名、检查 IP 并建立连接,于是检查和使用之间的时间差在一个地方被堵上,而不是分散在每个工具里。

在客户现场,合理的做法是:把 Agent 放进一个子网,它通往互联网的唯一路由是经过代理,没有通往数据库的路由,强制启用 IMDSv2,并让跳数限制保持在沙箱拿不到令牌的水平。

向客户安全团队汇报时,画出三层:代码里的白名单和 IP 检查,中间的出口代理,底层的网络隔离和元数据配置。一层失守,其他层还能顶住。这样一张图,通常比一句“我们会校验 URL”更快通过安全评审。

常见错误

最常见的错误是写黑名单,比如“拦截 localhost 和 127. 这两个字符串”。这些地址有很多种写法,而这正是 MCP 文档说要避免的手写检查。第二个错误是只在开头检查一次 URL,然后任由 HTTP 库自行跟随重定向、重新解析 DNS。

第三个错误是只考虑用户输入恶意 URL。在 Agent 场景里,URL 可能藏在邮件、工单或 Agent 被要求阅读的网页里。第四个错误是以为云平台会处理好元数据,而一次“为了让容器跑起来”的跳数限制修改,就可能重新打开这扇门。

一张图,既能修漏洞,也能帮你拿 offer

本周练习:拿出你最近一次部署的网络图,标出运行 Agent 的机器,然后画出这台机器能发送请求的每一个箭头。凡是你无法向客户解释清楚的箭头,都是下次演示前要完成的工作。

这张图,加上你砍掉的箭头清单,也是求职时最有力的证明。如果某个岗位提到在客户基础设施中部署,或与安全团队协作,面试时就讲这个故事:哪台机器、哪个箭头、哪一层把它挡住了。

在简历上,一句“为运行在客户网络中的 Agent 设计出口策略和 SSRF 防护,通过安全评审”,比三行框架列表更有说服力。招 FDE 的人需要知道,你能看到别人漏掉的箭头。

这篇文章对你有帮助吗?

8 个信源
路线图上的下一篇 · 阶段 3: AI 应用昨天批准的 MCP 服务器,更新后可能就变成了恶意工具Agent 接触客户数据前,如何审读、锁定版本并隔离第三方 MCP 服务器,以及为何安装时批准一次不够。