AWS Bedrock mantle gateway 纯透传代理 —— 让你借代理的出口 IP 绕过 mantle 对 Anthropic (Claude)模型的源 IP 地域封锁。
mantle(bedrock-mantle.<region>.api.aws)对 Anthropic 模型按请求源 IP 的地理位置封锁:从受限
地区(如中国大陆)的 IP 调 Claude 会返回 400 Access to Anthropic models is not allowed,而 GLM /
MiniMax 等 OpenAI 兼容模型放行。本代理部署在不受限地区(如东京 ap-northeast-1),你把 mantle
host 换成代理域名、带上你自己的 mantle Bearer token,请求经代理转发,mantle 看到的源 IP 变成
代理所在地 → Claude 放行。
通用开放中继:代理不持任何密钥、不做调用方鉴权、不绑定任何具体调用方。每个人用自己的 token,quota / 计费落在各自 token 上。它只是一个纯转发器。
只需把你原来直连 mantle 的代码里的 host 换成代理域名,其余(路径、Bearer token、请求体)完全不变。
1. 换 host —— 原来:
https://bedrock-mantle.ap-northeast-1.api.aws
换成:
https://proxy-mantle.example.com
2. 带上你自己的 Bearer token(代理原样透传 Authorization,不持有、不校验)。
3. 照常调两条路径之一:
Claude(Anthropic Messages API):
curl -N https://proxy-mantle.example.com/anthropic/v1/messages \
-H "Authorization: Bearer $YOUR_MANTLE_TOKEN" \
-H "Content-Type: application/json" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-workspace-id: default" \
-d '{
"model": "anthropic.claude-haiku-4-5",
"max_tokens": 256,
"stream": true,
"messages": [{"role": "user", "content": "你好"}]
}'GLM / MiniMax 等(OpenAI 兼容 Chat Completions):
curl -N https://proxy-mantle.example.com/v1/chat/completions \
-H "Authorization: Bearer $YOUR_MANTLE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "zai.glm-4.7-flash",
"max_tokens": 256,
"stream": true,
"messages": [{"role": "user", "content": "你好"}]
}'模型 ID 用 mantle 短名(如 anthropic.claude-haiku-4-5),不是 us.anthropic.*-vX:0 那种
inference-profile 格式。流式(stream: true)与非流式都支持。
- 纯透传:path / query / 请求体 /
Authorization及其它头原样转发;上游响应(状态码 / 头 / 体) 原样回传。代理不解析、不改写请求体。 - 双向流式(SSE):请求体和响应体都流式,不缓冲。首字节延迟与直连同量级。
- 上游错误如实透传:mantle 返回什么状态码(含 4xx / 5xx),代理原样回,不改写、不自动重试。
- 超时:上游连接/读超时 →
504;上游连接/TLS 失败 →502。 GET /healthz→200(存活探针,不依赖上游)。
这是有意的开放转发器(公网入口 + 无调用方鉴权 + 纯透传),可接受,因为:
- 代理不持任何密钥——没 token 就调不动(上游 mantle 直接 401/400),代理不放行、不伪造。
- quota / 计费落在调用方各自的 token 上;token 泄露风险由持有者承担,与代理无关。
- 代理只转发到硬编码的有界上游集合(2 个固定 host 模板 × 合法 region 语法,不是任意 URL 代理),
忽略入站
Host→ 无 SSRF 面(见specs/002-multi-upstream-routing.md)。 - 过路凭据不留痕:代理绝不把
Authorization或请求/响应体写入日志。 - 防滥用 = 入口 WAF per-IP 限流(防单 IP 霸占带宽);分布式滥用由上游按各 token quota 兜底。
使用建议:token 只经 HTTPS 传输、不要写进日志 / 客户端二进制;它是短时 Bearer,妥善保管。
你的代码 (host = proxy-mantle.example.com, 带你的 Bearer token)
│ HTTPS
▼
[Route53] → [公网 ALB :443 (ACM, idle 300s, access log→私有S3)]
│ └ REGIONAL WAF (per-IP 限流)
▼
[ECS Fargate ×2 (ARM64, 常驻无冷启动) Rust 纯透传代理]
│ 出站 HTTPS (硬编码上游, TLS 验证, TCP keepalive)
▼
bedrock-mantle.<部署region>.api.aws ← 上游跟随部署 region:东京→东京、美国→us endpoint
- ALB + ECS Fargate(不用 Lambda Function URL / API Gateway):ALB 原生透传 SSE 流式;Fargate
desiredCount≥1常驻无冷启动。 - 上游 endpoint 跟随部署 region:部署到东京 → 上游东京 mantle;部署到美国 → 上游 us mantle。
已验证(2026-07-10,美区 sandbox vs 北京 EC2 对照):传统 Bedrock Runtime
(bedrock-runtime.<region>.amazonaws.com)对 Anthropic 模型的地域封锁与 mantle 同源——按源 IP
地理位置封锁,错误文案一致(Access to Anthropic models is not allowed from unsupported countries...),
非 Anthropic 模型(如 Amazon Nova)不受影响。且传统 Bedrock 支持纯 Authorization: Bearer <API Key>
鉴权(IAM create-service-specific-credential --service-name bedrock.amazonaws.com 生成的长期
key,走 REST POST /model/<id>/converse),不必 SigV4——鉴权模型与 mantle 几乎一致,东京出口理论上同样能绕。
已实现,不需要独立部署:同一个代理 endpoint 已支持按 ?mantle=®ion= 参数切换到传统
Bedrock(见下「单 endpoint 同时代理 mantle 与传统 Bedrock」),不必另起一套栈。
模型 ID 格式不同,调用方需自行注意(代理不解析/不转换 body,这是调用方侵入,不是代理要处理的事):
- mantle:裸短名,如
anthropic.claude-sonnet-4-6。 - 传统 Bedrock:新一代模型的 on-demand 调用大多要求带 scope 前缀的 inference profile ID,如
jp.anthropic.claude-sonnet-4-6(区域级)或global.anthropic.claude-sonnet-4-6(全球级);裸短名 会报... isn't supported. Retry your request with the ID or ARN of an inference profile。
不带任何参数时,代理行为不变(转发到部署时配置的 UPSTREAM_HOST)。带上这两个白名单参数,可以在
同一个代理 endpoint 上切换上游:
# 显式选传统 Bedrock + us-east-1(注意:model ID 要用能跨区域的 global. scope,
# 不能用锁区域的 jp. scope 去配一个不匹配的 region)
curl -N "https://proxy-mantle.example.com/model/global.anthropic.claude-sonnet-4-6/converse?mantle=false®ion=us-east-1" \
-H "Authorization: Bearer $YOUR_BEDROCK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"messages":[{"role":"user","content":[{"text":"你好"}]}]}'
# 只选 region,mantle 默认 true(走 mantle 家族)
curl -N "https://proxy-mantle.example.com/anthropic/v1/messages?region=us-west-2" \
-H "Authorization: Bearer $YOUR_MANTLE_TOKEN" ...mantle=false→ 上游 =bedrock-runtime.<region>.amazonaws.com(传统 Bedrock);缺省或mantle=true→ 上游 =bedrock-mantle.<region>.api.aws(mantle,现状行为)。region缺省时使用代理部署 region。- 这两个参数是代理自己的路由控制参数,转发前会被剥除,不会出现在上游收到的请求里。
region只校验命名语法(如xx-name-digit),不校验该 region 是否真实存在;传入一个语法合法 但不存在的 region 会在连接阶段失败,代理返回 502(而不是别的错误)。
完整行为契约见 specs/002-multi-upstream-routing.md。
# Rust 代理(纯逻辑 + 集成测试,wiremock fake 上游)
cargo test
cargo build --release
# 本地起代理(默认上游东京 mantle)
PORT=8899 ./target/release/mantle-proxy
# 另开终端:curl http://127.0.0.1:8899/anthropic/v1/messages ...(带你的 token)
# CDK 基础设施
cd infra && npm install
npm test # CDK 单测(jest,锁 idle 300s / WAF / ARM64 / 上游跟随 region / 无 Function URL)
npx cdk synth # 合成 + cdk-nag 合规扫描有两种部署模式,按域名 zone 是否在部署账号选:
CDK 自动 lookup zone、签 ACM 证书(DNS 验证)、建 alias:
cd infra
AWS_PROFILE=<profile> AWS_REGION=ap-northeast-1 \
CDK_DEFAULT_REGION=ap-northeast-1 CDK_DEFAULT_ACCOUNT=<account> \
npx cdk deploy --require-approval never \
-c domainName=<fqdn> -c zoneName=<zone>代理 ALB 在东京(Global 账号),但域名 zone 在别的账号(如 example.com 权威 NS 在中国区
Route53,是中国区可靠解析的必要条件)。CDK(Global 账号)无法 lookup 该 zone / 自动验证 / 建 alias,
须手动桥接:
- 在东京 ACM 手动签证书(给该 FQDN),拿验证 CNAME:
CERT=$(AWS_PROFILE=<global> aws acm request-certificate \ --domain-name proxy-mantle.example.com --validation-method DNS \ --region ap-northeast-1 --query CertificateArn --output text) AWS_PROFILE=<global> aws acm describe-certificate --certificate-arn "$CERT" \ --region ap-northeast-1 --query 'Certificate.DomainValidationOptions[0].ResourceRecord'
- 用能管该 zone 的凭据把验证 CNAME 写进 zone,等证书
ISSUED(ACM 自动续期也走同记录)。 - 部署时传
certificateArn(此时 stack 不 lookup zone、不建 alias):AWS_PROFILE=<global> AWS_REGION=ap-northeast-1 \ CDK_DEFAULT_REGION=ap-northeast-1 CDK_DEFAULT_ACCOUNT=<account> \ npx cdk deploy --require-approval never \ -c domainName=proxy-mantle.example.com -c certificateArn="$CERT"
- 部署后取输出的
AlbDns,在 zone 里建proxy-mantle.example.comCNAME → ALB DNS。⚠️ CNAME 漂移:跨账号不能用 Route53 alias(只能 CNAME 指 ALB 官方 DNS 名)。ALB 若被重建 (DNS 名变),须手动更新该 CNAME。
上游 endpoint 跟随部署 region(东京→东京 mantle、美国→us endpoint),或 -c upstreamHost=<host> 显式覆盖。
| 变量 | 默认 | 说明 |
|---|---|---|
UPSTREAM_HOST |
bedrock-mantle.<region>.api.aws |
上游 mantle host(CDK 按部署 region 注入) |
PORT |
8080 |
监听端口 |
CONNECT_TIMEOUT_SECS |
10 |
上游连接超时 |
READ_TIMEOUT_SECS |
90 |
上游 TTFB 超时(SSE 拿到响应头后不再计整流) |
TCP_KEEPALIVE_SECS |
90 |
出站 TCP keepalive(防中间盒掐断长 idle SSE) |
行为契约见 specs/001-tokyo-mantle-proxy.md(OpenSpec 风格
Requirement / Scenario)。经 codex + Kiro 双评审收敛。
Apache-2.0