Gateway

Аутентификация через доверенный прокси

Когда использовать

  • Вы запускаете OpenClaw за прокси с поддержкой идентификации (Pomerium, Caddy + OAuth, nginx + oauth2-proxy, Traefik + forward auth).
  • Ваш прокси выполняет всю аутентификацию и передаёт идентификатор пользователя через заголовки.
  • Вы работаете в Kubernetes или контейнерной среде, где прокси — единственный путь к Gateway.
  • Вы сталкиваетесь с ошибками WebSocket 1008 unauthorized, поскольку браузеры не могут передавать токены в полезной нагрузке WS.

Когда НЕ следует использовать

  • Ваш прокси не аутентифицирует пользователей, а лишь завершает TLS или выполняет балансировку нагрузки.
  • Существует какой-либо путь к Gateway в обход прокси (бреши в межсетевом экране, доступ из внутренней сети).
  • Вы не уверены, что прокси правильно удаляет или перезаписывает перенаправленные заголовки.
  • Вам нужен только персональный однопользовательский доступ (вместо этого рассмотрите Tailscale Serve + loopback).

Как это работает

  • Прокси аутентифицирует пользователя

    Ваш обратный прокси аутентифицирует пользователей (OAuth, OIDC, SAML и т. д.).

  • Прокси добавляет заголовок идентификации

    Прокси добавляет заголовок с идентификатором аутентифицированного пользователя (например, x-forwarded-user: nick@example.com).

  • Gateway проверяет доверенный источник

    OpenClaw проверяет, что запрос поступил с IP-адреса доверенного прокси (gateway.trustedProxies) и это не собственный loopback-адрес или адрес локального интерфейса Gateway.

  • Gateway извлекает идентификатор

    OpenClaw считывает обязательные заголовки, а затем идентификатор пользователя из настроенного заголовка.

  • Авторизация

    Если все проверки пройдены и пользователь соответствует allowUsers (если задано), запрос авторизуется.

  • Конфигурация

    json5
    {  gateway: {    // По умолчанию аутентификация доверенного прокси требует, чтобы IP-адрес источника прокси не был loopback-адресом    bind: "lan",     // КРИТИЧЕСКИ ВАЖНО: добавляйте сюда только 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: ["nick@example.com", "admin@company.org"],         // Необязательно: разрешить loopback-прокси на том же хосте после явного включения        allowLoopback: false,      },    },  },}

    Справочник по конфигурации

    gateway.trustedProxiesstring[]required

    Массив доверенных IP-адресов прокси (или CIDR). Запросы с других IP-адресов отклоняются.

    gateway.auth.modestringrequired

    Должно иметь значение "trusted-proxy".

    gateway.auth.trustedProxy.userHeaderstringrequired

    Имя заголовка с идентификатором аутентифицированного пользователя.

    gateway.auth.trustedProxy.requiredHeadersstring[]

    Дополнительные заголовки, которые должны присутствовать, чтобы запрос считался доверенным.

    gateway.auth.trustedProxy.allowUsersstring[]

    Список разрешённых идентификаторов пользователей. Пустой список разрешает доступ всем аутентифицированным пользователям.

    gateway.auth.trustedProxy.allowLoopbackbooleandefault: false

    Явное включение поддержки loopback-прокси на том же хосте.

    Поведение сопряжения Control UI

    Когда параметр gateway.auth.mode = "trusted-proxy" активен и запрос проходит проверки доверенного прокси, сеансы WebSocket Control UI могут подключаться без идентификатора сопряжённого устройства.

    Особенности областей доступа:

    • Сеансы WebSocket Control UI без устройства подключаются, но по умолчанию не получают областей доступа оператора. OpenClaw очищает список запрошенных областей доступа до [], чтобы сеанс, не привязанный к одобренному сопряжённому устройству или токену, не мог самостоятельно назначить себе разрешения.
    • Если после успешного подключения WebSocket методы завершаются ошибкой missing scope, используйте HTTPS, чтобы браузер мог создать идентификатор устройства и завершить сопряжение. См. Небезопасный HTTP для Control UI.
    • Только для аварийного доступа: gateway.controlUi.dangerouslyDisableDeviceAuth=true сохраняет запрошенные области доступа даже без идентификатора устройства. Это серьёзно снижает безопасность; как можно скорее отмените это изменение. См. Небезопасный HTTP для Control UI.

    Ограничение областей доступа обратным прокси: если при запросе обновления соединения WebSocket Control UI ваш прокси отправляет x-openclaw-scopes, OpenClaw ограничивает области доступа сеанса пересечением запрошенных и объявленных областей. Этот заголовок не предоставляет области доступа, а лишь ограничивает доступный сеансу набор.

    Следствия:

    • В этом режиме сопряжение больше не является основным механизмом ограничения доступа к Control UI.
    • Фактическим механизмом контроля доступа становятся политика аутентификации вашего обратного прокси и allowUsers.
    • Разрешайте входящий трафик Gateway только с IP-адресов доверенных прокси (gateway.trustedProxies + межсетевой экран).

    Пользовательские клиенты WebSocket не являются сеансами Control UI. gateway.controlUi.dangerouslyDisableDeviceAuth не предоставляет области доступа произвольным клиентам client.mode: "backend" или клиентам в формате CLI. Пользовательская автоматизация должна использовать идентификатор устройства и сопряжение, зарезервированный для прямого локального доступа вспомогательный серверный путь client.id: "gateway-client" или плагин admin HTTP RPC, если интерфейс HTTP-запросов и ответов подходит лучше.

    Заголовок областей доступа оператора

    Аутентификация через доверенный прокси — это режим HTTP с передачей идентификатора, поэтому вызывающие стороны могут при необходимости объявлять области доступа оператора с помощью x-openclaw-scopes в запросах к HTTP API.

    Примечание: области доступа WebSocket определяются рукопожатием протокола Gateway и привязкой идентификатора устройства. В запросах обновления соединения WebSocket Control UI заголовок x-openclaw-scopes только ограничивает согласованные области доступа сеанса, но не предоставляет их. См. Поведение сопряжения Control UI.

    Примеры:

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

    Поведение:

    • Если заголовок присутствует, OpenClaw учитывает объявленный набор областей доступа.
    • Если заголовок присутствует, но пуст, запрос объявляет отсутствие областей доступа оператора.
    • Если заголовок отсутствует, обычные HTTP API с передачей идентификатора используют стандартный набор областей доступа оператора по умолчанию (operator.admin, operator.read, operator.write, operator.approvals, operator.pairing, operator.talk.secrets).
    • HTTP-маршруты плагинов с аутентификацией Gateway по умолчанию имеют более узкие права: при отсутствии x-openclaw-scopes их область доступа среды выполнения ограничивается только operator.write.
    • HTTP-запросы из браузера должны проходить проверку gateway.controlUi.allowedOrigins (или намеренно включённый резервный режим заголовка Host) даже после успешной аутентификации через доверенный прокси.

    Практическое правило: явно отправляйте x-openclaw-scopes, если запрос доверенного прокси должен иметь более узкие права, чем предоставляются по умолчанию, или если маршруту плагина с аутентификацией Gateway требуется область доступа шире, чем запись.

    Завершение TLS и HSTS

    Используйте одну точку завершения TLS и применяйте HSTS в ней.

    Завершение TLS на прокси (рекомендуется)

    Когда ваш обратный прокси обслуживает HTTPS для https://control.example.com, настройте Strict-Transport-Security на прокси для этого домена.

    • Хорошо подходит для развёртываний с доступом из интернета.
    • Позволяет хранить сертификат и политику усиления безопасности HTTP в одном месте.
    • OpenClaw может продолжать использовать loopback HTTP за прокси.

    Пример значения заголовка:

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

    Завершение TLS на Gateway

    Если OpenClaw самостоятельно обслуживает HTTPS напрямую (без прокси, завершающего TLS), задайте:

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

    strictTransportSecurity принимает строковое значение заголовка или false для явного отключения.

    Рекомендации по внедрению

    • Сначала используйте короткий срок действия (например, max-age=300), пока проверяете трафик.
    • Переходите к длительным значениям (например, max-age=31536000) только после полной проверки.
    • Добавляйте includeSubDomains, только если каждый поддомен готов к работе через HTTPS.
    • Используйте предварительную загрузку, только если вы намеренно выполняете её требования для всего набора доменов.
    • Локальная разработка исключительно через loopback не получает преимуществ от HSTS.

    Примеры настройки прокси

    Pomerium

    Pomerium передаёт идентификатор в x-pomerium-claim-email (или других заголовках утверждений), а JWT — в x-pomerium-jwt-assertion.

    json5
    {  gateway: {    bind: "lan",    trustedProxies: ["10.0.0.1"], // IP-адрес Pomerium    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
    Caddy с OAuth

    Caddy с плагином caddy-security может аутентифицировать пользователей и передавать заголовки идентификации.

    json5
    {  gateway: {    bind: "lan",    trustedProxies: ["10.0.0.1"], // IP-адрес прокси Caddy/sidecar    auth: {      mode: "trusted-proxy",      trustedProxy: {        userHeader: "x-forwarded-user",      },    },  },}

    Фрагмент Caddyfile:

    caddy
    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.

    json5
    {  gateway: {    bind: "lan",    trustedProxies: ["10.0.0.1"], // IP-адрес nginx/oauth2-proxy    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";}
    Traefik с переадресованной аутентификацией
    json5
    {  gateway: {    bind: "lan",    trustedProxies: ["172.17.0.1"], // IP-адрес контейнера Traefik    auth: {      mode: "trusted-proxy",      trustedProxy: {        userHeader: "x-forwarded-user",      },    },  },}

    Смешанная конфигурация токенов

    Gateway отклоняет запуск с аутентификацией через доверенный прокси, если также настроен общий токен (gateway.auth.token или OPENCLAW_GATEWAY_TOKEN). Эти варианты взаимоисключающие, поскольку общий токен позволил бы вызывающим сторонам на том же хосте аутентифицироваться совершенно иным способом, нежели через подтверждённый прокси идентификатор, применение которого должен обеспечивать этот режим.

    Если запуск завершается ошибкой наподобие gateway auth mode is trusted-proxy, but a shared token is also configured:

    • Удалите общий токен при использовании режима доверенного прокси или
    • Переключите gateway.auth.mode на "token", если планируете использовать аутентификацию по токену.

    Заголовки идентификации доверенного прокси из loopback-интерфейса по-прежнему отклоняются: вызывающие стороны на том же хосте не проходят неявную аутентификацию как пользователи прокси. Внутренние вызывающие стороны OpenClaw, обходящие прокси, могут вместо этого аутентифицироваться с помощью gateway.auth.password / OPENCLAW_GATEWAY_PASSWORD. Резервная аутентификация по токену намеренно не поддерживается в режиме доверенного прокси.

    Контрольный список безопасности

    Перед включением аутентификации через доверенный прокси убедитесь в следующем:

    • [ ] Прокси — единственный путь: порт Gateway защищён межсетевым экраном от всего, кроме вашего прокси.
    • [ ] trustedProxies минимален: указаны только фактические IP-адреса вашего прокси, а не целые подсети.
    • [ ] Источник прокси из loopback-интерфейса выбран намеренно: аутентификация через доверенный прокси отклоняет запросы из loopback-интерфейса, если gateway.auth.trustedProxy.allowLoopback явно не включён для прокси на том же хосте.
    • [ ] Прокси удаляет заголовки: ваш прокси перезаписывает (а не дополняет) заголовки x-forwarded-*, полученные от клиентов.
    • [ ] Завершение TLS: ваш прокси обрабатывает TLS; пользователи подключаются по HTTPS.
    • [ ] allowedOrigins задан явно: Control UI вне loopback-интерфейса использует явно заданный gateway.controlUi.allowedOrigins.
    • [ ] allowUsers задан (рекомендуется): доступ ограничен известными пользователями, а не предоставляется всем прошедшим аутентификацию.
    • [ ] Нет смешанной конфигурации токенов: не задавайте одновременно gateway.auth.token и gateway.auth.mode: "trusted-proxy".
    • [ ] Локальная резервная аутентификация по паролю закрыта от внешнего доступа: если вы настраиваете gateway.auth.password для внутренних прямых вызывающих сторон, защитите порт Gateway межсетевым экраном, чтобы удалённые клиенты вне прокси не могли подключаться к нему напрямую.

    Аудит безопасности

    openclaw security audit помечает аутентификацию через доверенный прокси как проблему критического уровня серьёзности. Это сделано намеренно: предупреждение напоминает, что безопасность делегируется конфигурации вашего прокси.

    Аудит проверяет следующее:

    • Базовое предупреждение или критическое напоминание для gateway.trusted_proxy_auth.
    • Отсутствует конфигурация trustedProxies.
    • Отсутствует конфигурация userHeader.
    • Пустой allowUsers (разрешает доступ любому аутентифицированному пользователю).
    • Включён allowLoopback для источников прокси на том же хосте.

    Когда Control UI открыт для внешнего доступа, также применяются отдельные проверки, не относящиеся непосредственно к доверенному прокси: gateway.controlUi.allowedOrigins с подстановочным знаком или отсутствующим значением, а также резервное определение источника по заголовку Host.

    Устранение неполадок

    trusted_proxy_untrusted_source

    Запрос поступил не с IP-адреса из gateway.trustedProxies. Проверьте:

    • Правильно ли указан IP-адрес прокси? (IP-адреса контейнеров Docker могут изменяться.)
    • Есть ли перед вашим прокси балансировщик нагрузки?
    • Используйте docker inspect или kubectl get pods -o wide, чтобы определить фактические IP-адреса.
    trusted_proxy_loopback_source

    OpenClaw отклонил запрос доверенного прокси из loopback-интерфейса.

    Проверьте:

    • Подключается ли прокси с 127.0.0.1 / ::1?
    • Пытаетесь ли вы использовать аутентификацию через доверенный прокси с обратным прокси на том же хосте, подключающимся через loopback-интерфейс?

    Исправление:

    • Для внутренних клиентов на том же хосте, которые не проходят через прокси, предпочтительно использовать аутентификацию по токену или паролю либо
    • Направьте трафик через адрес доверенного прокси вне loopback-интерфейса и сохраните этот IP-адрес в gateway.trustedProxies либо
    • Для намеренно настроенного обратного прокси на том же хосте задайте gateway.auth.trustedProxy.allowLoopback = true, сохраните loopback-адрес в gateway.trustedProxies и убедитесь, что прокси удаляет или перезаписывает заголовки идентификации.
    trusted_proxy_local_interface_source / trusted_proxy_local_interface_check_failed

    IP-адрес источника запроса совпал с одним из собственных адресов сетевых интерфейсов хоста Gateway вне loopback-интерфейса (а не с адресом прокси). Эта защита предотвращает подмену трафика с того же хоста в tailnet-сетях или мостовых сетях Docker. ..._check_failed означает, что при обнаружении интерфейсов произошла ошибка, поэтому OpenClaw отклоняет запрос.

    Проверьте:

    • Отправляет ли процесс на самом хосте Gateway заголовки идентификации напрямую, в обход прокси?
    • Работает ли прокси в том же сетевом пространстве имён, что и Gateway, с IP-адресом, который также отображается как локальный интерфейс?

    Исправление: направьте трафик прокси через адрес, который не привязан локально к хосту Gateway, либо используйте allowLoopback только для настоящей конфигурации прокси на том же хосте.

    trusted_proxy_user_missing

    Заголовок пользователя был пуст или отсутствовал. Проверьте:

    • Настроен ли ваш прокси на передачу заголовков идентификации?
    • Правильно ли указано имя заголовка? (Регистр не учитывается, но написание имеет значение.)
    • Действительно ли пользователь прошёл аутентификацию на прокси?
    trusted_proxy_missing_header_*

    Обязательный заголовок отсутствовал. Проверьте:

    • Конфигурацию прокси для этих конкретных заголовков.
    • Не удаляются ли заголовки где-либо в цепочке.
    trusted_proxy_user_not_allowed

    Пользователь аутентифицирован, но отсутствует в allowUsers. Добавьте его или удалите список разрешённых пользователей.

    trusted_proxy_no_proxies_configured / trusted_proxy_config_missing

    gateway.auth.mode имеет значение "trusted-proxy", но gateway.trustedProxies пуст, либо отсутствует сам gateway.auth.trustedProxy. Все запросы отклоняются, пока не будут заданы оба параметра.

    trusted_proxy_origin_not_allowed

    Аутентификация через доверенный прокси выполнена успешно, но браузерный заголовок Origin не прошёл проверку источника Control UI.

    Проверьте:

    • gateway.controlUi.allowedOrigins содержит точный источник браузера.
    • Вы не полагаетесь на источники с подстановочным знаком, если только намеренно не хотите разрешить доступ всем.
    • Если вы намеренно используете режим резервного определения по заголовку Host, gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true задан осознанно.
    Подключение успешно, но методы сообщают об отсутствии области доступа

    Соединение WebSocket устанавливается, но chat.history, sessions.list или models.list завершается ошибкой missing scope: operator.read.

    Распространённые причины:

    • Сеанс Control UI без устройства: аутентификация через доверенный прокси может разрешить соединение WebSocket без идентификатора устройства, но OpenClaw намеренно очищает области доступа в сеансах без устройства.
    • Собственный серверный клиент: gateway.controlUi.dangerouslyDisableDeviceAuth предназначен для Control UI и не предоставляет области доступа произвольным серверным или CLI-подобным клиентам WebSocket.
    • Чрезмерно узкий x-openclaw-scopes: если прокси добавляет этот заголовок в запрос обновления соединения WebSocket для Control UI, области доступа сеанса ограничиваются указанным набором. Пустое значение заголовка означает отсутствие областей доступа.

    Исправление:

    • Для Control UI используйте HTTPS, чтобы браузер мог создать идентификатор устройства и завершить сопряжение.
    • Для пользовательской автоматизации используйте идентификатор устройства и сопряжение, зарезервированный внутренний серверный путь прямого локального доступа gateway-client или административный HTTP RPC.
    • Используйте gateway.controlUi.dangerouslyDisableDeviceAuth: true только как временный аварийный путь для Control UI.
    WebSocket по-прежнему не работает

    Убедитесь, что ваш прокси:

    • Поддерживает обновление соединений WebSocket (Upgrade: websocket, Connection: upgrade).
    • Передаёт заголовки идентификации в запросах обновления соединения WebSocket, а не только в HTTP-запросах.
    • Не использует отдельный путь аутентификации для соединений WebSocket.

    Миграция с аутентификации по токену

  • Настройте прокси

    Настройте прокси для аутентификации пользователей и передачи заголовков.

  • Проверьте прокси отдельно

    Проверьте конфигурацию прокси отдельно (с помощью curl и заголовков).

  • Обновите конфигурацию OpenClaw

    Добавьте аутентификацию через доверенный прокси в конфигурацию OpenClaw.

  • Перезапустите Gateway

    Перезапустите Gateway.

  • Проверьте WebSocket

    Проверьте соединения WebSocket из Control UI.

  • Выполните аудит

    Запустите openclaw security audit и изучите результаты.

  • Связанные материалы

    Was this useful?
    On this page

    On this page