CentOS配置SSL证书nginx和keycloak

使用 Nginx 反向代理 Docker 版 Keycloak 并配置 SSL

前提条件:

  1. Keycloak 已在 Docker 中运行,端口映射为 8080:8080
  2. 域名 auth.yourdomain.com 已解析到服务器 IP
  3. 服务器已安装 Docker 和 Docker Compose

完整步骤:

1. 创建 Nginx 配置文件

1
sudo nano /etc/nginx/conf.d/keycloak.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# HTTP 重定向到 HTTPS
server {
listen 80;
server_name auth.yourdomain.com;
return 301 https://$host$request_uri;
}

# HTTPS 服务配置
server {
listen 443 ssl http2;
server_name auth.yourdomain.com;

# 证书路径(先使用自签名,后续替换)
ssl_certificate /etc/nginx/ssl/self.crt;
ssl_certificate_key /etc/nginx/ssl/self.key;

# SSL 优化配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

# 安全响应头
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;

# 反向代理配置
location / {
proxy_pass http://localhost:8080; # 指向Keycloak容器
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;

# WebSocket 支持
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}

# 静态资源缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {
proxy_pass http://localhost:8080;
proxy_cache static_assets;
proxy_cache_valid 200 30d;
add_header X-Cache-Status $upstream_cache_status;
}

# 禁止访问敏感路径
location ~ ^/(keycloak\.json|theme-resources|resources|auth/admin) {
deny all;
return 404;
}
}

2. 创建临时自签名证书(用于初始测试)

1
2
3
4
5
sudo mkdir -p /etc/nginx/ssl
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/nginx/ssl/self.key \
-out /etc/nginx/ssl/self.crt \
-subj "/CN=auth.yourdomain.com"

3. 测试并启动 Nginx

1
2
sudo nginx -t
sudo systemctl restart nginx

4. 配置 Keycloak 容器适应反向代理

修改 Keycloak 的 Docker 启动命令(或 docker-compose.yml):

1
2
3
4
5
6
7
8
9
10
docker run -d \
--name keycloak \
-e KEYCLOAK_ADMIN=admin \
-e KEYCLOAK_ADMIN_PASSWORD=ChangeMe123 \
-e KC_PROXY=edge \ # 关键设置:声明在边缘代理之后
-e KC_HOSTNAME=auth.yourdomain.com \ # 设置外部域名
-e KC_HTTP_ENABLED=false \ # 禁用直接 HTTP 访问
-p 8080:8080 \
quay.io/keycloak/keycloak:22.0.5 \
start --optimized

5. 获取 Let’s Encrypt SSL 证书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 安装 Certbot
sudo yum install epel-release
sudo yum install certbot python3-certbot-nginx

# 获取证书
sudo certbot --nginx \
-d auth.yourdomain.com \
--email admin@yourdomain.com \
--agree-tos \
--no-eff-email \
--redirect

# 设置自动续订
echo "0 3 * * * /usr/bin/certbot renew --quiet --post-hook 'systemctl reload nginx'" | sudo tee -a /etc/crontab > /dev/null

6. 更新 Nginx 配置使用新证书

Certbot 会自动修改 Nginx 配置,将:

1
2
ssl_certificate /etc/nginx/ssl/self.crt;
ssl_certificate_key /etc/nginx/ssl/self.key;

替换为:

1
2
ssl_certificate /etc/letsencrypt/live/auth.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/auth.yourdomain.com/privkey.pem;

7. 重启服务

1
2
sudo systemctl reload nginx
docker restart keycloak

8. 配置防火墙

1
2
3
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

验证配置:

  1. 访问测试

    1
    2
    3
    4
    5
    curl -I https://auth.yourdomain.com
    # 应返回 200 OK

    curl -k http://localhost:8080
    # 应返回 404(直接访问已被禁用)
  2. SSL 验证

    1
    2
    openssl s_client -connect auth.yourdomain.com:443 -servername auth.yourdomain.com | grep "Verify"
    # 应返回 Verify return code: 0 (ok)
  3. Keycloak 日志检查

    1
    2
    docker logs keycloak | grep KC_PROXY
    # 应显示代理配置:Proxy address forwarding is enabled

高级配置选项:

1. 自定义 Nginx 代理头

1
2
3
4
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;

2. 启用 HTTP/2 和 Brotli 压缩

1
2
3
4
5
6
listen 443 ssl http2;

# 在 http 块中添加
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

3. 安全加固配置

1
2
3
4
5
6
7
8
9
10
11
# 禁用服务器版本信息
server_tokens off;

# 防止点击劫持
add_header X-Frame-Options "SAMEORIGIN";

# 启用XSS保护
add_header X-XSS-Protection "1; mode=block";

# 禁用内容类型嗅探
add_header X-Content-Type-Options "nosniff";

故障排除:

问题1:Keycloak 重定向循环
解决:确保容器设置了正确的代理类型:

1
docker exec -it keycloak /opt/keycloak/bin/kc.sh build --proxy edge

问题2:Nginx 502 Bad Gateway
解决

  1. 检查 Keycloak 容器是否运行:docker ps
  2. 检查端口映射:docker port keycloak
  3. 测试本地访问:curl http://localhost:8080

问题3:混合内容警告
解决:在 Keycloak 管理控制台设置正确的 URL:

  1. 登录 Keycloak 管理控制台
  2. 进入 Realm Settings → General
  3. 设置 Frontend URL: https://auth.yourdomain.com

问题4:WebSocket 连接失败
解决:确保 Nginx 包含以下配置:

1
2
3
4
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;

最终架构:

1
2
3
4
用户 -> HTTPS(443) -> Nginx -> HTTP(8080) -> Keycloak 容器
↳ SSL 终止
↳ 请求头重写
↳ 安全加固

通过以上配置,您已实现:

  1. Docker 版 Keycloak 的安全 HTTPS 访问
  2. Nginx 反向代理 + SSL 终止
  3. Let’s Encrypt 自动证书管理
  4. 安全加固和性能优化
  5. WebSocket 支持