信頼済みプロキシ認証

セキュリティに関わる機能です。 このモードは認証を完全にリバースプロキシに委任します。設定を誤ると Gateway が不正アクセスにさらされる可能性があります。有効化する前にこのページを注意深くお読みください。

使用すべき場合

trusted-proxy 認証モードは以下の場合に使用してください:

  • アイデンティティ認識プロキシ(Pomerium、Caddy + OAuth、nginx + oauth2-proxy、Traefik + forward auth)の背後で OpenClaw を実行している
  • プロキシがすべての認証を処理し、ヘッダー経由でユーザーアイデンティティを渡す
  • Kubernetes やコンテナ環境で、プロキシが Gateway への唯一のパスである
  • ブラウザが WS ペイロードでトークンを渡せないため WebSocket 1008 unauthorized エラーが発生している

使用すべきでない場合

  • プロキシがユーザー認証を行わない場合(単なる TLS ターミネーターやロードバランサー)
  • プロキシをバイパスして Gateway に到達するパスがある場合(ファイアウォールの穴、内部ネットワークアクセス)
  • プロキシが転送ヘッダーを正しく除去/上書きしているか不明な場合
  • パーソナルなシングルユーザーアクセスのみが必要な場合(よりシンプルな構成として Tailscale Serve + ループバックを検討してください)

仕組み

  1. リバースプロキシがユーザーを認証(OAuth、OIDC、SAML など)
  2. プロキシが認証済みユーザーアイデンティティを含むヘッダーを追加(例:x-forwarded-user: [email protected]
  3. OpenClaw がリクエストの送信元が信頼済みプロキシ IPgateway.trustedProxies で設定)であることを確認
  4. OpenClaw が設定されたヘッダーからユーザーアイデンティティを抽出
  5. すべてのチェックに合格するとリクエストが認可

コントロール UI のペアリング動作

gateway.auth.mode = "trusted-proxy" がアクティブで、リクエストが信頼済みプロキシチェックに合格した場合、コントロール UI の WebSocket セッションはデバイスペアリングアイデンティティなしで接続できます。

影響:

  • このモードでは、ペアリングはコントロール UI アクセスの主要なゲートではなくなります。
  • リバースプロキシの認証ポリシーと allowUsers が有効なアクセス制御になります。
  • Gateway のイングレスは信頼済みプロキシ IP のみにロックしてください(gateway.trustedProxies + ファイアウォール)。

設定

{
  gateway: {
    // 同一ホストのプロキシにはループバック、リモートプロキシホストには lan/custom を使用
    bind: "loopback",

    // 重要:ここにはプロキシの IP のみを追加
    trustedProxies: ["10.0.0.1", "172.17.0.1"],

    auth: {
      mode: "trusted-proxy",
      trustedProxy: {
        // 認証済みユーザーアイデンティティを含むヘッダー(必須)
        userHeader: "x-forwarded-user",

        // オプション:存在が必須のヘッダー(プロキシ検証)
        requiredHeaders: ["x-forwarded-proto", "x-forwarded-host"],

        // オプション:特定ユーザーに制限(空 = 全員許可)
        allowUsers: ["[email protected]", "[email protected]"],
      },
    },
  },
}

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

設定リファレンス

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

TLS ターミネーションと HSTS

TLS ターミネーションポイントは1つにして、そこで HSTS を適用してください。

推奨パターン:プロキシでの TLS ターミネーション

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

  • インターネット公開デプロイに適しています。
  • 証明書と HTTP ハードニングポリシーを一箇所に集約。
  • OpenClaw はプロキシの背後でループバック HTTP のまま動作できます。

ヘッダー値の例:

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

Gateway での TLS ターミネーション

OpenClaw 自体が直接 HTTPS を提供する場合(TLS ターミネートプロキシなし):

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

strictTransportSecurity はヘッダー値の文字列、または明示的に無効化する場合は false を受け付けます。

