如何部署RHBK的Nginx反向代理?

Keycloak

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的生产环境

如何部署Red Hat build of Keycloak生产模式?

2.1.2 部署Nginx反向代理

如何部署反向代理服务器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-

Keycloak
如何部署RHBK 26.2.5的Nginx反代?

1 基础知识 1.1 代理模式 1.1.1 Edge模式 – 该模式代理与红帽构建的Ke …

Keycloak
如何部署RHBK 26.2.5生产模式?

1 配置红帽构建的Keycloak 1.1 KeyCloak的配置 1.1.1 配置加载顺序 &#8 …

Keycloak
如何部署RHBK 26.2.5开发模式?

1 基础知识 1.1 软件介绍 – Keycloak支持以最小代价为应用程序或安全服务提 …