如何部署RHBK的Nginx反向代理?
- By : Will
- Category : Keycloak, Reverse Proxy

1 基础知识
1.1 代理模式
1.1.1 Edge模式
– 该模式代理与红帽构建的Keycloak之间的http通讯
– 该模式适用于高度安全的内网环境
– 反向代理对Keycloak使用http连接
– 反向代理对Keycloak客户端使用TLS连接
1.1.2 Reencrypt模式
– 该模式代理与红帽构建的Keycloak之间的https通讯
– 该模式适用于红帽构建的Keycloak之间内部通讯也需要受保护的环境
– 该模式需要反向代理和Keycloak各自维护自己的加密证书,确保两者之间的通信安全
1.1.3 Passthrough模式
– 该模式代理直接转发HTTPS到红帽构建的Keycloak,而不中止(解密)TLS
– 反向代理收到客户端HTTPS请求后,不解密该请求而直接转发给红帽构建Keycloak
– 反向代理不对HTTPS连接进行解密,即保持整个连接的加密状态。
– 反向代理与客户端之间的安全连接依赖于红帽构建的Keycloak的服务密钥和证书
– 意味着安全性是基于 Keycloak 服务器的证书,而不是反向代理的证书
1.1.4 代理的命令行配置范例
bin/kc.[sh|bat] start --proxy <mode>
注:支持的可选值“edge”、“reencrypt”和“passthrough”
1.2 代理设置要求
1.2.1 HTTP标头的要求
– 代理传递客户端请求的标准依据为RFC7239
– Keycloak需要代理设置非标准X-Forwarded用于正确处理请求
– Keycloak需要代理设置特定非标准 X-Forwarded标头
— 标头“X-Forwarded-For”,包含客户端的原始 IP 地址。
— 标头“X-Forwarded-Proto”,指示原始请求使用的协议(HTTP 或 HTTPS)。
— 标头“X-Forwarded-Host”,原始请求的主机名。
— 标头“X-Forwarded-Port”,原始请求使用的端口。
1.2.2 Context-path要求
– 红帽构建的Keycloak默认站点跟路径为“/”
– 如果修改为URI路径,可使用配置参数“hostname-path”或“hostname-url”
命令行配置范例如下,
--hostname-path=/auth --hostname-url=https://example.com/auth --http-relative-path=/auth
1.2.3 禁用主机名称严格模式
– 红帽构建的Keycloak默认需要设置调用的主机名
– 如果反向代理被配置为检查主机名,可用“hostname-strict=false”参数设置接受任何主机名称
命令行启动参数设置范例,
bin/kc.[sh|bat] start --proxy <mode> --hostname-strict=false
1.2.4 启用粘性会话
– 典型的集群由负载均衡器(反向代理)和2个以上的红帽构建的Keycloak组成
– 出于性能要求,浏览器需与负载均衡器保持同一会话,即同一请求转发到同一红帽构建的Keycloak后端节点
– 实现会话保此,需要红帽构建的Keycloak与Infinispan分布式缓存集成
– Infinispan分布式缓存主要存储当前身份验证会话和用户会话相关的数据
粘性会话的工作流程,
– 用户发送请求服务器通过反向代理返回红帽构建Keycloak的登陆页面
– 负载均衡器根据负载均衡算法选择后端的红帽构建Keyclak节点
– 红帽构建Keyclak节点使用随即ID(如123)创建身份验证会话,并保存到Infinispan分布式缓存
– Infinispan分布式缓存根据会话ID的哈希值分配会话的主要所有者,假设分布到node2。
– 红帽构建Keycloak创建的“cookie AUTH_SESSION_ID”格式为“<session-id.owner-node-id>”,如“123.node2”
– 红帽构建Keycloak的登陆页面根据“cookie AUTH_SESSION_ID”的值返回对应的用户页面
禁用粘性会话的命令参数,该参数默认为“true”,
bin/kc.[sh|bat] start --spi-sticky-session-encoder-infinispan-should-attach-route=false
1.2.5 管理控制台的正确公开
– 管理控制太的URL基于请求动态生成,包括HTTP和HTTPS、主机名和端口
– 在使用边缘代理模式时,如代理配置不正确,可能会导致管理控制台以不安全的HTTP方案访问
为确保管理控制台使用正确的配置,你需要在反向代理配置以下“X-Forwarded标头”,
– 标头“X-Forwarded-For”,标记客户端的原始IP地址。
– 标头“X-Forwarded-Proto”,标记指定原始请求的协议(HTTP 或 HTTPS)。
– 标头“X-Forwarded-Host”,标记原始请求的主机名。
– 标头“X-Forwarded-Port”,标记原始请求使用的端口。
Nginx代理设置范例,
location / { proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port $server_port; proxy_pass http://keycloak_backend; }
1.2.6 仅开放必要的URI
红帽构建的 Keycloak 路径 | 反向代理路径 | expose | 原因 |
---|---|---|---|
/ | – | 否 | 在公开所有路径时,管理路径会不必要地公开。 |
/admin/ | – | 否 | 公开的管理路径会导致不必要的攻击向量。 |
/js/ | – | 是(请参阅以下备注) | 访问”内部”客户端所需的 keycloak.js,例如帐户控制台 |
/welcome/ | – | 否 | 不需要在初始安装后公开欢迎页面。 |
/realms/ | /realms/ | 是 | 需要这个路径才能正常工作,例如对于 OIDC 端点。 |
/resources/ | /resources/ | 是 | 需要此路径才能正确提供资产。它可以从 CDN 而不是红帽构建的 Keycloak 路径提供。 |
/robots.txt | /robots.txt | 是 | 搜索引擎规则 |
/metrics | – | 否 | 公开的指标会导致不必要的攻击向量。 |
/health | – | 否 | 公开健康检查会导致不必要的攻击向量。 |
1.2.7 启用客户端证书查找
– 当代理设置为TLS终止模式时,客户端证书信息可通过特定的HTTP请求标头转发到代理服务器用于验证客户端
– 红帽构建Keycloak支持根据代理的类型,配置Keycloak如何检索客户端证书的信息
命令行配置范例,参数“spi-x509cert-lookup-provider”可选包括apache、haproxy或nginx。
bin/kc.sh build --spi-x509cert-lookup-provider=nginx
配置检索客户端证书信息的HTTP标头,配置范例如下,
bin/kc.[sh|bat] start \ --spi-x509cert-lookup--ssl-client-cert=SSL_CLIENT_CERT \ --spi-x509cert-lookup--ssl-cert-chain-prefix=CERT_CHAIN \ --spi-x509cert-lookup--certificate-chain-length=10
详细的参数说明如下,
– 参数“ssl-client-cert”,保存客户端证书的标头名称,通常是 SSL_CLIENT_CERT。
– 参数“ssl-cert-chain-prefix”,用于检索单个证书到链的长度的前缀。例如CERT_CHAIN作为前缀,支持从CERT_CHAIN_0到CERT_CHAIN_9加载证书。
– 参数“certificate-chain-length”,定义证书链的最大长度,设置为10表示最多处理10个证书。
– 参数“trust-proxy-verification”,启用信任NGINX代理的证书验证,而不是将证书直接转发到Keycloak。
2 最佳实践
2.1 部署环境
2.1.1 部署Keycloak的生产环境
2.1.2 部署Nginx反向代理
2.2 Keycloak服务配置
2.2.1 修改Keycloak配置
vim /etc/keycloak/keycloak.conf
配置修改如下,
# Basic settings for running in production. Change accordingly before deploying the server. # Database db = mariadb db-username = keycloak db-password = keycloakpwd db-url = jdbc:mariadb://localhost:3306/keycloak?characterEncoding=UTF-8 # Observability health-enabled = true metrics-enabled = true # HTTP https-certificate-file = /etc/keycloak/wildcard.cmdschool.org.crt https-certificate-key-file = /etc/keycloak/wildcard.cmdschool.org.key # The proxy address forwarding mode if the server is behind a reverse proxy. #proxy = reencrypt # Uncomment to enable proxy forwarding mode # Do not attach route to cookies and rely on the session affinity capabilities from reverse proxy #spi-sticky-session-encoder-infinispan-should-attach-route = false # Uncomment to disable route attachment to cookies # Hostname for the Keycloak server. hostname = websso.cmdschool.org #hostname-strict-backchannel = true #hostname-admin = rhbk01.cmdschool.org # Logging configuration log = console,file log-level = INFO,org.hibernate:debug,org.hibernate.hql.internal.ast:info log-file = /var/log/keycloak/keycloak.log log-file-size = 10MB log-file-count = 20 # proxy configuration proxy = reencrypt
2.2.2 重启服务使配置生效
systemctl restart keycloak.service systemctl status keycloak.service
2.3 配置Keycloak代理
2.3.1 创建代理配置
mkdir -p /etc/nginx/sso.conf.d/ vim /etc/nginx/sso.conf.d/websso.cmdschool.org_443_keycloak.conf
加入如下配置,
server { listen 443 ssl; server_name websso.cmdschool.org; include /etc/nginx/public/ssl_default.conf; #... location ~ ^/(js|realms|resources|robots.txt)/ { proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port $server_port; proxy_pass https://rhbk01.cmdschool.org:8443; } location / { proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port $server_port; proxy_pass https://rhbk01.cmdschool.org:8443; allow 10.0.0.0/8; allow 172.16.0.0/12; allow 192.168.0.0/16; deny all; } } server { listen 80; server_name websso.cmdschool.org; return 301 https://websso.cmdschool.org$request_uri; }
2.3.2 引入配置
vim /etc/nginx/nginx.conf
加入如下配置,
#... http { #... include /etc/nginx/sso.conf.d/*.conf; } #...
2.3.3 检查配置并重启使配置生效
nginx -t systemctl reload nginx systemctl status nginx
2.3.3 测试代理配置
https://websso.cmdschool.org
注:请注意使用Internet和Internal分别测试,以便验证是否只能interanl可以访问管理页面。
参阅文档
====================
https://docs.redhat.com/zh-cn/documentation/red_hat_build_of_keycloak/22.0/html-single/server_guide/index#reverseproxy-