---
read_when:
    - ID 認識プロキシの背後で OpenClaw を実行する
    - OpenClaw の前段に OAuth 付きの Pomerium、Caddy、または nginx を設定する
    - リバースプロキシ構成での WebSocket 1008 unauthorized エラーの修正
    - HSTS やその他の HTTP 強化ヘッダーをどこで設定するかを決める
sidebarTitle: Trusted proxy auth
summary: Gateway 認証を信頼済みリバースプロキシ（Pomerium、Caddy、nginx + OAuth）に委譲する
title: 信頼済みプロキシ認証
x-i18n:
    generated_at: "2026-06-27T11:39:44Z"
    model: gpt-5.5
    postprocess_version: locale-links-v1
    provider: openai
    source_hash: 498a8aca666f88201302af3895b11ba43ab9c0b1bff00a262145fc9e21e80fa7
    source_path: gateway/trusted-proxy-auth.md
    workflow: 16
---

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

## 使用する場合

次の場合は `trusted-proxy` 認証モードを使用します。

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

## 使用しない場合

- プロキシがユーザーを認証しない場合（単なる TLS ターミネーターやロードバランサー）。
- プロキシを迂回して Gateway に到達できる経路がある場合（ファイアウォールの穴、内部ネットワークアクセス）。
- プロキシが転送ヘッダーを正しく削除または上書きしているか不明な場合。
- 個人の単一ユーザーアクセスだけが必要な場合（より簡単な設定として Tailscale Serve + ループバックを検討してください）。

## 仕組み

<Steps>
  <Step title="Proxy authenticates the user">
    リバースプロキシがユーザーを認証します（OAuth、OIDC、SAML など）。
  </Step>
  <Step title="Proxy adds an identity header">
    プロキシは、認証済みユーザー ID を含むヘッダーを追加します（例: `x-forwarded-user: nick@example.com`）。
  </Step>
  <Step title="Gateway verifies trusted source">
    OpenClaw は、リクエストが **信頼済みプロキシ IP**（`gateway.trustedProxies` で設定）から来たことを確認します。
  </Step>
  <Step title="Gateway extracts identity">
    OpenClaw は、設定されたヘッダーからユーザー ID を抽出します。
  </Step>
  <Step title="Authorize">
    すべての確認に成功すると、リクエストは認可されます。
  </Step>
</Steps>

## Control UI のペアリング動作

`gateway.auth.mode = "trusted-proxy"` が有効で、リクエストが trusted-proxy チェックに合格した場合、Control UI WebSocket セッションはデバイスペアリング ID なしで接続できます。

スコープへの影響:

