IDE AI 流量正向代理
组织可以将 AISIX 部署在终止 TLS 的出口设备之后,以治理必须继续使用官方服务端点的 IDE 和编码 Agent 流量。本指南以 GitHub Copilot IDE 扩展和 Copilot CLI 为例。AISIX 从该设备接收明文 HTTP 流量,在使用员工凭证将各请求转发到官方上游之前,可以执行访问控制、审计、内容检查和请求限制。
AISIX 不会拦截 TLS,也不会签发证书颁发机构证书。客户端继续使用官方服务端点。流量可以通过显式代理配置或透明拦截到达出口设备;当该设备终止 TLS 时,客户端必须信任该设备的证书颁发机构。
前置条件
请准备以下内容:
- 一个 AISIX 部署:
- 对于 AISIX Cloud,需要一个已关联网关的环境,以及一个具有写入权限范围的管理员 Token。
- 对于开源 AISIX 网关,需要将网关配置为加载声明式资源文件。
- 一个能够保留原始
Host请求头并注入 HTTP 请求头的 TLS 终止出口设备。 - 在客户端计算机上配置代理和证书信任的权限。
- 最新的 GitHub Copilot 允许列表和 Copilot 网络设置。
curl和jq。本地验证使用pipx安装 mitmproxy。
流量拓扑
客户端将 HTTPS 流量发送到出口设备。该设备终止 TLS,保留原始 Host,注入网关 Key 和员工身份,并将解密后的 HTTP 流量发送到 AISIX。AISIX 移除仅供网关使用的请求头,并通过 HTTPS 使用员工的上游凭证转发请求。
网关接受携带原始 Host 的 origin-form 请求,透明重定向和代理链均使用这种形式。当代理链中的上游代理未提供 Host 时,网关也可以读取 URI authority 来接受 absolute-form 请求目标。与 hosts 匹配的路由会先于网关自身的类型化路由执行,因此 /v1/messages 等上游路径会被转发,而不会由网关的 Messages 端点处理。
选择要检查的主机
路由示例在路由的 hosts 字段中使用以下值,以检查 Copilot 推理、代码建议和选定的 GitHub API 流量:
hosts:
- api.githubcopilot.com
- "*.individual.githubcopilot.com"
- "*.business.githubcopilot.com"
- "*.enterprise.githubcopilot.com"
- copilot-proxy.githubusercontent.com
- origin-tracker.githubusercontent.com
- api.github.com
这并不是完整的 Copilot 网络允许列表。身份认证、资产、遥测、实验和编辑器特定服务可能会使用其他主机。请对照 GitHub 最新的允许列表检查出口策略,再决定设备将哪些主机发送到 AISIX,以及允许哪些主机直接访问。
api.github.com 由 Copilot 和其他 GitHub 客户端共享。如果设备分流该主机,所有使用此代理的客户端对该主机发出的请求都可能匹配此路由。如果只有选定的 GitHub API 路径需要经过 AISIX,请从路由中移除该主机,或在设备上缩小分流范围。
配置 Copilot 路由
该路由使用 preserve_host,以便通过一个允许列表转发多个官方主机。header_key 使用设备注入的网关凭证,而 forward_client 则保留员工的上游 Authorization,供 GitHub 使用。
AISIX Cloud
导出 AISIX Cloud 连接信息:
# AISIX_CP 包含 /api,且末尾没有斜杠。
export AISIX_CP="YOUR_AISIX_CLOUD_ADMIN_API_BASE_URL"
export AISIX_TOKEN="YOUR_ADMIN_TOKEN"
export ENV_ID="YOUR_ENVIRONMENT_ID"
创建路由:
ROUTE_RESPONSE=$(curl --fail-with-body -sS -X POST \
"$AISIX_CP/environments/$ENV_ID/passthrough_routes" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "copilot",
"hosts": [
"api.githubcopilot.com",
"*.individual.githubcopilot.com",
"*.business.githubcopilot.com",
"*.enterprise.githubcopilot.com",
"copilot-proxy.githubusercontent.com",
"origin-tracker.githubusercontent.com",
"api.github.com"
],
"preserve_host": true,
"auth_mode": "header_key",
"auth_header_name": "x-aisix-api-key",
"credential_mode": "forward_client",
"identity_header": "x-aisix-user"
}')
export ROUTE_ID=$(printf '%s' "$ROUTE_RESPONSE" | jq -er '.passthrough_route.id')
printf '%s' "$ROUTE_RESPONSE" | jq '.warnings // []'
如果计划专门为此路由关联安全护栏,请保留 ROUTE_ID。
为出口设备创建专用调用方 Key。其明文只会返回一次:
CALLER_RESPONSE=$(curl --fail-with-body -sS -X POST \
"$AISIX_CP/environments/$ENV_ID/api_keys" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"display_name": "Copilot egress device",
"allowed_models": [],
"allowed_routes": ["copilot"]
}')
export EGRESS_DEVICE_KEY=$(printf '%s' "$CALLER_RESPONSE" | jq -er '.plaintext')
printf '%s' "$CALLER_RESPONSE" | jq '.warnings // []'
也可以在控制台中完成相同的操作,入口分别位于环境的 Passthrough Routes 页面和调用方 Key 的 Passthrough route access 部分。上线前请检查返回的所有兼容性警告。警告仅供参考,因此请通过每个网关验证流量。关联路由范围的安全护栏时,也可能产生相应的警告。
开源 AISIX 网关
选择出口设备要注入的 Key:
export EGRESS_DEVICE_KEY="YOUR_GATEWAY_CALLER_KEY"
从网关当前使用的完整资源文件开始配置。将路由和调用方 Key 添加到对应的集合中,并保持不相关的资源不变:
passthrough_routes:
- name: copilot
hosts:
- api.githubcopilot.com
- "*.individual.githubcopilot.com"
- "*.business.githubcopilot.com"
- "*.enterprise.githubcopilot.com"
- copilot-proxy.githubusercontent.com
- origin-tracker.githubusercontent.com
- api.github.com
preserve_host: true
auth_mode: header_key
auth_header_name: x-aisix-api-key
credential_mode: forward_client
identity_header: x-aisix-user
api_keys:
- display_name: egress-device
key_env: EGRESS_DEVICE_KEY
allowed_models: []
allowed_routes: [copilot]
验证组装后的完整文件:
aisix validate --resources resources.yaml
在进程环境中设置 EGRESS_DEVICE_KEY,然后启动或重新创建网关。重新加载无法向已运行的进程添加环境变量。
了解身份认证和归属信息
员工的上游凭证保留在 Authorization 中,因此网关凭证需要使用不同的传递方式:
- 上文所示的
header_key从x-aisix-api-key读取网关 Key,并在转发前移除该请求头。员工的Authorization仍可供 GitHub 使用。 - 当设备无法注入网关 Key 时,可以使用
anonymous。将路由绑定到专用的调用方 Key 主体,并将source_cidrs限制为 AISIX 为这些请求解析出的地址:通常是设备地址;如果启用了真实客户端 IP 解析,则为原始客户端网段。
在这两种模式中,解析出的调用方 Key 都必须在 allowed_routes 中授予 copilot。
按员工追踪流量
AISIX 不会验证 identity_header 中的值。出口设备必须验证员工身份,移除客户端提供的所有 x-aisix-user,并用可信身份覆盖该请求头。AISIX 将受长度限制的值记录为 client_identity,并在转发前移除该请求头。
如果没有此请求头,解析出的来源 IP 通常表示出口设备,而不是员工。要恢复原始客户端地址,请只为确切的可信设备网段和转发请求头配置真实客户端 IP 解析。对于匿名路由,还需要在 source_cidrs 中允许这些解析出的客户端网段。
应用审计、安全护栏和限制
该路由本身不拥有限流或预算配置。控制项从已认证的调用方解析,并在支持时从其他关联范围解析。
请求限制
调用方 API Key、团队和成员的请求限制会在分发前应用。透传路由没有限流字段或路由策略范围。如果不同主机组需要不同的请求限制或并发限制,请使用不同的调用方 Key。
从可识别协议载荷中提取的 Token 用量会记录在用量事件中,但不会递增 tpm 或 tpd 计数器。已经耗尽的共享 Token 计数器可以拒绝请求,但透传流量不会推进该计数器。对于 SSE,AISIX 返回流式响应时会释放并发配额,而不是等到数据流结束时才释放。
预算
在 AISIX Cloud 中,已经应用于解析后调用方的预算会在分发前检查。透传用量目前没有模型 ID,以零成本记录,也不会 向预算账本增加支出。开源 AISIX 网关没有本地预算资源。
安全护栏
在 AISIX Cloud 中,使用 Passthrough routes 范围关联安全护栏,可以只检查此路由。环境、调用方 Key 和团队范围的安全护栏也可能应用。
开源资源文件通过 guardrail_attachments 集合声明挂载关系,因此文件中定义的安全护栏只有在 Attachment 将其作用域覆盖到此路由时才会检查该路由的流量:可以使用 scope_type: env 覆盖整个环境,也可以使用 scope_type: passthrough_route 并指定此路由。
请求被拦截时,会在调用上游之前返回 422。缓冲响应会在交付前接受检查。SSE 响应开始后,如果触发拦截,数据流会以 SSE content_filter 错误帧结束。启用暂缓发送的安全护栏可能会在检查期间延迟数据帧。
内容和用量导出
对于成功转发的流量,配置了 content_mode: full 的可观测性导出器会以字符串内容接收请求体,而不是接收服务提供方协议载荷的标准化副本。当缓冲响应符合支持的提取格式时,会记录提取出的文本;否则,会将响应体记录为文本。对于流式响应,会记录累积提取出的文本;不透明的数据载荷也会作为文本保留。所有采集仍受已配置的限制约束。
采集的内容只会发送到支持内容的导出器。用量事件包含匹配的路由、调用方、记录的 Token 数量和 client_identity。当前 AISIX Cloud 的 Request Logs 界面会显示调用方和 Token 元数据,但不会显示 passthrough_route_name 或 client_identity。
了解 Copilot CLI 流量
GitHub Copilot CLI 是一个能够编辑文件、运行 Shell 命令、选择模型并使用其内置 GitHub MCP 服务器的 Agent。其确切的网络端点和协议载荷选择取决于版本,不属于本 AISIX 配置契约的一部分。
AISIX 会识别 messages、input 和 prompt 请求格式,以便为安全护栏提取内容并提取用量信息。其他流量(包括 JSON-RPC 和普通 GitHub API 调用)均视为不透明流量,并在不转换请求体协议的情况下转发。因此,选定的主机路由不需要协议字段。
GitHub 文档将 /model、/mcp、/usage 和 /context 列为 CLI 命令,但具体命令是否发送网络流量可能随客户端版本变化。请在实际环境中验证当前客户端行为,不要依赖固定的端点清单。
使用 mitmproxy 验证开源网关
以下本地练习使用 mitmproxy 作为终止 TLS 的设备。本地快速入门网关监听 127.0.0.1:3000,mitmproxy 监听 127.0.0.1:8888。
-
使用上面配置的 Copilot 路由、调用方 Key 和
EGRESS_DEVICE_KEY启动 网关。 -
安装并验证 mitmproxy:
pipx install mitmproxymitmdump --version -
将以下设备脚本保存为
mitm_to_aisix.py。该脚本会分流选定的主机,恢复原始Host,注入网关 Key 和用户身份,并保持 SSE 流式传输:mitm_to_aisix.pyimport osfrom mitmproxy import httpAISIX_HOST, AISIX_PORT = "127.0.0.1", 3000GATEWAY_KEY = os.environ["EGRESS_DEVICE_KEY"]IDENTITY = os.environ.get("AISIX_CLIENT_IDENTITY", "alice@example.com")COPILOT_HOSTS = {"api.githubcopilot.com","copilot-proxy.githubusercontent.com","origin-tracker.githubusercontent.com","api.github.com",}COPILOT_SUFFIXES = (".individual.githubcopilot.com",".business.githubcopilot.com",".enterprise.githubcopilot.com",)def _matches_one_label(host: str, suffix: str) -> bool:if not host.endswith(suffix):return Falselabel = host[: -len(suffix)]return bool(label) and "." not in labeldef _diverted(host: str) -> bool:return host in COPILOT_HOSTS or any(_matches_one_label(host, suffix) for suffix in COPILOT_SUFFIXES)def request(flow: http.HTTPFlow) -> None:host = flow.request.pretty_hostif not _diverted(host):returnflow.request.host = AISIX_HOSTflow.request.port = AISIX_PORTflow.request.scheme = "http"flow.request.headers["host"] = hostflow.request.headers["x-aisix-api-key"] = GATEWAY_KEYflow.request.headers["x-aisix-user"] = IDENTITYdef responseheaders(flow: http.HTTPFlow) -> None:if "text/event-stream" in flow.response.headers.get("content-type", ""):flow.response.stream = True设置
flow.request.host会改写Host请求头,因此脚本随后会恢复上游主机。如果没有这一行,请求将无法匹配任何主机路由。响应钩子可防止 mitmproxy 将 SSE 缓冲成一个延迟响应。 -
在环境中设置网关 Key,并启动代理:
export AISIX_CLIENT_IDENTITY="alice@example.com"mitmdump -s mitm_to_aisix.py --listen-port 8888mitmproxy 第一次启动时,会创建后续步骤使用的本地证书颁发机构。
-
在另一个终端中,使用已获准执行测试请求的凭证,对代理分流、路由匹配以及到 GitHub 的转发进行冒烟测试:
curl -x "http://127.0.0.1:8888" \--cacert ~/.mitmproxy/mitmproxy-ca-cert.pem \-H "Authorization: Bearer YOUR_GITHUB_TOKEN" \"https://api.github.com/user"如果
401中提到x-aisix-api-key,说明设备 Key 未传入。如果返回403,说明该 Key 未被授予copilot。空的404通常意味着原始主机与路由不匹配。 -
配置 Copilot 客户端使用 mitmproxy,并信任其证书颁发机构。Copilot 会检查标准代理变量和
NODE_EXTRA_CA_CERTS:export HTTPS_PROXY="http://127.0.0.1:8888"export HTTP_PROXY="http://127.0.0.1:8888"export NODE_EXTRA_CA_CERTS="$HOME/.mitmproxy/mitmproxy-ca-cert.pem"copilot对于编辑器插件,请配置其 HTTP 代理设置,并让编辑器进程使用同一个证书颁发机构。请按照 GitHub 最新的网络设置文档配置实际使用的客户端。
-
如有需要,请配置 OTLP/HTTP 导出器,发送一个普通请求并检查导出的 Span。确认其中记录了
aisix.passthrough.route_name: copilot,并将注入的身份记录为aisix.client_identity。
若要在开源部署中检查 DLP,请声明关键词安全护栏并添加 Attachment:使用 scope_type: env 覆盖整个网关,或使用 scope_type: passthrough_route 并指定此路由。在 AISIX Cloud 中,也请先以同样方式将安全护栏挂载到此路由,再测试被拦截的提示词。
适用范围和限制
- 透传路由不会转发 WebSocket 升级请求;请从设备分流规则中排除相应主机或路径。
preserve_host以 443 端口上的https://<matched-host>为目标。- AISIX 不执行 TLS 拦截,也不提供证书颁发机构工具。
- Copilot 主机和客户端行为会独立于 AISIX 发生变化。部署或升级集成时,请重新检查 GitHub 的允许列表和客户端网络文档。