# WARP 出口 IP 怎么刷新：Gemini 报地区不支持时的排查方法

> Canonical: https://vxi.me/posts/warp-egress-gemini-location-error/
> Locale: zh-cn
> Published: 2026-10-05
> Updated: 2026-10-05
> Markdown: https://vxi.me/posts/warp-egress-gemini-location-error.md

如果你把 Google / Gemini 这类流量单独分到 Cloudflare WARP，迟早会碰到一种很迷惑的故障：WARP 明明是 `Connected`，网页甚至还能正常打开，但某个 Gemini API 或客户端突然开始返回：

```text
HTTP 400
FAILED_PRECONDITION
User location is not supported for the API use.
```

我这次遇到的就是这种情况。更容易误导人的地方在于，Gemini 网页端仍然正常，出问题的是另一个走 Gemini 后端的客户端。第一反应很容易变成“是不是账号被限制了”“是不是 Xray 路由坏了”“是不是要重配 Nginx”，但最后真正有效的动作反而很小：先确认 **Gemini 实际看到的 WARP 出口**，然后重连 WARP，再比较前后的出口变化。

这套排查方法适合一种很具体的架构：服务器上的 WARP 以本机 SOCKS5 代理运行，Xray 只把指定的 Google / Gemini TCP 流量送进这个 SOCKS5。入口可能还是 Cloudflare + Nginx + VLESS/WS，但入口和出口是两件完全不同的事。

## 真正要看的不是 VPS IP，而是最后一跳 WARP 出口

我现在更习惯先把链路画出来：

```text
客户端
  ↓
Cloudflare / Nginx / Xray
  ↓
Google / Gemini 流量
  ↓
127.0.0.1:40000
  ↓
Cloudflare WARP
  ↓
Gemini
```

这里最容易判断错的是 VPS 的 Origin IP。它只是服务器自己的公网地址；只要 Gemini 流量已经被 Xray 送进 WARP，Google 最终看到的就应该是 WARP 出口，而不是这台 VPS 的原生出口。

Cloudflare 对 WARP Local proxy 的定义也很明确：只有显式配置到 HTTPS 或 SOCKS5 本地代理的应用流量会经过 WARP，其余流量仍按普通网络连接出去。所以排查时，最好直接对这个 SOCKS5 做测试，而不是看浏览器、VPS 公网地址，或者只看 `warp-cli status`。

我会先记下当前出口。这里用 `console` 把“实际要执行的命令”和“返回结果”放在同一个现场里：

```console
$ curl -s --socks5-hostname 127.0.0.1:40000 https://www.cloudflare.com/cdn-cgi/trace | grep -E '^(ip|loc|warp)='
ip=<warp-egress-ip>
loc=US
warp=on
```

正常情况下会看到上面三个字段。

这里三个字段的意义不一样：

- `warp=on` 只能证明这次请求确实经过了 WARP。
- `ip=` 是目标网站实际看到的出口地址，也是这次排查最值得记录的值。
- `loc=` 是一个地理线索，但不是“这个客户端一定会接受”的保证。

最后一点很重要。2026 年 Google AI Developers Forum 上也有开发者报告：服务器明明位于 Gemini 支持地区，外部地理库看起来也正常，Gemini API 仍可能返回同样的 `User location is not supported`。所以 `loc=US`、`loc=CA` 这种结果更适合拿来判断方向，而不是直接当成最终结论。

## 我最后用的恢复动作很简单：记录、重连、再比较

如果 WARP 本身健康，而错误又明显指向 location / eligibility，我不会先动 Xray、Nginx 或 Cloudflare 入口。先做一次最小变化的 WARP 重连：

```bash
echo "=== BEFORE ==="
curl -s --socks5-hostname 127.0.0.1:40000 \
  https://www.cloudflare.com/cdn-cgi/trace \
  | grep -E '^(ip|loc|warp)='

warp-cli --accept-tos disconnect
sleep 5
warp-cli --accept-tos connect
sleep 10

echo "=== AFTER ==="
curl -s --socks5-hostname 127.0.0.1:40000 \
  https://www.cloudflare.com/cdn-cgi/trace \
  | grep -E '^(ip|loc|warp)='
```

