使用反向代理

了解如何配置 Keycloak 與反向代理、API 閘道或負載平衡器一同使用。

分散式環境經常需要使用反向代理。Keycloak 提供多種選項來與此類環境安全整合。

配置反向代理標頭

Keycloak 將根據 proxy-headers 選項解析反向代理標頭,該選項接受多個值

  • 預設情況下,如果未指定此選項,則不會解析任何反向代理標頭。

  • forwarded 啟用根據 RFC7239 解析 Forwarded 標頭。

  • xforwarded 啟用解析非標準的 X-Forwarded-* 標頭,例如 X-Forwarded-ForX-Forwarded-ProtoX-Forwarded-HostX-Forwarded-Port

如果您使用反向代理進行除 https 直通之外的任何操作,並且未設定 proxy-headers 選項,則預設情況下,您會看到透過代理執行來源檢查的請求返回 403 Forbidden 回應。

例如

bin/kc.[sh|bat] start --proxy-headers forwarded
如果選擇 forwardedxforwarded,請確保您的反向代理正確設定並覆寫 ForwardedX-Forwarded-* 標頭。若要設定這些標頭,請查閱您的反向代理的文件。錯誤的配置會讓 Keycloak 面臨安全漏洞。

請採取額外預防措施,確保用戶端位址透過 ForwardedX-Forwarded-For 標頭由您的反向代理正確設定。如果此標頭配置不正確,惡意用戶端可以設定此標頭,並欺騙 Keycloak 認為用戶端是從與實際位址不同的 IP 位址連線的。如果您對 IP 位址進行任何拒絕或允許列表,此預防措施可能更為重要。

當使用 xforwarded 設定時,X-Forwarded-Port 的優先順序高於 X-Forwarded-Host 中包含的任何連接埠。
如果 TLS 連線在反向代理 (邊緣終止) 處終止,則需要透過「http-enabled」設定啟用 HTTP。

反向代理上的不同上下文路徑

Keycloak 假設它是透過與 Keycloak 配置相同的上下文路徑透過反向代理公開的。預設情況下,Keycloak 是透過根目錄 (/) 公開的,這表示它也希望透過反向代理在 / 上公開。您可以在這些情況下使用完整 URL 作為 hostname 選項,例如,如果 Keycloak 是透過反向代理在 /auth 上公開,則使用 --hostname=https://my.keycloak.org/auth

如需在不同的主機名稱或上下文路徑上公開 Keycloak (包括管理 REST API 和主控台) 的更多詳細資訊,請參閱 配置主機名稱 (v2)

或者,您也可以使用 http-relative-path 選項來變更 Keycloak 本身的上下文路徑,以符合反向代理的上下文路徑,這會變更 Keycloak 本身的上下文路徑,以符合反向代理使用的上下文路徑。

啟用黏性連線

典型的叢集部署包含負載平衡器 (反向代理) 和私有網路上的 2 個或多個 Keycloak 伺服器。為了效能,如果負載平衡器將與特定瀏覽器連線相關的所有請求轉送至相同的 Keycloak 後端節點,可能會很有用。

原因是,Keycloak 使用 Infinispan 分散式快取在底層儲存與目前驗證連線和使用者連線相關的資料。Infinispan 分散式快取的配置限制了擁有者的數量。這表示連線相關資料僅儲存在某些叢集節點中,如果其他節點想要存取這些資料,則需要遠端查找這些資料。

例如,如果 ID 為 123 的驗證連線儲存在 node1 上的 Infinispan 快取中,然後 node2 需要查找此連線,則需要透過網路將請求傳送至 node1,以傳回特定的連線實體。

