如何测试 NO_PROXY 规则,防止流量绕过代理

互联网请求通道经过代理检查点,只有少量获批目标使用受控直连路径

NO_PROXY 是出口策略,不是无害的便利变量。一个过宽的域名后缀、通配符、大小写变量冲突,或运行时特有的解析方式,都可能让本应经过代理的请求直接访问目标。后果包括出口 IP 异常、审计证据缺失、区域结果不一致,甚至代理故障被静默直连掩盖。

下面是一套可重复的上线前测试方法。所有测试必须只针对已获授权的网络与端点。

先确认进程实际生效的配置

不要只看部署模板,要记录运行进程真正读取到的值:

  • 大写与小写的代理环境变量;
  • 命令行中的代理和绕过参数;
  • 应用或 SDK 使用的代理 Agent;
  • 容器、无服务器平台和服务管理器注入的环境;
  • 操作系统自动发现的代理设置;
  • 允许或阻止直连出口的网络策略。

修改环境变量后,应重启或回收测试实例。长时间运行的进程可能仍保留旧环境或旧连接池。

不要假设所有客户端都按同一方式解析

不同 HTTP 栈没有统一语义。当前 Node.js 内置代理支持在大小写变量同时存在时优先使用小写变量,并可处理精确主机、域名后缀、通配符、IP、IP 范围以及主机加端口规则;同时还需要通过文档规定的环境变量、命令行、全局配置或 Agent 显式启用。

curl 支持主机、域名、通配符和 CIDR。IPv6 数字地址不加方括号。libcurl 的空 no-proxy 选项表示所有主机重新使用代理,这与通配符“全部绕过代理”正好不同。

Python urllib 可从环境变量和操作系统发现代理;文档中的 no_proxy 使用逗号分隔的主机名后缀,并可附带端口。自定义 ProxyHandler 会改变或关闭这种自动发现。

因此,应把每种运行时及版本视为独立契约并逐一验证。

建立路由决策矩阵

准备两个自有测试端点:一个必须经过代理,一个明确获准直连。还要加入“不应命中”的反例,以便发现规则意外扩张。

测试项策略意图预期路由
精确主机名仅一个内部服务直连
同级主机名不应继承精确匹配代理
域名后缀获批内部命名空间直连
相似后缀不得误匹配代理
主机加端口仅批准端口绕过按端口区分
IPv4 地址单个批准端点直连
IPv4 CIDR/范围客户端支持时使用直连
IPv6 地址单个批准端点直连
IPv6 CIDR/范围视客户端能力而定客户端特定
通配符仅隔离诊断全部直连
空值不设置绕过代理
大小写冲突明确优先级客户端特定

同时测试空格、尾随点、国际化域名、Punycode、重定向、DNS 别名,以及在无关域名中包含相同字符串的情况。每次匹配都应当狭窄、明确且有记录。

用证据确认路径,不靠响应码猜测

HTTP 200 只能证明可达,不能证明经过了哪条路径。至少收集两种独立证据:

  1. 代理侧只会在请求经过代理时出现的合成请求标识;
  2. 目标侧观测到的已知代理出口或已知直连测试出口。

建议只记录别名和分类:

runtime_version
policy_hash
test_case
destination_alias
expected_route
proxy_observed
egress_class
status_class
latency_bucket

两侧证据不一致就应判定失败,不能用成功响应覆盖路由偏差。

在真实部署边界中测试

测试必须运行在生产所用的容器镜像、主机类型和启动流程内。本地终端可能存在不同的变量大小写、继承环境或系统代理设置。至少验证:

  1. 全新进程启动;
  2. 连接复用后的热进程;
  3. 配置变更并按要求重启;
  4. 代理不可用时不会静默直连;
  5. 从允许主机重定向到未允许主机;
  6. 适用场景下的 IPv4 与 IPv6 解析。

Node.js 应分别测试全局代理配置和应用自定义 Agent;curl 应比较环境变量与显式参数;Python 应确认自定义 opener 是否覆盖环境发现。

让意外直连以失败结束

稳健方案应使用短小、经审核的绕过清单,并在网络层阻止意外直连:

  • 出站 Web 流量默认走代理;
  • 仅使用精确主机或范围很窄的后缀例外;
  • 生产持久配置禁止通配符;
  • 启动时拒绝含糊或格式错误的条目;
  • 对直连目标及端口设置允许清单;
  • 重试次数有界且不得切换为直连;
  • 在脱敏遥测中记录策略哈希;
  • 分阶段上线并准备已知可用的回滚配置。

不要把代理凭证放在 URL、日志或测试夹具中。如果全局变量无法安全表达需求,应改用按目标显式路由。

上线检查清单

  • [ ] 已获取大小写变量的实际生效值。
  • [ ] 已记录运行时和客户端版本。
  • [ ] 已测试精确主机、后缀、端口、IPv4 与 IPv6。
  • [ ] 已识别不受支持的 CIDR 或范围语法。
  • [ ] 已验证通配符和空值行为。
  • [ ] 重定向不会逃离预期路由。
  • [ ] 代理侧与目标侧证据一致。
  • [ ] 代理故障不会触发直连降级。
  • [ ] 网络层限制了直连出口。
  • [ ] 日志不含凭证或敏感标识。
  • [ ] 已测试金丝雀重启和回滚。

相关 98IP 内容还包括代理故障转移恢复演练curl 代理认证 407 排错代理凭证轮换

常见问题

.example.internal 是否只匹配一个主机?

通常它表示后缀,而不是单一精确主机,但具体行为取决于客户端。应同时测试父域、子域、同级主机和相似域名。

* 能否作为临时默认值?

不安全。常见客户端会因此让所有目标绕过代理。仅在隔离诊断环境使用,并阻止它进入生产持久配置。

防火墙能替代应用测试吗?

不能。网络限制是重要的失败关闭控制,但应用层测试能在错误变成事故前发现配置偏差。

代理请求失败后是否应直接重试?

除非独立批准的策略明确允许,否则不应这样做。静默直连会改变身份、地域和审计范围,应使用有界代理重试并明确失败。

合规说明

仅测试自有或已获授权的基础设施与端点。绕过清单应限于合法业务需求,遵守目标服务条款和速率限制,尽量减少数据收集,不得利用路由控制规避访问限制或掩盖滥用行为。

资料说明:Node.js 项目 HTTP 文档;curl 项目 curl 手册与 CURLOPT_NOPROXY 文档;Python Software Foundation urllib 文档。查阅日期:2026 年 9 月 5 日。