ロールアウトガイダンス

  • トラフィックを検証する間は短い max age から始めてください(例:max-age=300)。
  • 信頼性が確認できたら長期間の値に増やしてください(例:max-age=31536000)。
  • すべてのサブドメインが HTTPS 対応の場合にのみ includeSubDomains を追加。
  • 完全なドメインセットでプリロード要件を意図的に満たす場合にのみ preload を使用。
  • ループバック専用のローカル開発では HSTS は不要です。

プロキシセットアップ例

Pomerium

Pomerium はアイデンティティを x-pomerium-claim-email(またはその他のクレームヘッダー)と 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: [email protected]
    pass_identity_headers: true

Caddy + OAuth

caddy-security プラグインを使った Caddy で、ユーザー認証とアイデンティティヘッダーの受け渡しが可能です。

{
  gateway: {
    bind: "lan",
    trustedProxies: ["127.0.0.1"], // Caddy の IP(同一ホストの場合)
    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}
    }
}

nginx + oauth2-proxy

oauth2-proxy がユーザーを認証し、x-auth-request-email でアイデンティティを渡します。

{
  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";
}

Traefik + Forward Auth

{
  gateway: {
    bind: "lan",
    trustedProxies: ["172.17.0.1"], // Traefik コンテナの IP
    auth: {
      mode: "trusted-proxy",
      trustedProxy: {
        userHeader: "x-forwarded-user",
      },
    },
  },
}

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

信頼済みプロキシ認証を有効化する前に確認してください:

  • プロキシが唯一のパス:Gateway ポートがプロキシ以外からファイアウォールされている
  • trustedProxies が最小限:実際のプロキシ IP のみ、サブネット全体を含めない
  • プロキシがヘッダーを除去:プロキシが x-forwarded-* ヘッダーをクライアントから追記ではなく上書きしている
  • TLS ターミネーション:プロキシが TLS を処理し、ユーザーは HTTPS で接続
  • allowUsers を設定(推奨):認証済みの全員を許可するのではなく、既知のユーザーに制限

セキュリティ監査

openclaw security audit は信頼済みプロキシ認証を critical 重大度の検出として報告します。これは意図的なもので、セキュリティをプロキシのセットアップに委任していることの注意喚起です。

監査がチェックする項目:

  • trustedProxies 設定の欠落
  • userHeader 設定の欠落
  • 空の allowUsers(認証済みの全ユーザーを許可)

トラブルシューティング

”trusted_proxy_untrusted_source”

リクエストの送信元が gateway.trustedProxies に含まれる IP ではありません。確認事項:

  • プロキシ IP は正しいですか?(Docker コンテナの IP は変わることがあります)
  • プロキシの前にロードバランサーがありますか?
  • docker inspectkubectl get pods -o wide で実際の IP を確認してください

”trusted_proxy_user_missing”

ユーザーヘッダーが空または欠落しています。確認事項:

  • プロキシがアイデンティティヘッダーを渡す設定になっていますか?
  • ヘッダー名は正しいですか?(大文字小文字は区別されませんが、綴りは重要です)
  • ユーザーはプロキシで実際に認証されていますか?

“trustedproxy_missing_header*”

必要なヘッダーが存在しません。確認事項:

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

”trusted_proxy_user_not_allowed”

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

WebSocket がまだ失敗する場合

プロキシが以下を確認してください:

  • WebSocket アップグレードをサポートしている(Upgrade: websocketConnection: upgrade
  • WebSocket アップグレードリクエストでもアイデンティティヘッダーを渡している(HTTP だけでなく)
  • WebSocket 接続用に別の認証パスを持っていない

トークン認証からの移行

トークン認証から信頼済みプロキシに移行する場合:

  1. プロキシがユーザーを認証してヘッダーを渡す設定にする
  2. プロキシのセットアップを独立してテスト(ヘッダー付き curl)
  3. OpenClaw の設定を信頼済みプロキシ認証に更新
  4. Gateway を再起動
  5. コントロール UI からの WebSocket 接続をテスト
  6. openclaw security audit を実行して検出項目を確認

関連