Openresty之动态更新https证书

文章介绍了如何在不中断服务的情况下,通过Lua脚本来动态更新OpenResty(Nginx)的HTTPS证书和密钥。主要步骤包括编写lua脚本,清除原有证书,读取新的PEM或DER格式的证书数据,然后通过`ssl.set_cert`和`ssl.set_priv_key`设置新证书和私钥。最后修改nginx.conf配置文件引入lua脚本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       如果是第一次看这个文章,可以先看下这篇openresty介绍性的文章:Openresty宏观介绍

         没用过openresty的人可能不知道这个是干啥的,但是用过的人大概就明白这个到底是个啥。在此简单说一下,openresty功能和Nginx功能一样,在用户如果需要做https访问的时候,需要在Nginx的配置文件nginx.conf文件里面配置证书和对应的KEY秘钥,这样Nginx才能提供https的访问请求。那么此时可能有这么一个需求,证书过期或者其他什么原因需要在不停止服务的情况下更改证书和秘钥,实现动态更改证书和秘钥的功能。实现如下功能需要下面几步

  • 编写lua脚本文件,在脚本文件里面去修改证书和密钥
  • 拷贝lua文件到openresty的安装路径
  • 修改nginx.conf文件,引入lua脚本,实现动态更新证书

一般证书/私钥的格式分两种,一种是文本格式的 PEM,另一种是二进制格式的 DER

1、编写lua脚本

命名脚本文件为ssl.lua,如果证书是PEM格式的话,通过如下方法更新证书和私钥:

local ssl = require "ngx.ssl"

-- 清除之前设置的证书和私钥
local ok, err = ssl.clear_certs()
if not ok then
    ngx.log(ngx.ERR, "failed to clear existing (fallback) certificates")
    return ngx.exit(ngx.ERROR)
end

-- 获取证书内容,比如 io.open("my.crt"):read("*a")
local cert_data, err = get_my_pem_cert_data()
if not cert_data then
    ngx.log(ngx.ERR, "failed to get PEM cert: ", err)
    return
end

-- 解析出 cdata 类型的证书值,你可以用 lua-resty-lrucache 缓存解析结果
local cert, err = ssl.parse_pem_cert(cert_data)
if not cert then
    ngx.log(ngx.ERR, "failed to parse PEM cert: ", err)
    return
end

local ok, err = ssl.set_cert(cert)
if not ok then
    ngx.log(ngx.ERR, "failed to set cert: ", err)
    return
end

local pkey_data, err = get_my_pem_priv_key_data()
if not pkey_data then
    ngx.log(ngx.ERR, "failed to get DER private key: ", err)
    return
end

local pkey, err = ssl.parse_pem_priv_key(pkey_data)
if not pkey then
    ngx.log(ngx.ERR, "failed to parse pem key: ", err)
    return
end

local ok, err = ssl.set_priv_key(pkey)
if not ok then
    ngx.log(ngx.ERR, "failed to set private key: ", err)
    return
end

备注:里面的get_my_pem_cert_data函数是获取证书函数,此处没有原函数,用户根据自己情况获取,有些是文件直接读取,有些是网络请求获取,有些是字符串直接使用。

如果证书格式是DER的话,使用如下代码进行动态更新

local ssl = require "ngx.ssl"

-- 清除之前设置的证书和私钥
local ok, err = ssl.clear_certs()
if not ok then
    ngx.log(ngx.ERR, "failed to clear existing (fallback) certificates")
    return ngx.exit(ngx.ERROR)
end

-- 获取证书内容,比如 io.open("my.crt.der"):read("*a")
local cert_data, err = get_my_der_cert_data()
-- 你也可以把 pem 格式的证书直接转换成 der 格式的,像这样:
-- local cert_pem_data = get_my_pem_cert_data()
-- local cert_data, err = ssl.cert_pem_to_der(cert_pem_data)
if not cert_data then
    ngx.log(ngx.ERR, "failed to get DER cert: ", err)
    return
end

-- 这里的 cert_data 是 string 类型的,所以可以直接缓存到 lua_shared_dict 当中
local ok, err = ssl.set_der_cert(cert_data)
if not ok then
    ngx.log(ngx.ERR, "failed to set DER cert: ", err)
    return
end

local pkey_data, err = get_my_der_priv_key_data()
-- 你也可以把 pem 格式的私钥直接转换成 der 格式的,像这样:
-- local pkey_pem_data = get_my_pem_priv_key_data()
-- local pkey_data, err = ssl.priv_key_pem_to_der(pkey_pem_data)
if not pkey_data then
    ngx.log(ngx.ERR, "failed to get DER private key: ", err)
    return
end

local ok, err = ssl.set_der_priv_key(pkey_data)
if not ok then
    ngx.log(ngx.ERR, "failed to set DER private key: ", err)
    return
end

2、拷贝lua文件到openresty安装目录