- デバイスなしの Control UI WebSocket セッションは接続できますが、デフォルトではオペレータースコープを受け取りません。OpenClaw は要求されたスコープリストを `[]` にクリアするため、承認済みのペアリング済みデバイスやトークンに紐づいていないセッションが権限を自己宣言することはできません。
- WebSocket 接続に成功した後にメソッドが `missing scope` で失敗する場合は、ブラウザーがデバイス ID を生成してペアリングを完了できるように HTTPS を使用してください。[Control UI の安全でない HTTP](/ja-JP/web/control-ui#insecure-http) を参照してください。
- 緊急時のみ: `gateway.controlUi.dangerouslyDisableDeviceAuth=true` は、デバイス ID がなくても要求されたスコープを保持します。これは深刻なセキュリティ低下です。速やかに元に戻してください。[Control UI の安全でない HTTP](/ja-JP/web/control-ui#insecure-http) を参照してください。

リバースプロキシによるスコープ制限:

- プロキシが Control UI WebSocket アップグレードリクエストで `x-openclaw-scopes` を送信する場合、OpenClaw はセッションスコープを、要求されたスコープと宣言されたスコープの共通部分に制限します。このヘッダーはスコープを付与しません。セッションが保持できる範囲を狭めるだけです。

影響:

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

カスタム WebSocket クライアントは Control UI セッションではありません。`gateway.controlUi.dangerouslyDisableDeviceAuth` は、任意の `client.mode: "backend"` や CLI 形式のクライアントにスコープを付与しません。カスタム自動化では、デバイス ID/ペアリング、予約済みの直接ローカル `client.id: "gateway-client"` バックエンドヘルパーパス、または HTTP リクエスト/レスポンスのサーフェスがより適している場合は [admin HTTP RPC Plugin](/ja-JP/plugins/admin-http-rpc) を使用してください。

## 設定

```json5
{
  gateway: {
    // Trusted-proxy auth expects requests from a non-loopback trusted proxy source by default
    bind: "lan",

    // 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"],

        // Optional: allow a same-host loopback proxy after explicit opt-in
        allowLoopback: false,
      },
    },
  },
}
```

<Warning>
**重要なランタイムルール**

- Trusted-proxy 認証は、デフォルトでループバック送信元のリクエスト（`127.0.0.1`、`::1`、ループバック CIDR）を拒否します。
- 同一ホストのループバックリバースプロキシは、`gateway.auth.trustedProxy.allowLoopback = true` を明示的に設定し、ループバックアドレスを `gateway.trustedProxies` に含めない限り、trusted-proxy 認証を満たしません。
- `allowLoopback` は、Gateway ホスト上のローカルプロセスをリバースプロキシと同程度に信頼します。Gateway が直接リモートアクセスから引き続きファイアウォールで保護され、ローカルプロキシがクライアント提供の ID ヘッダーを削除または上書きする場合にのみ有効化してください。
- リバースプロキシを経由しない内部 Gateway クライアントは、trusted-proxy ID ヘッダーではなく、`gateway.auth.password` / `OPENCLAW_GATEWAY_PASSWORD` を使用する必要があります。
- 非ループバックの Control UI デプロイでは、引き続き明示的な `gateway.controlUi.allowedOrigins` が必要です。
- **転送ヘッダーの証拠は、ローカル直接フォールバックにおいてループバックのローカル性を上書きします。** リクエストがループバックに到着しても、`Forwarded`、任意の `X-Forwarded-*`、または `X-Real-IP` ヘッダーの証拠を持つ場合、その証拠により、ローカル直接パスワードフォールバックとデバイス ID ゲートは不適格になります。`allowLoopback: true` の場合、trusted-proxy 認証は引き続き同一ホストプロキシリクエストとしてリクエストを受け入れられ、`requiredHeaders` と `allowUsers` は引き続き適用されます。

</Warning>

### 設定リファレンス

<ParamField path="gateway.trustedProxies" type="string[]" required>
  信頼するプロキシ IP アドレスの配列。他の IP からのリクエストは拒否されます。
</ParamField>
<ParamField path="gateway.auth.mode" type="string" required>
  `"trusted-proxy"` である必要があります。
</ParamField>
<ParamField path="gateway.auth.trustedProxy.userHeader" type="string" required>
  認証済みユーザー ID を含むヘッダー名。
</ParamField>
<ParamField path="gateway.auth.trustedProxy.requiredHeaders" type="string[]">
  リクエストを信頼するために存在している必要がある追加ヘッダー。
</ParamField>
<ParamField path="gateway.auth.trustedProxy.allowUsers" type="string[]">
  ユーザー ID の許可リスト。空の場合はすべての認証済みユーザーを許可します。
</ParamField>
<ParamField path="gateway.auth.trustedProxy.allowLoopback" type="boolean">
  同一ホストのループバックリバースプロキシに対するオプトインサポート。デフォルトは `false` です。
</ParamField>

<Warning>
ローカルリバースプロキシが意図した信頼境界である場合にのみ、`allowLoopback` を有効化してください。Gateway に接続できる任意のローカルプロセスは、プロキシ ID ヘッダーの送信を試みることができます。そのため、Gateway への直接アクセスはホスト内で非公開に保ち、`x-forwarded-proto` や、プロキシがサポートしている場合は署名付きアサーションヘッダーなど、プロキシ所有のヘッダーを要求してください。
</Warning>

## TLS 終端と HSTS

TLS 終端点は 1 つにし、そこで HSTS を適用してください。

<Tabs>
  <Tab title="Proxy TLS termination (recommended)">
    リバースプロキシが `https://control.example.com` の HTTPS を処理する場合、そのドメインに対してプロキシで `Strict-Transport-Security` を設定します。

    - インターネットに面したデプロイに適しています。
    - 証明書と HTTP 強化ポリシーを 1 か所に保てます。
    - OpenClaw はプロキシ背後のループバック HTTP のままにできます。

    ヘッダー値の例:

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

  </Tab>
  <Tab title="Gateway TLS termination">
    OpenClaw 自体が HTTPS を直接提供する場合（TLS 終端プロキシなし）、次を設定します。

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

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

  </Tab>
</Tabs>

### ロールアウトのガイダンス

- トラフィックを検証している間は、まず短い最大期間（例: `max-age=300`）から開始します。
- 十分な確信が得られた後にのみ、長期間の値（例: `max-age=31536000`）へ増やします。
- すべてのサブドメインが HTTPS 対応済みの場合にのみ、`includeSubDomains` を追加します。
- ドメインセット全体について preload 要件を意図的に満たしている場合にのみ、preload を使用します。
- ループバックのみのローカル開発では、HSTS の利点はありません。

## プロキシ設定例

<AccordionGroup>
  <Accordion title="Pomerium">
    Pomerium は `x-pomerium-claim-email`（または他のクレームヘッダー）で ID を渡し、`x-pomerium-jwt-assertion` で JWT を渡します。

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

    Pomerium 設定スニペット:

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

  </Accordion>
  <Accordion title="Caddy with OAuth">
    `caddy-security` Plugin を備えた Caddy は、ユーザーを認証して ID ヘッダーを渡すことができます。

    ```json5
    {
      gateway: {
        bind: "lan",
        trustedProxies: ["10.0.0.1"], // Caddy/sidecar proxy 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}
        }
    }
    ```

  </Accordion>
  <Accordion title="nginx + oauth2-proxy">
    oauth2-proxy はユーザーを認証し、`x-auth-request-email` で ID を渡します。

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

    nginx 設定スニペット:

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

  </Accordion>
  <Accordion title="Traefik with forward auth">
    ```json5
    {
      gateway: {
        bind: "lan",
        trustedProxies: ["172.17.0.1"], // Traefik container IP
        auth: {
          mode: "trusted-proxy",
          trustedProxy: {
            userHeader: "x-forwarded-user",
          },
        },
      },
    }
    ```
  </Accordion>
</AccordionGroup>

## 混在トークン設定

OpenClaw は、`gateway.auth.token`（または `OPENCLAW_GATEWAY_TOKEN`）と `trusted-proxy` モードの両方が同時に有効な曖昧な設定を拒否します。混在トークン設定では、ループバックリクエストが誤った認証パスで暗黙的に認証される可能性があります。

起動時に `mixed_trusted_proxy_token` エラーが表示された場合:

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

Loopback の信頼済みプロキシ identity ヘッダーは引き続き fail closed します。同一ホストの呼び出し元が、プロキシユーザーとして暗黙に認証されることはありません。プロキシをバイパスする内部 OpenClaw 呼び出し元は、代わりに `gateway.auth.password` / `OPENCLAW_GATEWAY_PASSWORD` で認証できます。信頼済みプロキシモードでは、トークンフォールバックは意図的にサポートされていません。

## オペレータースコープヘッダー

信頼済みプロキシ認証は **identity を伴う** HTTP モードのため、呼び出し元は HTTP API リクエストで `x-openclaw-scopes` を使って、オペレータースコープを任意で宣言できます。

注: WebSocket スコープは、Gateway プロトコルのハンドシェイクとデバイス identity バインディングによって決まります。Control UI の WebSocket アップグレードリクエストでは、`x-openclaw-scopes` はネゴシエートされたセッションスコープの上限にすぎず、付与ではありません。信頼済みプロキシでの WebSocket スコープの挙動については、[Control UI ペアリングの挙動](#control-ui-pairing-behavior)を参照してください。

例:

- `x-openclaw-scopes: operator.read`
- `x-openclaw-scopes: operator.read,operator.write`
- `x-openclaw-scopes: operator.admin,operator.write`

挙動:

- ヘッダーが存在する場合、OpenClaw は宣言されたスコープセットを尊重します。
- ヘッダーが存在するが空の場合、リクエストはオペレータースコープが **ない** ことを宣言します。
- ヘッダーがない場合、通常の identity を伴う HTTP API は標準のオペレーター既定スコープセットにフォールバックします。
- Gateway 認証の**プラグイン HTTP ルート**は、既定でより狭くなります。`x-openclaw-scopes` がない場合、それらのランタイムスコープは `operator.write` にフォールバックします。
- ブラウザー由来の HTTP リクエストは、信頼済みプロキシ認証が成功した後でも、`gateway.controlUi.allowedOrigins`（または意図的な Host ヘッダーフォールバックモード）を通過する必要があります。
- Control UI WebSocket セッションでは、アップグレードリクエストに `x-openclaw-scopes` が存在する場合、それはスコープの上限です。空の値はスコープなしになります。

実用上のルール: 信頼済みプロキシリクエストを既定より狭くしたい場合、または Gateway 認証プラグインルートが write スコープより強いものを必要とする場合は、`x-openclaw-scopes` を明示的に送信してください。

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

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

- [ ] **プロキシが唯一の経路**: Gateway ポートは、プロキシ以外のすべてからファイアウォールで遮断されています。
- [ ] **trustedProxies は最小限**: サブネット全体ではなく、実際のプロキシ IP のみです。
- [ ] **Loopback プロキシ送信元が意図的**: 同一ホストプロキシ用に `gateway.auth.trustedProxy.allowLoopback` が明示的に有効化されていない限り、loopback 送信元リクエストに対する信頼済みプロキシ認証は fail closed します。
- [ ] **プロキシがヘッダーを除去する**: プロキシはクライアントからの `x-forwarded-*` ヘッダーを追記ではなく上書きします。
- [ ] **TLS 終端**: プロキシが TLS を処理し、ユーザーは HTTPS 経由で接続します。
- [ ] **allowedOrigins が明示的**: 非 loopback の Control UI は明示的な `gateway.controlUi.allowedOrigins` を使います。
- [ ] **allowUsers が設定されている**（推奨）: 認証された誰でも許可するのではなく、既知のユーザーに制限します。
- [ ] **トークン設定が混在していない**: `gateway.auth.token` と `gateway.auth.mode: "trusted-proxy"` の両方を設定しないでください。
- [ ] **ローカルパスワードフォールバックがプライベート**: 内部の直接呼び出し元向けに `gateway.auth.password` を設定する場合は、プロキシではないリモートクライアントが Gateway ポートへ直接到達できないよう、ファイアウォールで遮断してください。

## セキュリティ監査

`openclaw security audit` は、信頼済みプロキシ認証を **critical** 重大度の検出としてフラグします。これは意図的なもので、セキュリティをプロキシ設定に委任していることを思い出させるためです。

監査では次を確認します。

- 基本の `gateway.trusted_proxy_auth` 警告/critical リマインダー
- `trustedProxies` 設定の欠落
- `userHeader` 設定の欠落
- 空の `allowUsers`（認証済みユーザーなら誰でも許可）
- 同一ホストプロキシ送信元向けに有効化された `allowLoopback`
- 公開された Control UI サーフェスでのワイルドカードまたは欠落したブラウザー origin ポリシー

## トラブルシューティング

<AccordionGroup>
  <Accordion title="trusted_proxy_untrusted_source">
    リクエストは `gateway.trustedProxies` 内の IP から来ていません。確認してください。

    - プロキシ IP は正しいですか？（Docker コンテナー IP は変わることがあります。）
    - プロキシの前段にロードバランサーがありますか？
    - 実際の IP を見つけるには、`docker inspect` または `kubectl get pods -o wide` を使ってください。

  </Accordion>
  <Accordion title="trusted_proxy_loopback_source">
    OpenClaw は loopback 送信元の信頼済みプロキシリクエストを拒否しました。

    確認してください。

    - プロキシは `127.0.0.1` / `::1` から接続していますか？
    - 同一ホストの loopback リバースプロキシで信頼済みプロキシ認証を使おうとしていますか？

    修正:

    - プロキシを通らない内部の同一ホストクライアントには、トークン/パスワード認証を優先する、または
    - 非 loopback の信頼済みプロキシアドレス経由でルーティングし、その IP を `gateway.trustedProxies` に保持する、または
    - 意図的な同一ホストのリバースプロキシでは、`gateway.auth.trustedProxy.allowLoopback = true` を設定し、loopback アドレスを `gateway.trustedProxies` に保持し、プロキシが identity ヘッダーを除去または上書きすることを確認してください。

  </Accordion>
  <Accordion title="trusted_proxy_user_missing">
    ユーザーヘッダーが空か欠落していました。確認してください。

    - プロキシは identity ヘッダーを渡すように設定されていますか？
    - ヘッダー名は正しいですか？（大文字小文字は区別されませんが、スペルは重要です）
    - ユーザーは実際にプロキシで認証されていますか？

  </Accordion>
  <Accordion title="trusted_proxy_missing_header_*">
    必須ヘッダーが存在しませんでした。確認してください。

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

  </Accordion>
  <Accordion title="trusted_proxy_user_not_allowed">
    ユーザーは認証されていますが、`allowUsers` に含まれていません。そのユーザーを追加するか、許可リストを削除してください。
  </Accordion>
  <Accordion title="trusted_proxy_origin_not_allowed">
    信頼済みプロキシ認証は成功しましたが、ブラウザーの `Origin` ヘッダーが Control UI の origin チェックを通過しませんでした。

    確認してください。

    - `gateway.controlUi.allowedOrigins` に正確なブラウザー origin が含まれている。
    - 意図的に全許可の挙動にしたい場合を除き、ワイルドカード origin に依存していない。
    - 意図的に Host ヘッダーフォールバックモードを使う場合、`gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true` が意図的に設定されている。

  </Accordion>
  <Accordion title="Connection succeeds but methods report missing scope">
    WebSocket は接続されますが、`chat.history`、`sessions.list`、または
    `models.list` が `missing scope: operator.read` で失敗します。

    よくある原因:

    - デバイスなしの Control UI セッション: 信頼済みプロキシ認証はデバイス identity なしで WebSocket 接続を許可できますが、OpenClaw は設計上、デバイスなしセッションのスコープをクリアします。
    - カスタムバックエンドクライアント: `gateway.controlUi.dangerouslyDisableDeviceAuth` は Control UI スコープであり、任意のバックエンドまたは CLI 形状の WebSocket クライアントにスコープを付与しません。
    - 過度に狭い `x-openclaw-scopes`: プロキシが Control UI WebSocket アップグレードリクエストにこのヘッダーを注入する場合、セッションスコープはそのセットに制限されます。空のヘッダー値はスコープなしになります。

    修正:

    - Control UI では、ブラウザーがデバイス identity を生成してペアリングを完了できるよう HTTPS を使ってください。
    - カスタム自動化では、デバイス identity/ペアリング、予約済みの直接ローカル `gateway-client` バックエンドヘルパーパス、または [admin HTTP RPC](/ja-JP/plugins/admin-http-rpc) を使ってください。
    - `gateway.controlUi.dangerouslyDisableDeviceAuth: true` は、一時的な Control UI の緊急回避パスとしてのみ使ってください。

  </Accordion>
  <Accordion title="WebSocket still failing">
    プロキシが次を満たしていることを確認してください。

    - WebSocket アップグレードをサポートしている（`Upgrade: websocket`、`Connection: upgrade`）。
    - WebSocket アップグレードリクエストで identity ヘッダーを渡している（HTTP だけではありません）。
    - WebSocket 接続用に別の認証パスを持っていない。

  </Accordion>
</AccordionGroup>

## トークン認証からの移行

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

<Steps>
  <Step title="Configure the proxy">
    ユーザーを認証してヘッダーを渡すようにプロキシを設定します。
  </Step>
  <Step title="Test the proxy independently">
    プロキシ設定を単独でテストします（ヘッダー付き curl）。
  </Step>
  <Step title="Update OpenClaw config">
    信頼済みプロキシ認証で OpenClaw 設定を更新します。
  </Step>
  <Step title="Restart the Gateway">
    Gateway を再起動します。
  </Step>
  <Step title="Test WebSocket">
    Control UI からの WebSocket 接続をテストします。
  </Step>
  <Step title="Audit">
    `openclaw security audit` を実行し、検出結果を確認します。
  </Step>
</Steps>

## 関連

- [設定](/ja-JP/gateway/configuration) — 設定リファレンス
- [リモートアクセス](/ja-JP/gateway/remote) — その他のリモートアクセスパターン
- [セキュリティ](/ja-JP/gateway/security) — 完全なセキュリティガイド
- [Tailscale](/ja-JP/gateway/tailscale) — tailnet 専用アクセス向けのより簡単な代替手段
