bin/kc.[sh|bat] start --proxy-headers forwarded
分布式环境通常需要使用反向代理。Keycloak 提供了多种选项来安全地与此类环境集成。
默认情况下,Keycloak 在以下端口上运行
8443
(当您通过 --http-enabled=true
显式启用 HTTP 时为 8080
)
9000
端口 8443
(如果启用了 HTTP,则为 8080
)用于管理 UI、账户控制台、SAML 和 OIDC 端点以及管理 REST API,如配置主机名 (v2) 指南中所述。
端口 9000
用于管理,其中包括运行状况检查和指标的端点,如配置管理接口 指南中所述。
即使您为前端/后端和管理使用不同的主机名(如为生产环境配置 Keycloak 中所述),您也只需要代理端口 8443
(或 8080
)。您不应代理端口 9000
,因为运行状况检查和指标直接使用这些端口,并且您不希望将此信息暴露给外部调用者。
Keycloak 将根据 proxy-headers
选项解析反向代理标头,该选项接受多个值
默认情况下,如果未指定该选项,则不解析任何反向代理标头。当不使用代理或使用 https 直通时,应使用此选项。
forwarded
启用对 Forwarded
标头的解析,如 RFC7239 中所述。
xforwarded
启用对非标准 X-Forwarded-*
标头的解析,例如 X-Forwarded-For
、X-Forwarded-Proto
、X-Forwarded-Host
和 X-Forwarded-Port
。
如果您将反向代理用于 https 直通以外的任何用途,并且未设置 proxy-headers 选项,则默认情况下,您将看到通过代理执行源检查的请求的 403 Forbidden 响应。 |
例如
bin/kc.[sh|bat] start --proxy-headers forwarded
如果选择了 forwarded 或 xforwarded ,请确保您的反向代理正确设置并覆盖相应的 Forwarded 或 X-Forwarded-* 标头。要设置这些标头,请查阅您的反向代理文档。请勿将 forwarded 或 xforwarded 与 https 直通一起使用。错误配置会将 Keycloak 暴露于安全漏洞。 |
请格外小心,确保您的反向代理通过 Forwarded
或 X-Forwarded-For
标头正确设置客户端地址。如果此标头配置不正确,恶意客户端可以设置此标头,并欺骗 Keycloak 认为客户端是从与实际地址不同的 IP 地址连接的。如果您对 IP 地址进行任何拒绝或允许列表操作,则此预防措施可能更为关键。
当使用 xforwarded 设置时,X-Forwarded-Port 优先于 X-Forwarded-Host 中包含的任何端口。 |
如果 TLS 连接在反向代理处终止(边缘终止),则需要通过 http-enabled 设置启用 HTTP。 |
Keycloak 假定它通过与 Keycloak 配置相同的上下文路径在反向代理下公开。默认情况下,Keycloak 通过根路径 (/
) 公开,这意味着它期望在反向代理上也通过 /
公开。在这些情况下,您可以为 hostname
选项使用完整 URL,例如,如果 Keycloak 通过反向代理在 /auth
上公开,则可以使用 --hostname=https://my.keycloak.org/auth
。
有关在不同主机名或上下文路径(包括管理 REST API 和控制台)上公开 Keycloak 的更多详细信息,请参阅 配置主机名 (v2)。
或者,您也可以更改 Keycloak 自身的上下文路径,以匹配反向代理使用的上下文路径,方法是使用 http-relative-path
选项,这将更改 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 创建 cookie AUTH_SESSION_ID,格式如 <会话 ID>.<所有者节点 ID>。在我们的示例中,它将是 123.node2。
响应将返回给用户,其中包含 Keycloak 登录屏幕和浏览器中的 AUTH_SESSION_ID cookie
从此时起,如果负载均衡器将所有后续请求转发到 node2,则会很有利,因为 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 路径提供。 |
/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 时,返回的远程地址将是来自实际连接客户端的地址。当使用 proxy-headers
选项时,该值不能为 true
。
当在兼容的 https 直通代理后面运行时,这很有用,因为请求标头无法被操纵。
例如
bin/kc.[sh|bat] start --proxy-protocol-enabled true
当代理配置为 TLS 终止代理时,客户端证书信息可以通过特定的 HTTP 请求标头转发到服务器,然后用于验证客户端身份。您可以根据您使用的代理配置服务器将如何检索客户端证书信息。
通过代理标头查找 X.509 身份验证的客户端证书被认为是安全敏感的。如果配置错误,伪造的客户端证书标头可用于身份验证。需要采取额外的预防措施,以确保通过代理标头传递的客户端证书信息是可信的。
|
服务器支持一些最常见的 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 |
持有链中其他证书的标头的前缀,并用于根据链的长度检索单个证书。例如,值 |
certificate-chain-length |
证书链的最大长度。 |
trust-proxy-verification |
启用信任 NGINX 代理证书验证,而不是将证书转发到 Keycloak 并在 Keycloak 中验证它。 |
cert-is-url-encoded |
转发的证书是否进行 URL 编码。在 NGINX 中,这对应于 |
NGINX SSL/TLS 模块不公开客户端证书链。Keycloak 的 NGINX 证书查找提供程序通过使用 Keycloak 信任存储重建它。
如果您正在使用此提供程序,请参阅 配置受信任的证书,了解如何配置 Keycloak 信任存储。