拷贝编辑的ssl.lua文件到目录/usr/local/openresty/nginx/lua/下面,如果没有,新建一个这个路径

3、修改nginx.conf文件

修改路径/usr/local/openresty/nginx/nginx.conf文件的内容如下:

#user  nobody;
worker_processes  1;

error_log  logs/error.log  error;
error_log  logs/error.log  notice;
error_log  logs/error.log  info;
pid        logs/nginx.pid;

events {
    worker_connections  1024;
}

env SERVER_ADDR;
env SERVER_ADDR_TOKEN;


http {
    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                     '$status $body_bytes_sent "$http_referer" '
                     '"$http_user_agent" "$http_x_forwarded_for"';
    # access_log  logs/access.log  main;
    # error_log   logs/error.log error; 

    lua_package_path "/usr/local/openresty/lualib/?.lua;/usr/local/openresty/nginx/lua/?.lua;";
    lua_package_cpath "/usr/local/openresty/lualib/?.so;;";


    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;
    proxy_connect_timeout 3s;

    #gzip  on;

   
    # HTTPS server
    server {
       listen       443 ssl;
       server_name  localhost;

       ssl_certificate      server.crt;
       ssl_certificate_key  server.key;
       ssl_certificate_by_lua_file lua/ssl.lua;

       ssl_session_cache    shared:SSL:1m;
       ssl_session_timeout  5m;

       ssl_ciphers  HIGH:!aNULL:!MD5;
       ssl_prefer_server_ciphers  on;

       location / {
            #设置代理目的url变量
            proxy_pass https://127.0.0.1;
       }
 
    }

}

最重要的两句代码就是上面的

lua_package_path "/usr/local/openresty/lualib/?.lua;/usr/local/openresty/nginx/lua/?.lua;";

ssl_certificate_by_lua_file lua/ssl.lua;

第一句是添加lua代码的路径,第二句代码是指定ssl请求的lua文件,意思就是所有的ssl访问请求都会经过ssl.lua代码文件的代码操作,在里面去动态修改证书。

### 使用 OpenResty 配置保留 HTTPS 连接的方法 在使用 OpenResty 处理 HTTPS 请求时,通常需要配置 Nginx 的 `ssl` 模块以支持 SSL/TLS 加密通信。以下是详细的配置方法: #### 1. 安装必要的依赖项 在安装 OpenResty 前,需确保已安装所需的开发库,特别是与 SSL 和 TLS 支持相关的库。可以通过以下命令完成安装: ```bash yum install -y pcre-devel openssl-devel gcc --skip-broken ``` 此步骤确保系统具备编译和运行 OpenResty 所需的基础环境[^1]。 #### 2. 编辑 OpenResty 的配置文件 OpenResty 是基于 Nginx 开发的高性能 Web 平台,其核心仍然是 Nginx 的配置语法。为了保留 HTTPS 连接,需要在 `nginx.conf` 文件中启用并正确配置 SSL 参数。 以下是一个典型的 HTTPS 配置示例: ```nginx server { listen 443 ssl; # 监听 HTTPS 默认端口 server_name example.com; # SSL 证书路径 ssl_certificate /path/to/your/certificate.crt; ssl_certificate_key /path/to/your/private.key; # 提升安全性的一些推荐设置 ssl_protocols TLSv1.2 TLSv1.3; # 禁用旧版本协议 ssl_ciphers HIGH:!aNULL:!MD5; # 设置强加密算法 ssl_session_cache shared:SSL:10m; # 启用会话缓存 ssl_session_timeout 10m; location / { proxy_pass http://backend_server; # 将请求转发至后端服务 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; # 确保后端知道原始协议是 HTTPS } } ``` 在此配置中,`listen 443 ssl` 表明该服务器块监听 HTTPS 流量,并启用了 SSL 功能。通过指定 `ssl_certificate` 和 `ssl_certificate_key` 来提供有效的 SSL 证书及其私钥[^4]。 #### 3. 确保反向代理保持 HTTPS 协议 如果 OpenResty 作为反向代理工作,则需要告知后端应用当前请求来自 HTTPS。这可通过设置头字段 `X-Forwarded-Proto` 实现,如下所示: ```nginx proxy_set_header X-Forwarded-Proto $scheme; ``` 这样可以保证即使流量被转发到内部网络中的 HTTP 服务,后端仍能够识别原始请求是否为 HTTPS[^3]。 #### 4. 测试与重启服务 完成以上配置后,应验证配置文件的有效性并重新加载 OpenResty/Nginx 服务: ```bash ./nginx -t # 测试配置文件是否有错误 ./nginx -s reload # 如果无误则重载新配置 ``` #### 注意事项 - 若防火墙未关闭,请确认允许外部设备访问服务器上的 443 端口。 - 对于云平台部署场景,还需调整实例的安全组规则以便放通入站方向针对 TCP 443 的流量[^2]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值