リバースプロキシの使用

Keycloakをリバースプロキシ、APIゲートウェイ、またはロードバランサーと共に構成する方法を学びます。

分散環境では、リバースプロキシの使用が頻繁に必要になります。Keycloakは、そのような環境と安全に統合するためのいくつかのオプションを提供しています。

プロキシされるポート

Keycloakはデフォルトで次のポートで実行されます

  • 8443 (--http-enabled=true でHTTPを明示的に有効にした場合は 8080)

  • 9000

ポート 8443 (または HTTP が有効な場合は 8080) は、ホスト名の設定 (v2) ガイドで説明されているように、Admin UI、アカウントコンソール、SAMLおよびOIDCエンドポイント、およびAdmin REST APIに使用されます。

ポート 9000 は、管理インターフェースの設定 ガイドで説明されているように、ヘルスチェックとメトリクスのエンドポイントを含む管理に使用されます。

フロントエンド/バックエンドと管理に異なるホスト名を使用する場合でも、本番環境向けKeycloakの設定 で説明されているように、ポート 8443 (または 8080) のみをプロキシする必要があります。ヘルスチェックとメトリクスはこれらのポートを直接使用し、この情報を外部の呼び出し元に公開したくないため、ポート 9000 をプロキシしないでください。

リバースプロキシヘッダーの設定

Keycloakは、いくつかの値を受け入れる proxy-headers オプションに基づいて、リバースプロキシヘッダーを解析します。

  • デフォルトでは、オプションが指定されていない場合、リバースプロキシヘッダーは解析されません。これは、プロキシが使用されていない場合、またはHTTPSパススルーで使用する必要があります。

  • forwarded は、RFC7239 に従って、Forwarded ヘッダーの解析を有効にします。

  • xforwarded は、X-Forwarded-ForX-Forwarded-ProtoX-Forwarded-Host、および X-Forwarded-Port などの非標準の X-Forwarded-* ヘッダーの解析を有効にします。

HTTPSパススルー以外の目的でリバースプロキシを使用しており、proxy-headers オプションを設定しない場合、デフォルトでは、オリジンチェックを実行するプロキシ経由のリクエストに対して 403 Forbidden レスポンスが表示されます。

bin/kc.[sh|bat] start --proxy-headers forwarded
forwarded または xforwarded のいずれかが選択されている場合は、リバースプロキシが Forwarded ヘッダーまたは X-Forwarded-* ヘッダーをそれぞれ適切に設定および上書きしていることを確認してください。これらのヘッダーを設定するには、リバースプロキシのドキュメントを参照してください。HTTPSパススルーで forwarded または xforwarded を使用しないでください。誤った設定は、Keycloakをセキュリティ脆弱性にさらす可能性があります。

クライアントアドレスが Forwarded ヘッダーまたは X-Forwarded-For ヘッダーを介してリバースプロキシによって適切に設定されていることを確認するために、特別な予防措置を講じてください。このヘッダーが正しく構成されていない場合、不正なクライアントがこのヘッダーを設定し、クライアントが実際のアドレスとは異なるIPアドレスから接続されているとKeycloakに誤認させることができます。IPアドレスの拒否または許可リストを作成する場合、この予防措置はより重要になる可能性があります。

xforwarded 設定を使用する場合、X-Forwarded-PortX-Forwarded-Host に含まれるポートよりも優先されます。
TLS接続がリバースプロキシ (エッジターミネーション) で終端される場合、http-enabled 設定を介してHTTPを有効にする必要があります。

リバースプロキシ上の異なるコンテキストパス

Keycloakは、Keycloakが構成されているのと同じコンテキストパスでリバースプロキシを介して公開されていると想定しています。デフォルトでは、Keycloakはルート (/) を介して公開されています。つまり、リバースプロキシでも / で公開されることを期待しています。このような場合、hostname オプションに完全なURLを使用できます。たとえば、Keycloakがリバースプロキシの /auth で公開されている場合は、--hostname=https://my.keycloak.org/auth を使用します。

Administration REST APIおよびコンソールを含む、異なるホスト名またはコンテキストパスでKeycloakを公開する方法の詳細については、ホスト名の設定 (v2) を参照してください。

