编码代理遥测会发送哪些数据?如何从本机审计
编码代理会产生4类流量,模型推理无法关闭。本文教您从本机核对配置、主机名与进程行为,找出分析、崩溃报告及集成工具的额外请求。
编码代理遥测实际涵盖的内容
编码代理遥测包含4种独立的数据流,只是共用了“遥测”这个词。每种数据流都有自己的控制方式。模型推理会将您的提示词和代码发送给模型服务提供方,任何设置都无法关闭这项传输。产品分析数据和崩溃报告会发送给供应商,通常还会发送给供应商付费使用的日志服务公司。训练数据的保留期限属于合同问题,而不是网络问题。人们容易忽略第4种数据流:您添加的每个集成都可能连接到一个并非由您选择的主机。
当前供应商默认设置的列表最容易过时。一次版本发布可能更改默认设置,新功能也可能增加一个现有开关无法覆盖的目的地。因此,真正持久的技能是执行一套可重复的审计流程,适用于任何代理:阅读供应商提供的文档,检查本机实际应用了哪些配置,从本机监控进程的行为,然后选择您愿意为之承担成本的控制措施。下面的每条命令都应在您自己的机器上运行,并针对您自己的网络流量。
四类流量,以及为什么需要采用不同的控制措施
模型推理流量无法避免。 Agent 会将您的提示词、它读取的文件、所执行命令的输出,以及自行生成的文本发送到模型端点。这就是产品正常工作的方式。唯一真正需要决定的是接收方:由他人运行的 API,还是由您自行运行的模型。公司云账户(Bedrock、Vertex、Foundry)只是改变接收方,并不会消除这条数据流。本文其余部分都不会减少推理流量,因此请将它与另外三类流量分开考虑。
产品分析和崩溃报告是发往不同主机的另一类流量。 使用次数、延迟数据、功能标志查询和堆栈跟踪通常会发送到与模型 API 完全无关的主机名,而且经常会发送到第三方错误跟踪服务。供应商通常将这些内容称为“指标”和“错误报告”,并通常为每个类别提供一个环境变量。流量很小,因此按字节统计永远无法发现它。您需要查找的是主机名,而不是带宽。
数据保留和训练属于策略,而不是数据包。 供应商是否保留您的提示词、保留多长时间,以及是否使用这些提示词训练未来的模型,都写在与您的套餐相关的条款中。个人套餐和商业套餐通常有所不同,而零保留安排通常需要单独签署协议。您无法通过 tcpdump 验证这些内容,因为无论实际策略如何,数据包看起来都完全相同。请阅读相关条款;如果这对您的雇主很重要,请要求对方提供书面确认。
集成会悄悄增加一个中转环节。 MCP(模型上下文协议)服务器、插件市场、自动更新检查、Web 搜索工具,以及在抓取 URL 前解析该 URL 的安全检查,都会向模型端点之外的主机发起请求。意外情况通常出现在这里,因为工具框架可能会将您以为在本地执行的工作通过其自身的服务转发出去;软件发布新版本后,也可能开始这样做,而无需修改您的任何配置。除非您已在网络层观察过新增工具的流量,否则应将每个新增工具都视为一个新的目标。
第 1 步:厂商文档说明了什么?
打开代理工具的设置参考和数据使用页面,手头准备一份词汇表并逐项阅读:指标、分析、错误报告、崩溃、反馈、调查、更新检查、安全检查、市场。每个词通常对应一个独立开关。记下确切的变量名,因为第 2 步会使用 grep 搜索这些变量名。
其中一个词容易误导你。在多个代理工具中,文档里的“遥测”指的是 OpenTelemetry 导出功能。你需要配置它,将指标发送到自己运行的收集器,这与将数据发送给厂商正好相反。Claude Code 就是其中之一:设置 CLAUDE_CODE_ENABLE_TELEMETRY=1 会将数据导出到你在 OTEL_EXPORTER_OTLP_ENDPOINT 中指定的端点。这与厂商自己的分析功能无关,后者有单独的退出设置。在设置任何选项前,先确认数据的流向。
不要假设主开关可以覆盖所有功能。以 2026 年 8 月为准,Claude Code 的 CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC 会同时关闭指标、错误报告、反馈命令和会话调查。同一份文档还说明,该设置不包括 WebFetch 的域名安全检查。该检查会将即将访问的主机名发送到厂商 API,并且有单独的设置。这不是某个产品特有的问题。所有产品都存在同样的情况:主开关只能覆盖编写该开关时已经存在的类别。
还要考虑退出设置的代价。同一份文档指出,禁用遥测也会禁用部分功能所依赖的功能标志评估。因此,为了保护隐私而关闭一个开关,可能会同时关闭你正在使用的功能,而且不会显示能将两者关联起来的错误消息。不要只看标志名称,还要阅读它旁边的说明。
第 2 步:实际应用了哪个配置?
您写入的设置,不一定是实际应用的设置。代理会合并多个文件中的配置,其中一个文件可能位于您刚从他人处克隆的仓库内。先从您当前 shell 的环境开始检查。
env | grep -Ei 'telemetry|otel|analytics|error_report|do_not_track|proxy'然后按文档列出的顺序,输出工具读取的所有设置文件。对于 Claude Code,截至 2026 年 8 月,顺序是用户文件、两个项目文件,以及 Linux 上的托管策略目录。
for f in ~/.claude/settings.json .claude/settings.json .claude/settings.local.json; do
echo "== $f"; [ -f "$f" ] && cat "$f"
done
ls -l /etc/claude-code/ 2>/dev/null随 git clone 一起进入项目的文件,可能包含陌生人写入的配置,并重新启用用户文件中已关闭的功能。如果代理提供列出已加载配置来源的状态命令,应优先使用它确认实际情况:Claude Code 会在 /status 中输出已加载的设置来源。
最可靠的检查方式是读取正在运行的进程,而不是检查文件。先为代理分配独立的 Linux 用户账户。这样可以缩短本文中的每条命令。然后读取该进程启动时使用的环境。
pgrep -u agent -a node
sudo tr '\0' '\n' < /proc/$(pgrep -u agent -n node)/environ | grep -Ei 'telemetry|proxy|otel'/proc/<pid>/environ 会显示进程在 exec 时获取的变量。因此,即使您的 .bashrc export 没有传递给由 systemd 启动的服务,也能发现这一情况。如果这里缺少您设置的变量,说明该变量从未生效,无论您的 dotfiles 中如何配置。
步骤 3:它连接到哪些主机?
先查看开放的套接字,并按代理运行所使用的账户进行筛选。
sudo ss -tnpe state established-e会在每行中添加一个 uid:字段。这样无需读取进程名称,就能将代理的连接与浏览器的连接区分开。记下远程地址,然后解析这些地址对应的名称。最可靠的名称来源是 TLS(传输层安全)握手,因为每个新连接都会以 ClientHello 开始,其中包含 SNI(服务器名称指示)字段。该字段就是客户端请求访问的主机名。
sudo apt install -y tshark
sudo tshark -i any -f 'tcp port 443' -Y 'tls.handshake.type == 1' \
-T fields -e ip.dst -e tls.handshake.extensions_server_name每个新连接对应一行。这正好就是所需的清单:模型 API、更新服务器、分析主机、错误跟踪服务,以及集成组件添加的任何连接。名称列为空,表示客户端使用了 ECH(加密 ClientHello),因此主机名不会出现在网络传输中。此时可改用目标 IP 地址、反向解析结果,或第 4 步中的代理。
DNS(域名系统)视图可用于交叉验证,因为它会显示代理查询过的名称,即使相应连接没有完成。
sudo tcpdump -ni any -l 'udp port 53'每个查询行都以记录类型和名称结尾,格式为 A? host.example.net. (39)。应在 any 上捕获,而不是在外部接口上捕获,因为使用 systemd-resolved 时,应用会连接到 127.0.0.53 上的本地存根监听器,只有该存根监听器会与外部通信。如果代理运行正常但完全看不到 DNS 流量,说明该运行时自行通过 HTTPS 执行 DNS 查询。此时只有第 4 步可以提供名称。
在代理执行实际工作时进行捕获。启动一个会话,让它读取文件,让它运行命令,再让它在某个操作上失败。启动时只触发一次的流量,或仅在抛出异常时产生的流量,不会出现在空闲捕获中。空闲捕获是审计得出看似合理但实际错误结论的最常见原因。
第 4 步:请求中包含什么?
主机名可以告诉您请求发往谁。要查看请求内容,请在代理前面放置一个由您控制的代理,并仅为该运行时信任其证书颁发机构(CA)。mitmproxy 是常用工具。该项目建议使用 mitmproxy.org 提供的独立二进制文件,并将 uv tool install mitmproxy 记录为 Python 软件包安装方式。
mitmdump -w /tmp/agent-flows.mitm首次运行时,工具会将 CA 写入 ~/.mitmproxy/,其中 mitmproxy-ca-cert.pem 是单独的证书文件。在启动 agent 的 shell 中,将客户端指向该代理和证书。
export HTTP_PROXY=http://127.0.0.1:8080
export HTTPS_PROXY=http://127.0.0.1:8080
export NODE_EXTRA_CA_CERTS="$HOME/.mitmproxy/mitmproxy-ca-cert.pem"
export REQUESTS_CA_BUNDLE="$HOME/.mitmproxy/mitmproxy-ca-cert.pem"
export SSL_CERT_FILE="$HOME/.mitmproxy/mitmproxy-ca-cert.pem"许多 agent CLI 是 Node 程序。Node 会在进程启动时读取 NODE_EXTRA_CA_CERTS,因此应在启动 agent 之前导出该变量,而不是稍后在另一个终端中导出。Python 客户端会读取 REQUESTS_CA_BUNDLE 或 SSL_CERT_FILE;在 Linux 上,使用标准库的 Go 二进制文件会读取 SSL_CERT_FILE。在将问题归咎于 agent 之前,先使用 curl 验证路径是否有效。
curl -sS -o /dev/null -w '%{http_code}\n' https://example.com代理正常工作时,会打印 200,请求也会出现在 mitmdump 的输出中。未受信任的 CA 会产生 curl: (60) SSL certificate problem: self-signed certificate in certificate chain;Node agent 的等效错误会包含代码 SELF_SIGNED_CERT_IN_CHAIN。之后使用控制台查看器读取保存的流量。您可以打开单个请求,查看其标头和正文。
mitmproxy -r /tmp/agent-flows.mitm有 4 种结果值得区分。您能看到请求,这时应读取请求并作出判断。agent 因证书错误而拒绝启动,这说明该运行时存在信任问题,并不能据此认定供应商存在问题。您只能看到模型 API,这意味着其他类别未启用,或者它们只会在您未触发的事件上执行。另一种情况是,agent 明显正常工作,但完全看不到任何请求。这意味着客户端忽略了代理环境变量,或固定了证书;此时不能依赖任何应用设置来告诉您真实情况。最后一种结果最重要。它会将您带回第 3 步,因为无法通过解释让数据包捕获工具看不到连接。
控制措施:从最弱到最强
选择退出设置。 成本最低,强度也最弱,因为它们依赖供应商遵守设置,并且只能覆盖已经存在的类别。将这些设置写入重启和新终端后仍会生效的位置,例如用户设置文件或 shell 配置文件中。顺便添加 DO_NOT_TRACK=1:许多命令行工具都遵守这一约定,包括部分代理,而且无需额外成本。下次更新后重新执行第 3 步,因为届时覆盖范围会发生变化。
出站流量限制。 此时不再请求代理遵守设置,而是开始强制执行。让代理以专用用户身份运行,然后允许该用户访问 loopback 和 DNS,丢弃其余流量。此配置使用独立的表,因此不会影响现有防火墙规则。
table inet agentegress {
chain output {
type filter hook output priority filter; policy accept;
meta skuid "agent" ip daddr 127.0.0.0/8 accept
meta skuid "agent" udp dport 53 accept
meta skuid "agent" counter log prefix "agent-egress-drop " drop
}
}使用 sudo nft -f /etc/nftables.d/agent.nft 应用规则,使用 sudo nft list table inet agentegress 监控计数器,并使用 sudo journalctl -k -g agent-egress-drop 查看丢弃的流量。丢弃计数器持续增加,并且其中出现了预期之外的主机名,这正是此操作要达到的目的。需要明确两点限制。meta skuid 匹配的是拥有 socket 的用户,因此只有在该账户无法切换为其他用户时才有效:如果代理可以免密码执行 sudo,此规则就只能起到建议作用。向任意服务器开放 UDP 53 还会留下数据外传通道,因为数据可以写入查询名称;如果您的威胁模型要求这样做,也应关闭该通道,方法是让代理使用您管理的主机作为解析器。主机名允许列表应放在代理中,而不是 nftables 中,因为 API 端点位于内容分发网络后,其 IP 地址会不断变化。此控制措施的代价是故障和维护:安装软件包、通过 SSH 执行 git 以及代理自身的更新检查都会失败,直到您为它们添加允许规则;之后这份列表也由您负责维护。如果您是在服务器而不是笔记本电脑上配置此方案,相同的账户和防火墙布局也是在 VPS 上安全运行 Claude Code的基础。
一次性机器。 为代理提供一个不包含任何重要凭据的虚拟机(VM),并在任务结束时销毁该虚拟机。这不会减少代理发送的数据,只会减少代理能够访问并发送的数据,而后者通常才是您真正关心的风险。将其与上面的出站规则结合使用,因为一台可以不受限制访问互联网的新 VM 仍然能够连接到您捕获范围内的每台主机。具体方法以及每次都必须重新构建的状态,见在一次性 VM 中运行编码代理;规格配置问题见在 VPS 上运行编码代理。
自行托管模型。 这是唯一能移除推理数据流的控制措施,因为提示词不会离开您的硬件。其成本不可忽视:您无法自行托管闭源模型,因此必须选择开放权重模型,并接受其在困难任务上的能力差距;此外还需要用于提供模型服务的硬件。相关权衡见是否可以自行托管 Claude;主要代理之间的能力差异见Claude Code、Cursor、Codex 和 Copilot 有何不同。
这四种控制措施都不会改变代理获准读取磁盘内容的范围,而推理流量会携带它读取的所有内容。如果工作目录中存在 .env 文件,代理一旦搜索某个变量名,该文件就会发送给模型。将这些内容置于代理无法访问的位置是另一项工作,详见避免机密进入 AI 代理的上下文。
每次更新后要检查的内容
- 将供应商的设置页面和数据使用页面与上次记录的内容进行差异比较,查找新增的开关和新的命名服务。
- 从
/proc/<pid>/environ重新读取进程环境,确认您的选择退出设置仍已应用于正在运行的进程。 - 再次打印项目设置文件,因为
git pull可能会引入同事修改过的配置文件。 - 对一次完整的实际工作会话执行 SNI 捕获,并将主机名列表与上次的列表进行比较。
- 检查防火墙丢弃计数器,因为新目标通常会先出现在这里,然后您才会在其他位置注意到它。
这大约需要十分钟,也是整个流程中唯一不会过时的部分。您在 2026 年 8 月验证过的默认设置,只能说明 2026 年 8 月的情况。捕获结果反映的是今天的情况。
FAQ
我能阻止编码代理将我的代码发送给模型吗?
不能。任何声称可以做到这一点的设置,描述的都是其他功能。将提示词、代理读取的文件以及它执行的命令输出发送到模型端点,是推理的工作方式。因此,唯一可变的是接收方。您可以将代理指向公司的云账户,或指向自行托管的模型,从而更换接收方;也可以限制代理可读取的内容,减少它发送的数据。关闭分析和错误报告完全不会影响这一流程。
如何查看编码代理连接到哪些主机?
让代理以独立的 Linux 用户身份运行,然后在使用代理期间捕获每个新连接的 TLS ClientHello:sudo tshark -i any -f 'tcp port 443' -Y 'tls.handshake.type == 1' -T fields -e ip.dst -e tls.handshake.extensions_server_name。每个连接会显示一行,其中包含目标地址和请求的主机名。使用 sudo tcpdump -ni any 'udp port 53' 交叉检查这些名称,并在 any 上进行捕获,因为本地解析器存根会先在 127.0.0.53 处理查询。应在代理执行实际工作时进行捕获,因为启动 ping 和崩溃报告不会出现在空闲捕获中。
代理运行时我的代理服务器没有显示流量。哪里出了问题?
可能是客户端忽略了 HTTP_PROXY 和 HTTPS_PROXY,也可能是客户端固定了证书并拒绝您的 CA。先使用 curl 测试路径:如果 curl 能通过代理访问互联网,而代理的流量列表中没有出现该代理,那么代理没有使用代理环境变量。某些运行时需要以特定方式提供 CA;Node 尤其只会在进程启动时读取 NODE_EXTRA_CA_CERTS,因此在启动代理后再导出该变量不会产生任何效果。代理服务器无法看到流量时,应改用数据包捕获,因为任何应用设置都无法绕过数据包捕获。
关闭遥测会阻止我的代码被用于训练吗?
不会。分析和崩溃报告与推理使用不同的数据流,因此禁用它们只会移除使用计数器和堆栈跟踪,发送到模型的每个提示词仍与之前完全相同。这些提示词是否会被保留,以及是否会用于训练未来的模型,取决于您的套餐条款;消费者套餐和商业套餐通常有所不同。这属于需要阅读的合同条款,而不是需要捕获的数据包。因此,请查看您套餐的数据使用页面;如果这点很重要,应在首次会话前签订商业协议或零保留协议。