如果特定的連線實體始終在本機可用會很有利,這可以藉由黏性連線來完成。在具有公用前端負載平衡器和兩個後端 Keycloak 節點的叢集環境中的工作流程可以是這樣

  • 使用者傳送初始請求以查看 Keycloak 登入畫面

  • 此請求由前端負載平衡器處理,該負載平衡器將其轉送至某些隨機節點 (例如,node1)。嚴格來說,該節點不必是隨機的,但可以根據其他一些條件 (用戶端 IP 位址等) 選擇。這一切都取決於基礎負載平衡器 (反向代理) 的實作和配置。

  • Keycloak 建立具有隨機 ID (例如,123) 的驗證連線,並將其儲存至 Infinispan 快取。

  • Infinispan 分散式快取根據連線 ID 的雜湊值指派連線的主要擁有者。如需更多相關詳細資訊,請參閱 Infinispan 文件。我們假設 Infinispan 指派 node2 為此連線的擁有者。

  • Keycloak 建立格式為 <連線 ID>.<擁有者節點 ID> 的 Cookie AUTH_SESSION_ID。在我們的範例中,它將是 123.node2 。

  • 回應會與 Keycloak 登入畫面和瀏覽器中的 AUTH_SESSION_ID Cookie 一起傳回給使用者

從這一點開始,如果負載平衡器將所有後續請求轉送至 node2 會很有利,因為此節點是 ID 為 123 的驗證連線的擁有者,因此 Infinispan 可以在本機查找此連線。驗證完成後,驗證連線會轉換為使用者連線,使用者連線也會儲存在 node2 上,因為它具有相同的 ID 123。

黏性連線對於叢集設定不是強制性的,但是由於上述原因,它對於效能有益。您需要將負載平衡器配置為透過 AUTH_SESSION_ID Cookie 進行黏性連線。具體如何執行此操作取決於您的負載平衡器。

如果您的代理支援連線親和性而不處理來自後端節點的 Cookie,則應將 spi-sticky-session-encoder-infinispan-should-attach-route 選項設定為 false,以避免將節點附加至 Cookie,而僅依賴反向代理的功能。

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

預設情況下,spi-sticky-session-encoder-infinispan-should-attach-route 選項值為 true,以便將節點名稱附加至 Cookie,以向反向代理指示應將後續請求傳送至的節點。

公開路徑建議

使用反向代理時,Keycloak 只需要公開某些路徑。下表顯示了建議公開的路徑。

Keycloak 路徑 反向代理路徑 已公開 原因

/

-

公開所有路徑時,會不必要地公開管理路徑。

/admin/

-

公開的管理路徑會導致不必要的攻擊向量。

/realms/

/realms/

此路徑是正確運作所必需的,例如,對於 OIDC 端點。

/resources/

/resources/

此路徑是正確提供資產所必需的。它可以從 CDN (而不是 Keycloak 路徑) 提供。

/robots.txt

/robots.txt

搜尋引擎規則

/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 時,返回的遠端位址將是來自實際連線用戶端的位址。

當在相容的 https 直通代理後方執行時,這非常有用,因為無法操作請求標頭。

例如

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

啟用用戶端憑證查找

當代理配置為 TLS 終止代理時,用戶端憑證資訊可以透過特定的 HTTP 請求標頭轉送至伺服器,然後用於驗證用戶端。您可以根據您使用的代理配置伺服器如何擷取用戶端憑證資訊。

伺服器支援一些最常見的 TLS 終止代理,例如

代理 提供者

Apache HTTP 伺服器

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 會指示伺服器從標頭 CERT_CHAIN_0CERT_CHAIN_9 載入其他憑證 (如果 certificate-chain-length 設定為 10)。

certificate-chain-length

憑證鏈的最大長度。

trust-proxy-verification

啟用信任 NGINX 代理憑證驗證,而不是將憑證轉送至 Keycloak 並在 Keycloak 中驗證。

配置 NGINX 提供者

NGINX SSL/TLS 模組不會公開用戶端憑證鏈。Keycloak 的 NGINX 憑證查找提供者會使用 Keycloak 信任儲存庫重建憑證鏈。

如果您使用此提供者,請參閱 配置信任的憑證,了解如何配置 Keycloak 信任儲存庫。

相關選項

hostname

伺服器公開的位址。

可以是完整的 URL,或僅是主機名稱。當僅提供主機名稱時,協定、連接埠和上下文路徑會從請求中解析。

CLI: --hostname
Env: KC_HOSTNAME

僅當啟用 hostname:v2 功能時可用

hostname-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 時,返回的遠端位址將會是來自實際連線用戶端的位址。

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

在此頁面上