あるいは、http-relative-path オプションを使用して、Keycloak自体のコンテキストパスをリバースプロキシのコンテキストパスに一致するように変更することもできます。これにより、Keycloak自体のコンテキストパスがリバースプロキシで使用されるコンテキストパスに一致するように変更されます。

スティッキーセッションの有効化

一般的なクラスタデプロイメントは、ロードバランサー (リバースプロキシ) とプライベートネットワーク上の2台以上のKeycloakサーバーで構成されています。パフォーマンス上の理由から、ロードバランサーが特定のブラウザセッションに関連するすべてのリクエストを同じKeycloakバックエンドノードに転送すると役立つ場合があります。

その理由は、Keycloakが現在の認証セッションとユーザーセッションに関連するデータを保存するために、Infinispan分散キャッシュを内部で使用しているためです。Infinispan分散キャッシュは、オーナーの数が制限されて構成されています。つまり、セッション関連データは一部のクラスタノードにのみ格納され、他のノードがデータにアクセスするにはリモートでデータを検索する必要があります。

たとえば、ID 123 の認証セッションが node1 の Infinispan キャッシュに保存され、node2 がこのセッションを検索する必要がある場合、特定のセッションエンティティを返すために、ネットワーク経由で node1 にリクエストを送信する必要があります。

特定のセッションエンティティが常にローカルで利用可能な場合は有益です。これは、スティッキーセッションを使用することで実現できます。パブリックフロントエンドロードバランサーと2つのバックエンドKeycloakノードを備えたクラスタ環境でのワークフローは次のようになります。

  • ユーザーがKeycloakログイン画面を表示するための初期リクエストを送信します。

  • このリクエストは、フロントエンドロードバランサーによって処理され、ランダムなノード (例: node1) に転送されます。厳密に言うと、ノードはランダムである必要はなく、他の基準 (クライアントIPアドレスなど) に従って選択できます。これはすべて、基盤となるロードバランサー (リバースプロキシ) の実装と構成によって異なります。

  • Keycloakは、ランダムなID (例: 123) で認証セッションを作成し、Infinispanキャッシュに保存します。

  • Infinispan分散キャッシュは、セッションIDのハッシュに基づいてセッションのプライマリオーナーを割り当てます。これに関する詳細については、Infinispanドキュメントを参照してください。Infinispanが node2 をこのセッションのオーナーとして割り当てたと仮定しましょう。

  • Keycloakは、<session-id>.<owner-node-id> のような形式でクッキー AUTH_SESSION_ID を作成します。この例の場合、123.node2 になります。

  • レスポンスは、Keycloakログイン画面とブラウザの AUTH_SESSION_ID クッキーと共にユーザーに返されます。

この時点から、ロードバランサーが次のすべてのリクエストを node2 に転送すると有益です。これは、node2 が ID 123 の認証セッションのオーナーであり、Infinispan がこのセッションをローカルで検索できるためです。認証が完了すると、認証セッションはユーザーセッションに変換され、同じ ID 123 を持つため、node2 にも保存されます。

スティッキーセッションはクラスタ構成には必須ではありませんが、上記の理由からパフォーマンスに優れています。ロードバランサーが AUTH_SESSION_ID クッキーを維持するように構成する必要があります。この変更を行うための適切な手順は、ロードバランサーによって異なります。

プロキシがバックエンドノードからのクッキーを処理せずにセッションアフィニティをサポートしている場合は、ノードをクッキーにアタッチすることを避け、リバースプロキシの機能のみに依存するために、spi-sticky-session-encoder-infinispan-should-attach-route オプションを false に設定する必要があります。

bin/kc.[sh|bat] start --spi-sticky-session-encoder-infinispan-should-attach-route=false

デフォルトでは、spi-sticky-session-encoder-infinispan-should-attach-route オプションの値は true であるため、ノード名がクッキーにアタッチされ、後続のリクエストを送信する必要があるノードをリバースプロキシに示すことができます。

公開パスの推奨事項

リバースプロキシを使用する場合、Keycloakは特定のパスのみを公開する必要があります。次の表は、公開が推奨されるパスを示しています。

Keycloakパス リバースプロキシパス 公開 理由

/

-

いいえ

