127.0.0.1 のみ、接続はトークンと secretKey で先に検証し、二本のレーンは地域単位のヘルス一行へ合算する。SSH 逆転送稿と同じ低露出姿勢で、輸送だけ frp に差し替える。
典型境界は三つ:Tailscale MagicDNS、ループバック+SSH、本稿の frp STCP。オーバーレイ禁止の VLAN では visitor が鍵を揃えるまで Mac 上の TCP に届かず、表はループバックのまま。PoP は GeoDNS・SSH マトリクス、縁で TLS を置くなら Cloudflare Tunnel 稿、上流プローブ形は JumpHost+マージ稿。公開 CTA は トップ・料金・ヘルプ・購入——ログイン不要。
軸は三つ。1) 0.0.0.0 のデモ拘束は境界を壊す/STCP は楽経路をループバックに寄せる。2) 秘密は frps の auth.token とプロキシ別 secretKey に集約し暦で回す。3) GW だけ緑・doctor だけ遅い等は同一リージョン一行に潰し、同じ瞬断で二枚ページしない。
| 論点 | 仕組み | 検収シグナル |
|---|---|---|
| GW ポートを公網から隠す | STCP visitor + frps token | ビルダー/visitor 双方で ss -ltn が OpenClaw を 127.0.0.1 のみ表示 |
| TCP が届く前に認証 | frps auth.token + STCP secretKey |
鍵ズレで reject が立ち、OpenClaw 側ログは静か |
| リージョン分離 | PoP ごとに proxy_name(例 openclaw-sin-gw) |
東京 visitor がシン誤接続しても名前不一致で失敗 |
| GW+doctor のヘルス巻き上げ | マージワーカーが地域単位で結合 | インシデント一枚/エンドポイント二枚にしない |
役割・ポート・gateway/doctor の連鎖
frps は信頼できる Linux バスション。bindPort = 7000、auth.method = "token" と長い auth.token。ダッシュボードは任意で 7500 を HTTPS+ベーシックの裏へ。7000/tcp は運用サブネットと各ビルダー出口のみ(公網丸開けは避ける)。各 vpshalo Mac の frpc は外向き 7000 のみで、地域ごとに STCP を二本:openclaw-{region}-gw → 127.0.0.1:18080(gateway)、openclaw-{region}-doctor → 127.0.0.1:18081(doctor)。プロキシごとに secretKey を分ける。
visitor は運用端末かマージワーカー側の frpc。こちらも外向きのみで、着地点は 127.0.0.1(慣例で GW 28080、doctor 28081)。curl http://127.0.0.1:28080/healthz が visitor→frps トークン→STCP 秘密→ビルダーループバック→OpenClaw まで一気に踏む。gateway は推論トラフィック、doctor はキュー深さやモデル版などの JSON。二本を束ね tokenizer 再読込で doctor だけ遅い状態も見える。
最小再現ステップ
在庫タグで {region} を置換(例 sin tyo hkg icn lax)。地域ごとに一度。
- 1 ループバック拘束。
OPENCLAW_HOME=/var/lib/openclaw/{region}(macOS は/usr/local/var等)とし--gateway-bind 127.0.0.1:18080 --doctor-bind 127.0.0.1:18081。localhost のみcurl …/healthzとcurl …/doctor。 - 2 frps。
frps -c frps.tomlで 7000 と token。SG/UFW/nftで 7000 を絞る。 - 3 ビルダー frpc。 STCP 二本、
secretKey別、remotePort無し。systemd/launchd で指数退避付き再起動(フラップで FW を緩めない)。 - 4 visitor。 127.0.0.1:28080/28081、秘密はプロキシと一致。共有前に localhost
curl。 - 5 合算。 小さなワーカーが
28080/healthzと28081/doctorを叩き{region,gw_ms,doctor_ms,status,error_class}を TSDB へ。五分窓で両レーン落ちのみページ、二地域同時劣化だけマルチ扱い。
# frpc.toml — ビルダー側(ループバック上 STCP×2)
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 — visitor 側(両レーン 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 に昇格させない。低露出の本体は「両端ループバック」のまま保つ。ランブックに貼る一行
- 回す秘密は二種: frps の
auth.tokenとプロキシ別secretKey。ssh_configの林より面が小さい。 - スキャンは OpenClaw まで届かない。 不一致は frps の reject に溜まり、OpenClaw の access ログを汚さない。
排障メモ
visitor が繋がらない。 バスション 7000/tcp と許可リストを確認。ログはトークン不一致で auth failed、STCP 秘密不一致で visitor not allowed。変数は一つずつ回す。GW は 200 だが doctor が遅い。 多くはビルダー側スレッド詰まり。OpenClaw を再起動し frp は触らない。遅延だけ高い。 中継が frps 経由になるので PoP をバスション近くへ。SCP/SFTP RTT 表で根拠を付ける。輪番後にズレ。 visitor の旧 secretKey を疑い、プロキシと visitor を同一窓で更新し curl 127.0.0.1:28080/healthz で黙らせてからアラート解除。二本同秒で落ちる。 トンネル劣化。frps 監督と frpc のキープアライブを見る。
bindAddr は版差あり。OpenClaw の --gateway-bind/--doctor-bind もタグで確認。本稿は意図説明であり SLA ではない。SSH/Tailscale 稿と補完関係。
手順をスクリプト化すれば境界は意図的に退屈になる。各地ループバック、認証付き STCP、公網リスナ無し、暦駆動の秘密更新、地域一枚の合算アラート。実測した PoP に リモート Mac を揃え、registry ミラーと visitor を同じ地理に寄せる。