🙈 By 刘琪 2025-07-21
简介
由于ssl证书签发的有效期越来越短,运维人员花在证书管理的成本将成倍增加。结合NJet动态证书管理的能力,在初次配置后,NJet可以通过标准的ACME协议实现证书的自动签发、续签,并自动更新到服务器中,从而实现无需重启,就可以保持证书的有效性,保证业务的持续安全。
功能介绍
cert-manager实现的主要功能如下:
- 为server块中的server_name域名实现证书自动申请、续签。
- 支持http-01、tls-alpn-01两种挑战(challenge)验证方式。
- 应用自动签发的证书。通过实现njet https server 块ssl_certificate_key和ssl_certificate指令自动配置(调用njet ssl API实现,即动态证书)来应用证书。
- 管里面admin API,实现磁盘中证书文件的管理。
由于njet本身的限制,每个server块在启动时需要预先配置证书,所以用户需要自己提前生成证书。后续使能了acme特性后,证书由cert-manager管理。
证书申请与续签
证书申请
用户配置中使能acme特性后,会触发acme证书申请,可以通过静态或动态两种方式使能。使能后证书申请流程如下:
证书申请流程(自动化创建证书)
通过njet指令ssl_certificate_management acme;启用acme特性。例子如下:
// 为vs12.com颁发证书
http {
server {
listen 443 ssl;
server_name vs12.com;
ssl_certificate server.crt;
ssl_certificate_key server.key;
ssl_certificate_management acme;
location /{
return 200 "vs12.com ssl\n";
}
}
}
Njet server_name指令支持配置多个域名,这种场景下,cert-manager会为多个域名生成一个证书,证书的CN为第一个域名,所有域名都会在证书的SAN扩展中配置。如下图:
cert-manager检测到域名已经生成过证书,将不会在进行证书生成。
证书续签
cert-manager定期检查证书列表,计算哪些证书应该进行续签操作,默认情况下有效期不到30天的证书会进行续签操作,此参数可以在程序启动时重写默认值。
证书续签成功后,应用自动签发的证书,即实现njet https server 块ssl_certificate_key和ssl_certificate指令自动配置。
挑战
cert-manager内置实现了tls、http挑战验证server,acme ca验证域名所有权时cert-manager会启动server,验证后关闭server。
http-01
cert-manager http挑战验证server默认监听80端口。
如果njet worker占用了80端口,那么http 挑战验证需要由njet worker转发到cert-manager,njet.conf只需配置80端口对应的server_name即可,挑战location cert-manager负责创建。
在创建挑战location时,cert-manager需要知道location 关联的listen ip,这个参数在cert-manager启动时需要指定,toml配置文件参数为proxyHttpChallengeServerIp。例如我们为vs12.com域名颁发证书,且通过http-01挑战验证,njet.conf中需要配置对应server(原因是:cert-manager动态为vs12.com server创建挑战location),配置样例如下:
//njet.conf
// 需要手动配置server,挑战location不需要配置,cert-manager会自动创建。
server {
listen 80;
server_name vs12.com;
location / {
return 200 "vs12.com port 80 /";
}
}
}
// 为vs12.com颁发证书
http {
server {
listen 443 ssl;
server_name vs12.com;
ssl_certificate server.crt;
ssl_certificate_key server.key;
ssl_certificate_management acme;
location /{
return 200 "vs12.com ssl\n";
}
}
}
cert-manager创建的挑战的location
如果njet worker不占用80,挑战验证就完全由cert-manager完成,不需要用户在njet.conf中创建对应域名的srever块,弊端是用户不能通过80端口访问njet代理的http服务。
tls-alpn-01
cert-manager tls挑战验证server默认监听443端口。
如果njet worker占用443端口,443端口也不能由https监听,只能由stream监听,我们需要用到njet的ssl预读功能。那么tls挑战验证请求需要由njet worker stream转发到cert-manager,https server需要使用内部端口,请求也由stream转发。配置如下:
http {
server {
listen 50010 ssl;
server_name vs1.com;
ssl_certificate server.crt;
ssl_certificate_key server.key;
// 启用acme特性
ssl_certificate_management acme;
location /{
return 200 "vs1.com ssl\n";
}
}
}
// 10443为cert-manager程序内部验证tls_alpn_01挑战的端口
stream {
map $ssl_preread_alpn_protocols $acme_tls_alpn_01_challenge_port {
~\bacme-tls/1\b 10443;
// njet内部http ssl端口
default 50010;
}
server {
listen 443;
listen [::]:443;
proxy_pass 127.0.0.1:$acme_tls_alpn_01_challenge_port;
ssl_preread on;
}
}
如果njet worker不占用443,挑战验证就完全由cert-manager完成,不需要njet stream转发,弊端是用户不能通过443端口访问njet代理的https 服务。
总之,80、443端口由njet worker还是cert-manager监听,会影响并产生不同的配置,请灵活使用。
应用证书
在证书申请、续签成功后,cert-manager会调用njet ssl API应用证书到对应的server块中。
在证书申请场景,如果应用证书失败,会删除证书文件,此过程为原子操作。
管理面admin API
除了mqtt证书删除事件可以删除磁盘上的证书文件,有的场景无法触发删除事件。所以cert-manager内置了一个HTTP server(称为admin API,即管理面API),提供HTTP API的方式去管理证书,目前支持get、list、delete证书。API定义如下:
API类型 | URL | HTTP方法 | 说明 |
---|---|---|---|
获取指定证书 | http://127.0.0.0:2000/api/v1//cert/{domain} | GET | 2000为admin API默认监听的端口。{domain}为域名 |
删除指定证书 | http://127.0.0.0:2000/api/v1//cert/{domain} | DELETE | {domain}为域名 |
获取所有证书 | http://127.0.0.0:2000/api/v1//cert | GET |
证书文件存储路径为以njet -p为根目录,.lego/certificates/为证书文件所在目录。
使用案例
为静态配置的域名vs8.com自动颁发证书
使用ssl挑战验证方式,进行证书签发。启动njet 前,需要在静态配置文件njet.conf 中配置server_name(比如vs8.com)和配置一个证书(https必须配置一个证书才能启动,为了演示这里配置的是自签名证书),启动njet 后,会自动触发njet为域名vs8.com自动申请一个新的证书。
在静态配置文件 njet.conf 中配置域名 vs8.com 并启用 ACME 证书管理功能,首次启动与证书签发。
njet.conf配置:
http {
server {
listen 50010 ssl;
server_name vs8.com;
// 启动前需配置一个证书,自签名证书即可
ssl_certificate server.crt;
ssl_certificate_key server.key;
// 启用acme特性
ssl_certificate_management acme;
location /{
return 200 "vs8.com ssl\n";
}
}
}
// 10443为cert-manager程序内部验证tls_alpn_01挑战的端口
stream {
map $ssl_preread_alpn_protocols $acme_tls_alpn_01_challenge_port {
~\bacme-tls/1\b 10443;
// njet内部ssl端口
default 50010;
}
server {
listen 443;
listen [::]:443;
proxy_pass 127.0.0.1:$acme_tls_alpn_01_challenge_port;
ssl_preread on;
}
}
Tls 443挑战配置:
cert-manager配置文件:
[copilot]
progName="sbin/cert-manager"
copilotType="cert"
stdoutFile = "/usr/local/njet/logs/cert_stdout.log"
stderrFile = "/usr/local/njet/logs/cert_stderr.log"
[acme]
email="liuqi@lq.com"
challengeType="tls"
acmeCaDir="http://127.0.0.1:4001/directory"
tlsChallengeServerAddress=":10443"
[njet]
[mqtt]
mqttServerAddress="127.0.0.1:1883"
[log]
v=2
首次启动与证书签发
域名变更与证书更新
如需为新的域名签发证书,可以修改njet.conf 的server_name为域名vs9.com,通过njet relaod方式,自动为vs9.com 发起新的 ACME 证书申请。
配置修改:
修改njet.conf vs8.com修改为vs9.com,然后reload njet
mqtt日志:
cert-manager日志:
Njet配置:
证书文件查看:
备注
- NJet自动证书申请在3.3.1及以上支持,详细配置请参考NJet3.3.1使用手册
- 动态证书更新是NJet的动态特性之一,
- cert_manager是一个独立的go 实现的程序,由NJetCoPilot框架驱动,其2进制见下表:
功能特性 | 二进制名称 | 架构 | njet版本 | 说明 |
---|---|---|---|---|
证书管理 | cert-manager-arm64 | arm64 | 3.3.1及以上 | arm架构 |
cert-manager | x86-64 | 3.3.1及以上 | intel架构 | |
cert-manager-loongarch64 | LoongArch | 3.3.1及以上 | 龙芯架构 |