すべてのパスを公開すると、管理パスが不必要に公開されます。

/admin/

-

いいえ

公開された管理パスは、不必要な攻撃ベクトルにつながります。

/realms/

/realms/

はい

このパスは、たとえば、OIDCエンドポイントが正しく機能するために必要です。

/resources/

/resources/

はい

このパスは、アセットを正しく提供するために必要です。Keycloakパスの代わりにCDNから提供される場合があります。

/metrics

-

いいえ

公開されたメトリクスは、不必要な攻撃ベクトルにつながります。

/health

-

いいえ

公開されたヘルスチェックは、不必要な攻撃ベクトルにつながります。

リバースプロキシ/ゲートウェイのパブリックAPIのルートパス / でKeycloakを実行することを前提としています。そうでない場合は、パスに目的のプレフィックスを付けます。

信頼できるプロキシ

信頼できるプロキシからのプロキシヘッダーのみが使用されるようにするには、proxy-trusted-addresses オプションを、IPアドレス (IPv4またはIPv6) またはクラスレスドメイン間ルーティング (CIDR) 表記のコンマ区切りリストに設定します。

bin/kc.[sh|bat] start --proxy-headers forwarded --proxy-trusted-addresses=192.168.0.32,127.0.0.0/8

PROXYプロトコル

proxy-protocol-enabled オプションは、サーバーがプロキシの背後からのリクエストを処理するときに HA PROXY プロトコルを使用するかどうかを制御します。true に設定すると、返されるリモートアドレスは、実際に接続しているクライアントからのアドレスになります。proxy-headers オプションを使用している場合、値は true にすることはできません。

これは、リクエストヘッダーを操作できないため、互換性のあるHTTPSパススループロキシの背後で実行する場合に役立ちます。

bin/kc.[sh|bat] start --proxy-protocol-enabled true

クライアント証明書ルックアップの有効化

プロキシがTLS終端プロキシとして構成されている場合、クライアント証明書情報を特定のHTTPリクエストヘッダーを介してサーバーに転送し、クライアントの認証に使用できます。使用しているプロキシに応じて、サーバーがクライアント証明書情報を取得する方法を構成できます。

X.509認証用のプロキシヘッダーを介したクライアント証明書ルックアップは、セキュリティに敏感であると見なされます。誤って構成すると、偽造されたクライアント証明書ヘッダーが認証に使用される可能性があります。プロキシヘッダーを介して渡されるクライアント証明書情報が信頼できることを保証するために、特別な予防措置を講じる必要があります。

  • ユースケースで、クライアント証明書ルックアップにプロキシヘッダーを使用することを意味する、再暗号化またはエッジTLS終端が必要かどうかを再確認してください。X.509認証が必要な場合、TLSパススルーは、プロキシヘッダーを介して証明書を渡す必要がないため、より安全なオプションとして推奨されます。プロキシヘッダーからのクライアント証明書ルックアップは、再暗号化およびエッジTLS終端にのみ適用できます。

  • パススルーがオプションでない場合は、次のセキュリティ対策を実装してください。

    • Keycloakが隔離され、プロキシからの接続のみを受け入れることができるようにネットワークを構成します。

    • プロキシが spi-x509cert-lookup-<provider>-ssl-client-cert オプションで構成されているヘッダーを上書きしていることを確認してください。

    • spi-x509cert-lookup-<provider>-trust-proxy-verification 設定に特に注意してください。プロキシがクライアント証明書を検証できると信頼できる場合にのみ有効にしてください。プロキシがクライアント証明書チェーンを検証せずに spi-x509cert-lookup-<provider>-trust-proxy-verification=true を設定すると、偽造されたクライアント証明書が認証に使用される場合に、Keycloakがセキュリティ脆弱性にさらされます。

サーバーは、次のような最も一般的なTLS終端プロキシをサポートしています。

プロキシ プロバイダー

Apache HTTP Server

apache

HAProxy

haproxy

NGINX

nginx

リクエストからクライアント証明書を取得する方法を構成するには、次のことを行う必要があります。

