使用反向代理

了解如何将 Keycloak 与反向代理、API 网关或负载均衡器一起配置。

分布式环境通常需要使用反向代理。Keycloak 提供了多种选项来安全地集成到此类环境中。

配置反向代理头

Keycloak 将根据 `proxy-headers` 选项解析反向代理头,该选项接受多个值

  • 默认情况下,如果未指定该选项,则不会解析任何反向代理头。

  • forwarded 启用根据 RFC7239 解析 `Forwarded` 头。

  • xforwarded 启用解析非标准的 `X-Forwarded-*` 头,例如 `X-Forwarded-For`、`X-Forwarded-Proto`、`X-Forwarded-Host` 和 `X-Forwarded-Port`。

如果您正在使用反向代理进行除了 https 传输之外的其他操作,并且未设置 `proxy-headers` 选项,那么默认情况下,您会看到对通过代理执行源检查的请求的 403 禁止响应。

例如

bin/kc.[sh|bat] start --proxy-headers forwarded
如果选择了 `forwarded` 或 `xforwarded`,请确保您的反向代理正确设置并覆盖 `Forwarded` 或 `X-Forwarded-*` 头。要设置这些头,请参考您反向代理的文档。错误配置会导致 Keycloak 暴露于安全漏洞。

采取额外预防措施以确保您的反向代理通过 `Forwarded` 或 `X-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

有关在不同主机名或上下文路径(包括管理 REST API 和控制台)上公开 Keycloak 的更多详细信息,请参见 配置主机名(v2)

或者,您也可以使用 `http-relative-path` 选项更改 Keycloak 本身的上下文路径以匹配反向代理的上下文路径,这将更改 Keycloak 本身的上下文路径以匹配反向代理使用的上下文路径。

启用粘性会话

典型的集群部署包括负载均衡器(反向代理)和私有网络上的 2 个或更多 Keycloak 服务器。出于性能目的,如果负载均衡器将与特定浏览器会话相关的所有请求转发到同一个 Keycloak 后端节点,则可能很有用。

原因是 Keycloak 在后台使用 Infinispan 分布式缓存来保存与当前身份验证会话和用户会话相关的数据。Infinispan 分布式缓存配置了有限数量的拥有者。这意味着会话相关数据仅存储在某些集群节点中,如果其他节点想要访问它,则需要远程查找数据。

例如,如果具有 ID 123 的身份验证会话存储在节点 1 上的 Infinispan 缓存中,然后节点 2 需要查找此会话,它需要将请求发送到节点 1 上的网络以返回特定会话实体。

如果特定会话实体始终在本地可用,则是有益的,这可以通过粘性会话来实现。具有公共前端负载均衡器和两个后端 Keycloak 节点的集群环境中的工作流程可能如下所示

  • 用户发送初始请求以查看 Keycloak 登录屏幕

  • 此请求由前端负载均衡器处理,它将请求转发到某个随机节点(例如,节点 1)。严格来说,该节点不需要是随机的,但可以根据其他标准(客户端 IP 地址等)来选择。这完全取决于底层负载均衡器(反向代理)的实现和配置。

  • Keycloak 使用随机 ID(例如,123)创建身份验证会话并将其保存到 Infinispan 缓存中。

  • Infinispan 分布式缓存根据会话 ID 的哈希值分配会话的主要拥有者。有关此方面的更多详细信息,请参见 Infinispan 文档。假设 Infinispan 分配节点 2 作为此会话的拥有者。

  • Keycloak 创建格式为 <session-id>.<owner-node-id> 的 cookie AUTH_SESSION_ID。在我们的示例中,它将是 123.node2。

  • 将响应返回给用户,其中包含 Keycloak 登录屏幕和浏览器中的 AUTH_SESSION_ID cookie

从此时起,如果负载均衡器将所有后续请求转发到节点 2,则是有益的,因为它是拥有 ID 为 123 的身份验证会话的节点,因此 Infinispan 可以本地查找此会话。完成身份验证后,身份验证会话将转换为用户会话,该会话也将保存到节点 2 上,因为它具有相同的 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-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_0` 到 `CERT_CHAIN_9` 加载其他证书,如果 `certificate-chain-length` 设置为 `10`。

certificate-chain-length

证书链的最大长度。

trust-proxy-verification

启用信任 NGINX 代理证书验证,而不是将证书转发到 Keycloak 并验证它。

配置 NGINX 提供者

NGINX SSL/TLS 模块不公开客户端证书链。Keycloak 的 NGINX 证书查找提供者通过使用 Keycloak 信任库来重建它。

如果您正在使用此提供者,请参见 配置受信任的证书,了解如何配置 Keycloak 信任库。

相关选项

hostname

服务器公开的地址。

可以是完整的 URL,也可以只是主机名。仅提供主机名时,方案、端口和上下文路径将从请求中解析。

CLI: --hostname
环境: KC_HOSTNAME

仅在启用 hostname:v2 功能时可用

hostname-admin

访问管理控制台的地址。

如果您使用反向代理公开管理控制台,而该地址与 `hostname` 选项中指定的地址不同,则使用此选项。

CLI: --hostname-admin
环境: KC_HOSTNAME_ADMIN

仅在启用 hostname:v2 功能时可用

http-relative-path

设置相对于 / 的路径以提供资源。

路径必须以 / 开头。

CLI: --http-relative-path
环境: KC_HTTP_RELATIVE_PATH

/ (默认)

proxy-headers

服务器应接受的代理头。

错误配置可能会导致服务器暴露于安全漏洞。优先于已弃用的代理选项。

CLI: --proxy-headers
环境: KC_PROXY_HEADERS

forwarded, xforwarded

proxy-protocol-enabled

服务器是否应在从代理后端提供请求时使用 HA PROXY 协议。

设置为 true 时,返回的远程地址将是实际连接客户端的地址。

CLI: --proxy-protocol-enabled
环境: KC_PROXY_PROTOCOL_ENABLED

true, false (默认)

proxy-trusted-addresses

受信任代理地址的逗号分隔列表。

如果设置,则将忽略来自其他地址的代理头。默认情况下,所有地址都可信。受信任的代理地址指定为 IP 地址(IPv4 或 IPv6)或无类域间路由 (CIDR) 表示法。仅在设置 proxy-headers 时可用。

CLI: --proxy-trusted-addresses
环境: KC_PROXY_TRUSTED_ADDRESSES

在本页上