コンテンツにスキップ

OpenClawのTrusted Proxy認証設定:リバースプロキシ連携ガイド

認証周りの設定は、開発者にとって常に悩みの種ですよね。特にリバースプロキシをすでに運用している場合、各サービスごとに個別の認証ロジックを組み込むのは非効率ですし、WebSocket でのトークン管理に苦労した経験がある方も多いのではないでしょうか。

そんな時に役立つのが、この trusted-proxy 認証モードです。既存の認証インフラを活かしつつ、Gateway へのアクセスをスマートに管理する方法を解説します。

⚠️ セキュリティに関わる重要な機能です。 このモードは、認証のすべてをリバースプロキシに委ねます。設定を誤ると、Gateway が不正アクセスにさらされる危険があります。有効にする前に、このページを注意深く読んでください。

以下のような場合に trusted-proxy 認証モードを使用してください。

  • Pomerium、Caddy + OAuth、nginx + oauth2-proxy、Traefik + forward auth などの ID 認識プロキシ(identity-aware proxy) の背後で OpenClaw を実行する場合
  • プロキシがすべての認証を処理し、ヘッダーを介してユーザー ID を渡す場合
  • Kubernetes やコンテナ環境で、プロキシが Gateway への唯一の経路である場合
  • ブラウザが WebSocket のペイロードでトークンを渡せないために、WebSocket の 1008 unauthorized エラーが発生している場合
  • プロキシがユーザー認証を行わない場合(単なる TLS 終端やロードバランサーとして機能している場合)
  • ファイアウォールの穴や内部ネットワーク経由など、プロキシをバイパスして Gateway にアクセスできる経路がある場合
  • プロキシが転送されたヘッダーを正しく削除・上書きしているか確信が持てない場合
  • 個人のシングルユーザーアクセスのみが必要な場合(よりシンプルなセットアップとして Tailscale Serve + loopback を検討してください)
  1. リバースプロキシがユーザーを認証します(OAuth, OIDC, SAML など)。
  2. プロキシは、認証されたユーザー ID を含むヘッダーを追加します(例: x-forwarded-user: nick@example.com)。
  3. OpenClaw は、リクエストが 信頼されたプロキシの IP(gateway.trustedProxies で設定)から送信されたものであるかを確認します。
  4. OpenClaw は、設定されたヘッダーからユーザー ID を抽出します。
  5. すべての確認が取れれば、リクエストは承認されます。

gateway.auth.mode = "trusted-proxy" が有効で、リクエストが信頼されたプロキシのチェックを通過した場合、Control UI の WebSocket セッションはデバイスのペアリング ID なしで接続できます。

これには以下の意味があります。

  • このモードでは、ペアリングは Control UI アクセスの主要なゲートではなくなります。
  • リバースプロキシの認証ポリシーと allowUsers が、実質的なアクセス制御となります。
  • Gateway への Ingress は、信頼されたプロキシの IP のみに制限してください(gateway.trustedProxies + ファイアウォール)。
{
gateway: {
// Use loopback for same-host proxy setups; use lan/custom for remote proxy hosts
bind: "loopback",
// CRITICAL: Only add your proxy's IP(s) here
trustedProxies: ["10.0.0.1", "172.17.0.1"],
auth: {
mode: "trusted-proxy",
trustedProxy: {
// Header containing authenticated user identity (required)
userHeader: "x-forwarded-user",
// Optional: headers that MUST be present (proxy verification)
requiredHeaders: ["x-forwarded-proto", "x-forwarded-host"],
// Optional: restrict to specific users (empty = allow all)
allowUsers: ["nick@example.com", "admin@company.org"],
},
},
},
}

gateway.bind が loopback の場合は、gateway.trustedProxies にループバックプロキシアドレス(127.0.0.1、::1、または同等のループバック CIDR)を含めてください。

フィールド必須説明
gateway.trustedProxiesはい信頼するプロキシの IP アドレスの配列。他の IP からのリクエストは拒否されます。
gateway.auth.modeはい"trusted-proxy" である必要があります。
gateway.auth.trustedProxy.userHeaderはい認証されたユーザー ID を含むヘッダー名。
gateway.auth.trustedProxy.requiredHeadersいいえリクエストが信頼されるために存在する必要がある追加のヘッダー。
gateway.auth.trustedProxy.allowUsersいいえユーザー ID の許可リスト。空の場合は、認証されたすべてのユーザーを許可します。