対応するプロキシプロバイダーを有効にする
bin/kc.[sh|bat] build --spi-x509cert-lookup-provider=<provider>
HTTPヘッダーを構成する
bin/kc.[sh|bat] start --spi-x509cert-lookup-<provider>-ssl-client-cert=SSL_CLIENT_CERT --spi-x509cert-lookup-<provider>-ssl-cert-chain-prefix=CERT_CHAIN --spi-x509cert-lookup-<provider>-certificate-chain-length=10

HTTPヘッダーを構成するときは、使用している値が、クライアント証明書情報とともにプロキシによって転送されるヘッダーの名前に対応していることを確認する必要があります。

プロバイダーを構成するために使用可能なオプションは次のとおりです。

オプション 説明

ssl-client-cert

クライアント証明書を保持するヘッダーの名前

ssl-cert-chain-prefix

チェーン内の追加の証明書を保持し、チェーンの長さに応じて個々の証明書を取得するために使用されるヘッダーのプレフィックス。たとえば、値 CERT_CHAIN は、certificate-chain-length10 に設定されている場合、サーバーにヘッダー CERT_CHAIN_0 から CERT_CHAIN_9 から追加の証明書をロードするように指示します。

certificate-chain-length

証明書チェーンの最大長。

trust-proxy-verification

証明書をKeycloakに転送してKeycloakで検証する代わりに、NGINXプロキシ証明書検証を信頼することを有効にします。

cert-is-url-encoded

転送された証明書がURLエンコードされているかどうか。NGINXでは、これは $ssl_client_cert および $ssl_client_escaped_cert 変数に対応します。これは、Traefik PassTlsClientCertミドルウェアにも使用できます。これは、クライアント証明書をエンコードせずに送信するためです。

NGINXプロバイダーの設定

NGINX SSL/TLSモジュールは、クライアント証明書チェーンを公開しません。KeycloakのNGINX証明書ルックアッププロバイダーは、Keycloakトラストストアを使用して再構築します。

このプロバイダーを使用している場合は、Keycloakトラストストアを構成する方法について、信頼できる証明書の構成 を参照してください。

関連オプション

ホスト名

サーバーが公開されるアドレス。

完全なURL、またはホスト名のみを指定できます。ホスト名のみが指定されている場合、スキーム、ポート、およびコンテキストパスはリクエストから解決されます。

CLI: --hostname
Env: KC_HOSTNAME

hostname:v2機能が有効になっている場合にのみ使用可能

ホスト名-admin

管理コンソールにアクセスするためのアドレス。

hostname オプションで指定されたアドレスとは異なるアドレスのリバースプロキシを使用して管理コンソールを公開する場合は、このオプションを使用します。

CLI: --hostname-admin
Env: KC_HOSTNAME_ADMIN

hostname:v2機能が有効になっている場合にのみ使用可能

http-relative-path

リソースを提供するための / 相対パスを設定します。

パスは / で始まる必要があります。

CLI: --http-relative-path
Env: KC_HTTP_RELATIVE_PATH

/ (デフォルト)

proxy-headers

サーバーで受け入れられる必要があるプロキシヘッダー。

誤った構成は、サーバーをセキュリティ脆弱性にさらす可能性があります。非推奨の proxy オプションよりも優先されます。

CLI: --proxy-headers
Env: KC_PROXY_HEADERS

forwarded, xforwarded

proxy-protocol-enabled

サーバーがプロキシの背後からのリクエストを処理するときに HA PROXY プロトコルを使用するかどうか。

true に設定すると、返されるリモートアドレスは、実際に接続しているクライアントからのアドレスになります。proxy-headers が使用されている場合は有効にできません。

CLI: --proxy-protocol-enabled
Env: KC_PROXY_PROTOCOL_ENABLED

true, false (デフォルト)

proxy-trusted-addresses

信頼できるプロキシアドレスのコンマ区切りリスト。

設定されている場合、他のアドレスからのプロキシヘッダーは無視されます。デフォルトでは、すべてのアドレスが信頼されています。信頼できるプロキシアドレスは、IPアドレス (IPv4またはIPv6) またはクラスレスドメイン間ルーティング (CIDR) 表記として指定されます。proxy-headers が設定されている場合にのみ使用できます。

CLI: --proxy-trusted-addresses
Env: KC_PROXY_TRUSTED_ADDRESSES

このページ内