NGINX不同子路径独立TLS证书配置及代理SSL证书通配问题咨询
我之前在处理多租户NGINX代理场景时碰到过完全一样的问题——NGINX原生的proxy_ssl_certificate、proxy_ssl_certificate_key和proxy_ssl_trusted_certificate确实不支持通配符或者动态变量直接配置,因为这些指令是在配置加载阶段生效的,没法根据每个请求的令牌动态调整。不过结合你已经在使用的access_by_lua_file,我们可以用OpenResty的Lua API完美解决这个问题,具体步骤如下:
解决方案思路
核心是利用OpenResty的请求阶段Lua API,在解析令牌后动态设置SSL客户端证书和信任CA,绕过原生NGINX配置阶段的限制。
1. 在令牌解析Lua脚本中提取证书信息
首先,在你的access_by_lua_file脚本里,解析令牌后把证书/密钥/CA的路径(或者直接证书内容,如果令牌里是二进制内容的话)存储到ngx.ctx(请求上下文)和ngx.var(NGINX变量)中:
-- 示例:从令牌解析出证书相关路径 local token_payload = your_token_parsing_function(ngx.var.http_authorization) -- 把证书/密钥路径存入请求上下文,供后续SSL设置使用 ngx.ctx.dynamic_cert_path = token_payload.cert_path ngx.ctx.dynamic_key_path = token_payload.key_path -- 把CA路径存入NGINX变量,因为proxy_ssl_trusted_certificate支持变量 ngx.var.dynamic_ca_path = token_payload.ca_path
2. 配置NGINX location,动态加载SSL证书
在对应的location块中,使用OpenResty的lua_ssl_certificate_by_lua_block指令,在请求阶段动态加载客户端证书和密钥,同时用变量设置信任CA:
http { # 预定义一个变量存储动态CA路径(避免未赋值时出错) map "" $dynamic_ca_path { default "/etc/nginx/default-ca.pem"; } server { listen 443 ssl; # 其他基础配置... location ~ ^/(analytics|topology) { # 先解析令牌,提取证书信息 access_by_lua_file /path/to/your/token_parser.lua; # 动态设置SSL客户端证书和密钥 lua_ssl_certificate_by_lua_block { local cert_path = ngx.ctx.dynamic_cert_path local key_path = ngx.ctx.dynamic_key_path -- 读取证书文件内容 local cert_data, err = io.open(cert_path, "r"):read("*a") if not cert_data then ngx.log(ngx.ERR, "Failed to read client cert: ", err) return ngx.exit(500) end local key_data, err = io.open(key_path, "r"):read("*a") if not key_data then ngx.log(ngx.ERR, "Failed to read client key: ", err) return ngx.exit(500) end -- 设置SSL证书和密钥 local ok, err = ngx.ssl.set_cert(cert_data) if not ok then ngx.log(ngx.ERR, "Failed to set client cert: ", err) return ngx.exit(500) end ok, err = ngx.ssl.set_priv_key(key_data) if not ok then ngx.log(ngx.ERR, "Failed to set client key: ", err) return ngx.exit(500) end } -- 动态设置信任的CA证书 proxy_ssl_trusted_certificate $dynamic_ca_path; proxy_ssl_verify on; proxy_ssl_verify_depth 3; -- 代理到目标后端(后端地址也可以从令牌解析后动态设置) proxy_pass https://$dynamic_backend; } } }
关键注意事项
- 权限问题:确保NGINX运行用户(通常是
www-data或nginx)有权限读取所有动态证书文件,否则会出现读取失败的错误。 - 证书内容直接使用:如果你的令牌里携带的是证书的二进制内容(不是文件路径),可以直接把内容传入
ngx.ssl.set_cert和ngx.ssl.set_priv_key,省去文件读取步骤,效率更高。 - 错误处理:一定要在Lua脚本中添加错误日志和异常处理,避免因证书加载失败导致请求静默失败。
内容的提问来源于stack exchange,提问作者doktoroblivion
相关产品推荐
相关产品推荐

