upstream 是可信出口通道的锚点,仅负责静态收敛至固定内网ip+端口的合规后端,不参与过滤决策;真正的“洗白”由网关层在 proxy_pass 前通过请求头重写、参数校验、方法限制、tls强制及日志审计等策略统一执行。

配置 upstream 配合安全网关实现出站流量“洗白”(即合法化、可控化、可审计的出口),核心不是让 upstream 做过滤,而是把它作为**可信出口通道的锚点**,再由网关层(如 Nginx、服务网格出口网关)统一执行策略。真正起过滤、校验、重写作用的是网关逻辑,upstream 只负责稳定、安全地指向唯一合规后端。
明确 upstream 的角色:只做可信目标收敛,不做动态决策
upstream 块本身不处理请求内容,它的作用是定义一组静态、可验证、受控的内网目标地址。所有出站流量必须经由它转发,杜绝直连公网或不可信域名:
- ✅ 必须使用固定内网 IP + 明确端口,例如:
server 192.168.10.100:8443 max_fails=2 fail_timeout=30s; - ❌ 禁用变量代理(如
proxy_pass https://$host)和上游含公网域名的定义(如server api.alipay.com:443),防止 DNS 劫持或注入绕过 - ✅ 若需灵活切换,用
set $upstream "192.168.10.100"; proxy_pass https://$upstream:8443;,避免 nginx 解析阶段变量污染 - ✅ 启用被动健康检查(
max_fails/fail_timeout),确保故障自动隔离,不把异常流量透传出去
在 proxy_pass 前加网关级清洗层
真正的“洗白”发生在 location 或 server 块中,利用 Nginx 内置指令对即将发往 upstream 的请求做标准化与过滤:
- 强制清理/重写请求头:
proxy_set_header X-Forwarded-For ""; proxy_hide_header Server; proxy_set_header User-Agent "clean-agent/1.0"; - 校验并截断非法参数:
if ($args ~* "(union|select|<script>|/etc/passwd)") { return 403; }</script>(注意:避免在 location 外滥用 if) - 限制出站方法与路径:
if ($request_method !~ ^(GET|POST|HEAD)$) { return 405; },非必要不出 PUT/DELETE - 启用请求体校验(需
http_ssl_module和合理client_max_body_size),防大文件上传穿透
对接服务网格出口网关(ASM/istio 场景)
当使用 ASM 或类似服务网格时,upstream 实际被抽象为 ServiceEntry + EgressGateway,此时“洗白”由控制面统一编排:
- 关闭默认
ALLOW_ANY,强制开启REGISTRY_ONLY,未显式声明的服务条目一律拦截 - 为每个外部依赖创建
ServiceEntry,仅允许指定 host、port、协议,并标注exportTo: ["."]控制可见范围 - 所有出站流量劫持到
egressgatewayPod,由其执行 mTLS、日志审计、速率限制等策略后再发往真实上游 - 配合
DestinationRule强制出口网关与外部服务间使用 TLS,避免明文外泄
补充关键加固项
仅靠 upstream + proxy_pass 不足以完成洗白,还需配套机制堵住旁路:
- 操作系统层禁用非必要 outbound 端口(如用 iptables 或 Azure NSG 限制 Pod 出向仅允许 443/8443)
- Nginx 中禁用 resolver(
resolver 127.0.0.1 valid=30s; # 注释掉或删除),彻底切断运行时 DNS 查询能力 - 若业务需调用多个外部域名,统一收口到一个内部 DNS 代理(如 CoreDNS + 白名单策略),再由 upstream 指向该代理
- 记录完整出站日志:
log_format egress '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $upstream_addr $request_time';











