127.0.0.1;连接路径上先做 frps auth.token 再做 STCP secretKey,再把两条健康通道合并成单条区域告警。这与 SSH 反向隧道姊妹篇同属「低暴露」编排,只是传输换成 frp。
常见周界三条路:Tailscale MagicDNS 覆盖网、loopback + SSH -R,以及本文的 frp STCP。STCP 不要求跳板开 GatewayPorts:未匹配密钥前,扫描流量进不了 Mac;访客与构建机两侧都钉在回环。PoP 与 SSH 基线见 《全球入口决策矩阵》;边缘公共 TLS 见 《Cloudflare Tunnel》篇;粘性入口与上游探针形态对齐 《JumpHost 与合并探针》。公开 CTA(免登录):首页、套餐价格、帮助中心、购买页。
设计动机可压成三句:1) 把「顺手绑 0.0.0.0」从默认路径里拿掉,让易用路径等于 loopback。2) 用一份 frps auth.token 加每条 STCP 独立 secretKey,轮换面远小于散落各机的长配置。3) 网关 200 而 doctor 卡死时,合并探针让值班看到「JP 红」而不是同一次抖动两条工单。
| 关切 | 机制 | 验收信号 |
|---|---|---|
| 公网不可直达网关端口 | STCP visitor + frps 令牌 | 构建机与访客机 ss -ltn 仅见 OpenClaw 在 127.0.0.1 |
| TCP 进 OpenClaw 前须鉴权 | auth.token + STCP secretKey |
密钥漂移时拒绝计数上升,OpenClaw 访问日志不被噪声刷爆 |
| 按区域隔离命名 | 每 PoP 独立 proxy_name(如 openclaw-sin-gw) |
东京访客误配新加坡名会直接失败,不会串区 |
| gateway + doctor 健康汇总 | 合并 worker 按区 join 两路 | 同一区域事故一条告警,而非每端点一条 |
frp 角色、端口与 gateway / doctor 串联
frps(服务端)跑在你信任的 Linux 跳板上:bindPort = 7000,auth.method = "token" 配长随机 auth.token;可选仪表盘 7500,务必 HTTPS + 独立口令。防火墙将 7000/tcp 收口到运维网段与各 vpshalo 构建机出口 IP,尽量避免对公网全开。frpc(构建机侧)在每台区域 Mac 上仅出站连跳板 7000,注册两条 STCP:openclaw-{region}-gw → 127.0.0.1:18080(gateway),openclaw-{region}-doctor → 127.0.0.1:18081(doctor 健康 JSON),各带独立 secretKey。
frpc visitor(访客侧)跑在运维机或合并探针 worker,同样只出站;本地只绑 127.0.0.1,约定 28080 对网关、28081 对 doctor。一次 curl http://127.0.0.1:28080/healthz 即走完整链路:visitor → frps 令牌 → STCP 密钥 → 远端 loopback → OpenClaw。Gateway 服务推理流量;doctor 暴露队列、模型版本、GPU/Metal 等更「深」的状态——两路串联才能在「HTTP 仍 200 但 tokenizer 卡死」时仍看见异常。
最小可复现步骤(每区重复)
将 {region} 换成库存标签(如 sin、tyo、hkg、icn、lax)。
- 步骤 1 — 钉死 loopback:每区独立
OPENCLAW_HOME,启动参数含--gateway-bind 127.0.0.1:18080 --doctor-bind 127.0.0.1:18081(具体 flag 以你锁定的 OpenClaw 版本为准)。仅在 Mac 本机执行curl …/healthz与curl …/doctor验证。 - 步骤 2 — 起 frps:
frps -c frps.toml,确认7000与令牌;安全组 / UFW /nft与构建机出口白名单一致。 - 步骤 3 — 构建机 frpc:两条
type = "stcp",无remotePort(STCP 设计上不开放公网端口)。用 systemd 或 launchd 拉起并加重启退避,避免一抖就放宽防火墙。 - 步骤 4 — 访客 frpc:两条 visitor,
bindAddr = 127.0.0.1,secretKey与构建机侧逐字一致;先本机curl再放开团队访问。 - 步骤 5 — 合并探针:小 worker 顺序请求
127.0.0.1:28080/healthz与127.0.0.1:28081/doctor,写入{region, gw_ms, doctor_ms, status};同一五分钟桶内双通道均失败再告警,两区同时劣化再升为多区域事件。
# frpc.toml — 构建机:两条 STCP 指向本机 loopback
serverAddr = "bastion-sin.vpshalo.example"
serverPort = 7000
auth.method = "token"
auth.token = "<long-random-frps-token>"
[[proxies]]
name = "openclaw-sin-gw"
type = "stcp"
secretKey = "<sk-sin-gw>"
localIP = "127.0.0.1"
localPort = 18080
[[proxies]]
name = "openclaw-sin-doctor"
type = "stcp"
secretKey = "<sk-sin-doctor>"
localIP = "127.0.0.1"
localPort = 18081
# frpc.toml — 访客:两路仅绑 127.0.0.1
[[visitors]]
name = "v-openclaw-sin-gw"
type = "stcp"
serverName = "openclaw-sin-gw"
secretKey = "<sk-sin-gw>"
bindAddr = "127.0.0.1"
bindPort = 28080
[[visitors]]
name = "v-openclaw-sin-doctor"
type = "stcp"
serverName = "openclaw-sin-doctor"
secretKey = "<sk-sin-doctor>"
bindAddr = "127.0.0.1"
bindPort = 28081
0.0.0.0。低暴露模式的底线是:回环始终是回环。排障速查
访客连不上:先 ping 流程:访客源 IP 能否打 7000/tcp 到跳板;frps 日志里 auth failed 多为令牌不一致,visitor not allowed 多为 secretKey 不匹配——一次只改一个变量。网关 200 但 doctor 卡住:多为构建机侧 worker/模型线程问题,doctor 正是在报这类「深」故障;优先重启 OpenClaw 子进程而非动 frp。能通但延迟高:STCP 可能经 frps 中继,把构建机放在离跳板更近的 vpshalo PoP,选型参考 《SCP/SFTP RTT 矩阵》。轮换后仍拒连:访客侧仍用旧 secretKey;维护窗内同步改 proxy 与 visitor,再用 curl 127.0.0.1:28080/healthz 静音前自检。两路同一秒同时挂:更像隧道或 frps 进程问题,查 frpc 保活与 frps 监管;暴力扫描通常只抬升 frps 拒绝计数,不会污染 OpenClaw 日志——这也是 STCP 相对「公网直开端口」的优势之一。
auth.method、STCP 与 visitor 的 bindAddr 写法。OpenClaw 的 --gateway-bind / --doctor-bind 亦因版本而异,本文描述的是意图与编排形状,不构成厂商 SLA。本模式与上文内链中的 SSH、Tailscale、Tunnel 方案互补而非互斥。
把上述步骤脚本化后,周界会「故意变得无聊」:每区 loopback、经认证的 frp STCP、无公网监听、按日历轮换密钥、每区一条合并告警而非探针噪声。按你实测过的 PoP 开通 远程 Mac 构建机,使镜像仓库、frp 与 visitor 同区搬迁,低暴露与低 RTT 才能同时成立。