这次实际故障里，WARP 重连前后拿到了不同的共享出口，`warp=on` 仍然成立，位置字段也保持在支持区域；重新测试客户端以后，原来的地区错误消失了。

这个结果能说明的是：**旧 WARP 出口是触发因素之一**。它并不能证明“某个 WARP IP 永远有问题”，也不能反推出 Gemini 的内部风控或地理分类规则。对排障来说，能把问题从“整条代理链”收窄到“最后一跳出口”已经很有价值。

如果重连以后 IP 没变，我一般再尝试一次，但不会把下面这组命令当成常规换 IP 手段：

```bash
warp-cli registration delete
warp-cli registration new
```

注册身份和共享公网出口不是一一绑定关系。删除注册再创建，既不能保证换到新出口，还会把一个原本健康的 WARP 注册状态重新引入变量。对线上节点来说，这个代价通常不值得。

我更愿意把顺序固定成：

```text
确认 WARP SOCKS5 可用
        ↓
记录 ip / loc / warp
        ↓
disconnect / connect
        ↓
再次记录出口
        ↓
出口变化 → 重测 Gemini / 客户端
        ↓
仍失败 → 再查路由、IPv4/IPv6、DNS 或服务端分类
```

这样做的好处是，每一步只改变一个变量。尤其是当你的入口已经稳定运行时，不要因为一个 `FAILED_PRECONDITION` 就顺手改 Nginx、VLESS、Cloudflare DNS 和 Xray 路由。改得越多，越难知道到底是哪一步恢复了。

还有一个边界需要说清楚：普通 WARP 并不是可控的住宅代理池。Cloudflare 官方明确写着，WARP 不用于伪装成来自另一个国家；普通共享出口也不能让你指定“美国某城市”或某个固定公网 IP。你可以通过断开 / 重连观察共享出口是否变化，但不能把这种变化当成确定性的轮换能力。

如果你的业务真正需要固定、独享、可加入白名单的出口，Cloudflare 提供的是 Zero Trust Enterprise 的 Dedicated Egress IP。它是账户独享的静态出口，并绑定具体 Cloudflare 数据中心；这和普通 WARP 共享出口不是一个产品层级。对个人开发者来说，大多数时候没必要因为偶发的 Gemini 分类问题直接升级到这一步，但它至少说明了“稳定固定出口”应该在哪一层解决。

我现在把这类故障分成两种来想：如果连 WARP SOCKS5 自己都不通，那是 WARP 服务或本机代理问题；如果 SOCKS5 正常、`warp=on`，但 Gemini 仍然返回 location 错误，就把注意力放到出口地址、协议路径和上游分类，不要先重做整条入口。

如果你也在把多个 AI 工具收进自己的代理层，可以继续看 [Codex 怎么通过 CLIProxyAPI 反代：Docker 部署、OAuth 登录和客户端配置](/posts/cliproxyapi-codex-docker-proxy/)。那篇更偏统一 AI 接入层，这篇则更像是“出口已经分流之后，出了问题怎么快速把范围缩小”。


## Runbook：Gemini 报 location 不支持时

如果入口本来稳定，我会先只动最后一跳，不要同时改 Nginx、VLESS、DNS 和 Xray：

1. 直接通过 WARP SOCKS5 请求 Cloudflare trace，记录 `ip / loc / warp`。
2. `warp=on` 但 Gemini 仍报错：记录当前出口，再做一次 `disconnect / connect`。
3. 出口变化后立即重测同一个 Gemini 客户端，别同时修改别的链路。
4. 出口没变，可以再重连一次；不要把 `registration delete/new` 当普通轮换 IP 手段。
5. 仍失败时，再查 Xray 分流、IPv4/IPv6、DNS 和上游服务自己的地区分类。
6. 如果业务需要固定、可白名单的出口，应该换到真正的 Dedicated Egress 方案，而不是依赖共享 WARP 出口偶然变化。
