# WARP 出口 IP 怎麼重新整理：Gemini 報地區不支援時的排查方法

> Canonical: https://vxi.me/zh-tw/posts/warp-egress-gemini-location-error/
> Locale: zh-tw
> Published: 2026-10-05
> Updated: 2026-10-05
> Markdown: https://vxi.me/zh-tw/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`。

我會先記下當前出口：

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

正常情況下，你會得到類似：

```text
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 接入層，這篇則更像是“出口已經分流之後，出了問題怎麼快速把範圍縮小”。
