bin/kc.[sh|bat] start --proxy-headers forwarded
分布式环境通常需要使用反向代理。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>
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 SSL/TLS 模块不公开客户端证书链。Keycloak 的 NGINX 证书查找提供者通过使用 Keycloak 信任库来重建它。
如果您正在使用此提供者,请参见 配置受信任的证书,了解如何配置 Keycloak 信任库。
值 | |
---|---|
仅在启用 hostname:v2 功能时可用 |
|
仅在启用 hostname:v2 功能时可用 |
|
|
(默认) |
|
|
|
|
|