TLS 終端ポイントを 1 つに絞り、そこで HSTS を適用してください。

推奨パターン: プロキシでの TLS 終端

Section titled “推奨パターン: プロキシでの TLS 終端”

リバースプロキシが https://control.example.com の HTTPS を処理する場合、そのドメインに対してプロキシ側で Strict-Transport-Security を設定します。

  • インターネットに公開するデプロイに適しています。
  • 証明書と HTTP のセキュリティ強化ポリシーを 1 か所にまとめられます。
  • OpenClaw はプロキシの背後で loopback の HTTP のまま運用できます。

ヘッダー値の例:

Strict-Transport-Security: max-age=31536000; includeSubDomains

OpenClaw 自体が直接 HTTPS を提供する場合(TLS 終端プロキシがない場合)は、以下のように設定します。

{
gateway: {
tls: { enabled: true },
http: {
securityHeaders: {
strictTransportSecurity: "max-age=31536000; includeSubDomains",
},
},
},
}

strictTransportSecurity は文字列のヘッダー値を受け取るか、明示的に無効にする場合は false を指定します。

  • トラフィックを検証している間は、まず短い有効期限(例: max-age=300)から始めてください。
  • 十分に確信が持てた後にのみ、長期の有効期限(例: max-age=31536000)に変更してください。
  • includeSubDomains は、すべてのサブドメインが HTTPS に対応している場合にのみ追加してください。
  • preload は、ドメインセット全体でプリロードの要件を意図的に満たしている場合にのみ使用してください。
  • loopback のみのローカル開発では HSTS のメリットはありません。

Pomerium は x-pomerium-claim-email(または他のクレームヘッダー)で ID を渡し、x-pomerium-jwt-assertion で JWT を渡します。

{
gateway: {
bind: "lan",
trustedProxies: ["10.0.0.1"], // Pomerium の IP
auth: {
mode: "trusted-proxy",
trustedProxy: {
userHeader: "x-pomerium-claim-email",
requiredHeaders: ["x-pomerium-jwt-assertion"],
},
},
},
}

Pomerium の設定スニペット:

routes:
- from: https://openclaw.example.com
to: http://openclaw-gateway:18789
policy:
- allow:
or:
- email:
is: nick@example.com
pass_identity_headers: true

caddy-security プラグインを使用した Caddy は、ユーザーを認証して ID ヘッダーを渡すことができます。

{
gateway: {
bind: "lan",
trustedProxies: ["127.0.0.1"], // Caddy's IP (if on same host)
auth: {
mode: "trusted-proxy",
trustedProxy: {
userHeader: "x-forwarded-user",
},
},
},
}

Caddyfile のスニペット:

openclaw.example.com {
authenticate with oauth2_provider
authorize with policy1
reverse_proxy openclaw:18789 {
header_up X-Forwarded-User {http.auth.user.email}
}
}

oauth2-proxy はユーザーを認証し、x-auth-request-email で ID を渡します。

{
gateway: {
bind: "lan",
trustedProxies: ["10.0.0.1"], // nginx/oauth2-proxy の IP
auth: {
mode: "trusted-proxy",
trustedProxy: {
userHeader: "x-auth-request-email",
},
},
},
}

nginx の設定スニペット:

location / {
auth_request /oauth2/auth;
auth_request_set $user $upstream_http_x_auth_request_email;
proxy_pass http://openclaw:18789;
proxy_set_header X-Auth-Request-Email $user;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
{
gateway: {
bind: "lan",
trustedProxies: ["172.17.0.1"], // Traefik コンテナの IP
auth: {
mode: "trusted-proxy",
trustedProxy: {
userHeader: "x-forwarded-user",
},
},
},
}

OpenClaw は、gateway.auth.token(または OPENCLAW_GATEWAY_TOKEN)と trusted-proxy モードが同時に有効になっている曖昧な設定を拒否します。トークン設定が混在していると、loopback リクエストが誤った認証パスでサイレントに認証されてしまう可能性があるためです。

起動時に mixed_trusted_proxy_token エラーが表示された場合は、以下のいずれかを行ってください。

  • trusted-proxy モードを使用する場合は、共有トークンを削除する
  • トークンベースの認証を意図している場合は、gateway.auth.mode を "token" に切り替える

また、loopback の trusted-proxy 認証は「失敗時に閉じる(fail closed)」設計になっています。同一ホストからの呼び出し元は、サイレントに認証されるのではなく、信頼されたプロキシを介して設定済みの ID ヘッダーを提供する必要があります。

セキュリティ・チェックリスト

Section titled “セキュリティ・チェックリスト”

trusted-proxy 認証を有効にする前に、以下を確認してください。

  • プロキシが唯一の経路である: Gateway のポートが、プロキシ以外からのアクセスをファイアウォールで遮断している
  • trustedProxies が最小限である: サブネット全体ではなく、実際のプロキシ IP のみを指定している
  • プロキシがヘッダーを削除している: プロキシがクライアントからの x-forwarded-* ヘッダーを(追加ではなく)上書きしている
  • TLS 終端: プロキシが TLS を処理し、ユーザーが HTTPS 経由で接続している
  • allowUsers が設定されている(推奨): 認証された全員を許可するのではなく、既知のユーザーに制限している
  • トークン設定が混在していない: gateway.auth.token と gateway.auth.mode: "trusted-proxy" の両方を設定していない

openclaw security audit を実行すると、trusted-proxy 認証は critical(重大)な深刻度の所見としてフラグが立てられます。これは意図的なものであり、セキュリティをプロキシ設定に委ねていることを再認識するためのリマインダーです。

監査では以下の項目がチェックされます。

  • trustedProxies 設定の欠落
  • userHeader 設定の欠落
  • allowUsers が空(認証されたすべてのユーザーを許可している状態)

リクエストが gateway.trustedProxies に含まれていない IP から送信されました。以下を確認してください。

  • プロキシの IP は正しいですか?(Docker コンテナの IP は変わることがあります)
  • プロキシの前にロードバランサーはありませんか?
  • docker inspect や kubectl get pods -o wide を使用して実際の IP を特定してください。

ユーザーヘッダーが空、または存在しません。以下を確認してください。

  • プロキシが ID ヘッダーを渡すように設定されていますか?
  • ヘッダー名は正しいですか?(大文字小文字は区別されませんが、スペルミスに注意してください)
  • ユーザーは実際にプロキシで認証されていますか?

必須ヘッダーが存在しません。以下を確認してください。

  • それらの特定のヘッダーに関するプロキシ設定
  • チェーンのどこかでヘッダーが削除されていないか

ユーザーは認証されていますが、allowUsers に含まれていません。ユーザーを追加するか、許可リストを削除してください。

プロキシが以下の条件を満たしているか確認してください。

  • WebSocket アップグレード(Upgrade: websocket, Connection: upgrade)をサポートしている
  • HTTP だけでなく、WebSocket アップグレードリクエストでも ID ヘッダーを渡している
  • WebSocket 接続に対して別の認証パスが設定されていない

トークン認証から trusted-proxy に移行する場合は、以下の手順で行ってください。

  1. ユーザーを認証し、ヘッダーを渡すようにプロキシを設定します。
  2. プロキシの設定を単体でテストします(ヘッダーを付けた curl など)。
  3. OpenClaw の設定を trusted-proxy 認証で更新します。
  4. Gateway を再起動します。
  5. Control UI からの WebSocket 接続をテストします。
  6. openclaw security audit を実行し、所見を確認します。
  • Security — セキュリティ完全ガイド
  • Configuration — 設定リファレンス
  • Remote Access — その他のリモートアクセスパターン
  • Tailscale — tailnet 限定アクセスのためのよりシンプルな代替案

設定でお困りですか? AI Setup Assistant がお手伝いします。

次のステップ:

OpenClaw

OpenClaw Expert

まだ解決しませんか?

このページで解決しない場合は、OpenClaw Expertに直接質問してください。