NJet中自动申请SSL证书

🙈 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证书申请,可以通过静态或动态两种方式使能。使能后证书申请流程如下:

证书申请流程(自动化创建证书)

img

通过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扩展中配置。如下图:

img

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

img 如果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

首次启动与证书签发​

img

域名变更与证书更新​​

如需为新的域名签发证书,可以修改njet.conf 的server_name为域名vs9.com,通过njet relaod方式,自动为vs9.com 发起新的 ACME 证书申请。

配置修改:

修改njet.conf vs8.com修改为vs9.com,然后reload njet

mqtt日志:

img

cert-manager日志:

img

Njet配置:

img

证书文件查看:

img

img

备注

  • 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及以上 龙芯架构