FIELD NOTE / SINGLE ENTRYNO SIGNAL / NO PROBLEM

Ubuntu 跑 Codex CLI:GCP SOCKS5 + pproxy 繞過香港地區封鎖(systemd 持久化)

讓 Ubuntu 上的 Codex CLI 在香港穩定連上 OpenAI,繞過地區封鎖,並把整套代理做成 systemd 常駐:開機自啟、斷線重連、日常使用零手動設定。2026-09-03 實測驗證,用 ChatGPT Plus 訂閱帳號登入,不另收費。

為什麼需要代理

同一個請求,從不同出口結果完全不同:

出口 api.openai.com 結果
本機(香港 IP) 403 地區封鎖
GCP 美國 VM 401(正常,只差憑證)

Codex CLI 會把底層的 403 包裝成「We’re currently experiencing high demand」的誤導訊息——看起來像 OpenAI 高負載,實際是地區封鎖。診斷時要用 curl 直連看真實 HTTP code,別被這句騙了。

架構

codex CLI (Bun)
  |  HTTP proxy
  v
pproxy  127.0.0.1:8080
  |  轉 SOCKS5
  v
ssh -D 1080  隧道
  |
  v
GCP US VM  35.208.247.13
  |
  v
api.openai.com

最大的坑:Bun 只吃 HTTP 代理

Codex CLI 的 runtime 是 Bun,而 Bun 不支援 SOCKS5。所以光建 ssh -D 隧道是不通的,必須多一層 pproxy 把 SOCKS5 轉成 HTTP,codex 才走得通。這是整套方案必須有兩層的根本原因。

步驟一:SSH SOCKS5 隧道

ssh -i ~/.ssh/id_rsa_gcp -D 1080 -N \
  -o ExitOnForwardFailure=yes \
  -o ServerAliveInterval=30 -o ServerAliveCountMax=3 \
  -o StrictHostKeyChecking=accept-new \
  simon@35.208.247.13

這在 127.0.0.1:1080 開了一個 SOCKS5 出口。

步驟二:pproxy(SOCKS5 轉 HTTP)

pip3 install --user --break-system-packages pproxy
pproxy -l http://127.0.0.1:8080 -r socks5://127.0.0.1:1080

步驟三:systemd 持久化

兩個使用者服務放在 ~/.config/systemd/user/。隧道服務 codex-tunnel.service:

[Unit]
Description=Codex SOCKS5 tunnel to GCP US VM
After=network-online.target
Wants=network-online.target
[Service]
ExecStart=/usr/bin/ssh -i /home/ubuntu-vm/.ssh/id_rsa_gcp -D 1080 -N -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o StrictHostKeyChecking=accept-new simon@35.208.247.13
Restart=always
RestartSec=10
[Install]
WantedBy=default.target

代理服務 codex-http-proxy.service,用 Requires 確保它跟在隧道後面起來:

[Unit]
Description=Codex HTTP proxy (pproxy: SOCKS5 -> HTTP)
After=codex-tunnel.service
Requires=codex-tunnel.service
[Service]
ExecStart=/usr/bin/python3 /home/ubuntu-vm/.local/bin/pproxy -l http://127.0.0.1:8080 -r socks5://127.0.0.1:1080
Restart=always
RestartSec=5
[Install]
WantedBy=default.target
systemctl --user daemon-reload
systemctl --user enable --now codex-tunnel.service codex-http-proxy.service

Restart=always 讓斷線自動重連。前提是 linger 已開:loginctl show-user ubuntu-vm | grep Linger 應為 yes,否則登出後服務會停。

步驟四:codex wrapper

建 ~/.codex-proxy/bin/codex,讓打 codex 就自動走代理,不用每次手動設環境變數:

#!/usr/bin/env bash
export HTTPS_PROXY="${HTTPS_PROXY:-http://127.0.0.1:8080}"
export HTTP_PROXY="${HTTP_PROXY:-http://127.0.0.1:8080}"
export ALL_PROXY="${ALL_PROXY:-http://127.0.0.1:8080}"
export NO_PROXY="localhost,127.0.0.1,192.168.0.0/16,10.0.0.0/8,${NO_PROXY:-}"
exec /home/ubuntu-vm/.npm-global/bin/codex "$@"

再在 ~/.bashrc 末尾把這個目錄排到 PATH 最前面:

export PATH="$HOME/.codex-proxy/bin:$PATH"

步驟五:用 ChatGPT 帳號登入

codex login --device-auth

終端印出 https://auth.openai.com/codex/device 和一次性 code,在瀏覽器登入 ChatGPT 帳號授權即可。用量計入 ChatGPT Plus 訂閱,不另外收費;若改用 API key 登入則按 token 另計費,不要把 key 塞進 ~/.codex/auth.json。

驗證

# 代理鏈可達(應回 401,代表已連上只差憑證)
HTTPS_PROXY=http://127.0.0.1:8080 curl -s -o /dev/null -w '%{http_code}\n' https://api.openai.com/v1/models
# 出口 IP 應為 GCP 美國
HTTPS_PROXY=http://127.0.0.1:8080 curl -s https://api.ipify.org
# 端到端
export PATH="$HOME/.codex-proxy/bin:$PATH"
codex exec --skip-git-repo-check "Reply with exactly: OK"

2026-09-03 實測:401、出口 IP 為 35.208.247.13、codex 成功回覆 OK,新開的 shell 自動指向 wrapper。

Notes

  • Bun 只吃 HTTP 代理是必須多一層 pproxy 的根本原因;日後若 codex 改回 Node runtime 或支援 SOCKS,可簡化成單層。
  • high demand 不等於高負載:先 curl 看真實 HTTP code 再下結論。
  • 若透過 Hermes 的 codex-delegate 委派,wrapper 要等 Hermes 重載 PATH 後才生效。
  • Codex CLI 版本會變動(本次 v0.139.0);升級後行為改變先跑 codex doctor 確認 runtime 是否仍是 Bun。
pixel cat

貓說:先讓系統安靜地跑起來。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *