ssl-cert-server
使用 Let's Encrypt 自动颁发和更新 SSL 证书
$ opm get jxskiss/ssl-cert-server
ssl-cert-server
在 OpenResty/nginx 和任何 Golang TLS 程序中,使用 Let's Encrypt 实现即时免费 SSL 注册和更新。
ssl-cert-server 在收到请求时会自动并透明地从 Let's Encrypt 颁发 SSL 证书,当证书需要更新时,它会自动在后台异步更新证书。
OpenResty 插件使用 OpenResty 1.9.7.2+ 中的 ssl_certificate_by_lua
功能。
使用 ssl-cert-server 向 Let's Encrypt 注册 SSL 证书,即表示您同意 Let's Encrypt 订阅协议。
免责声明:我从很棒的项目 lua-resty-auto-ssl 和 Go 的 autocert 包中获得了一些最初的灵感和代码。此外,该程序使用 Lego 来解决 dns-01 挑战。非常感谢 😀
特性
依赖关系极少,部署方便,对分布式环境友好。
高性能,对用户请求的延迟非常低。
使用 http-01 挑战为每个域颁发和更新证书,支持 OpenResty 和 Golang。
使用 tls-alpn-01 挑战为每个域颁发和更新证书,支持 Golang。
使用 dns-01/http-01 挑战颁发和更新 SAN 证书,支持 OpenResty 和 Golang。
使用 tls-alpn-01 挑战颁发和更新 SAN 证书,支持 Golang。
使用 dns-01 挑战颁发和更新 通配符证书,支持 OpenResty 和 Golang。
服务手动管理的证书。
服务 OCSP 装订,带有缓存和异步更新,延迟可以忽略不计。
生成和服务自签名证书。
像 Nginx 一样优雅地重启,不会丢失任何请求。
支持目录和 Redis 作为缓存存储,添加新的存储支持很容易。
注意:目前该程序设计用于内部网络,安全特性尚未认真考虑,请务必妥善保护您的证书服务器并注意安全问题。
集中式证书服务器
与其他类似项目相比,该项目提供了一个集中式的证书服务器,用于在一个地方管理所有证书(包括自动颁发或手动管理的证书,以及自签名证书)。OpenResty 插件和 Golang TLS 配置库充当服务器的客户端。
这种设计有几个优点
将 ACME 相关工作和与存储的通信卸载到后端 Golang 服务器,让 Nginx/OpenResty 做它被设计为最擅长的事情;
它对分布式部署更友好,可以在一个地方管理所有证书,OpenResty 插件和 Golang 库的部署简单直接;您获得的是一个域的单一证书,而不是与您的 Web 服务器实例一样多的证书(如其他一些类似项目所做的那样);
与使用 Lua 进行 ACME 工作和存储相比,Golang 程序更容易维护和进行故障排除;
此外,Golang 程序更容易扩展以支持新的存储类型或新特性(例如通配符证书、安全性等);
使用多级缓存机制,帮助前端 Nginx 和 Golang Web 服务器在性能损耗可以忽略不计的情况下,无需任何重新加载,自动更新到更新的证书
OpenResty 每个工作进程的 LRU 缓存,带有 cdata 指针(Golang 客户端使用内存中的写时复制缓存),回退到
OpenResty 共享内存缓存(Golang 客户端不需要),回退到
后端 ssl-cert-server 内部的内存缓存,最后到
存储或 ACME 服务器。
缓存的证书和 OCSP 装订在后端 ssl-cert-server 中自动更新和刷新。
状态
被认为是 BETA 版。
尽管该程序已经运行了近 5 年,为我的个人网站提供支持,但它是一个业余项目,并且在大型生产系统中没有已知的部署。
强烈建议任何对该程序感兴趣的人在您的环境中进行测试。
安装
对于 OpenResty
Lua 库已在 OPM 上发布,以下命令将安装 ssl-cert-server 库,以及它的依赖项“lua-resty-http”。
opm get jxskiss/ssl-cert-server
如果您没有 opm,您可以手动安装 Lua 库,以 OpenResty 安装在“/usr/local/openresty”下为例(您可能需要使用 sudo 来授予适当的权限)
mkdir -p /usr/local/openresty/site/lualib/resty
cd /usr/local/openresty/site/lualib/resty
wget https://raw.githubusercontent.com/ledgetech/lua-resty-http/v0.16.1/lib/resty/http.lua
wget https://raw.githubusercontent.com/ledgetech/lua-resty-http/v0.16.1/lib/resty/http_connect.lua
wget https://raw.githubusercontent.com/ledgetech/lua-resty-http/v0.16.1/lib/resty/http_headers.lua
wget https://raw.githubusercontent.com/jxskiss/ssl-cert-server/master/lib/resty/ssl-cert-server.lua
对于 Golang TLS 程序
go get github.com/jxskiss/ssl-cert-server/lib/tlsconfig@latest
有关使用 lib/tlsconfig
的示例,请参阅以下文档。
运行 ssl-cert-server
下载证书服务器服务二进制文件,可以自己构建
go install github.com/jxskiss/ssl-cert-server@latest
或从 发布页面 下载预构建的二进制文件。
将 example.conf.yaml
复制到您喜欢的位置,并编辑它以满足您的需求。配置选项在示例文件中解释。
运行您的证书服务器
/path/to/ssl-cert-server run -c /path/to/your/conf.yaml
或要生成自签名证书,请参阅 ssl-cert-server generate-self-signed -h
。
现在您可以配置 OpenResty 或 Golang 程序来使用证书服务器获取 SSL 证书,请参阅以下示例。
Nginx 配置示例
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
lua_shared_dict ssl_certs_cache 1m;
init_by_lua_block {
-- Define a function to determine which SNI domains to automatically
-- handle and register new certificates for. Defaults to not allowing
-- any domain, so this must be configured.
function allow_domain(domain)
if domain:find("example.com$") then
return true
end
return false
end
-- Initialize backend certificate server instance.
-- Change lru_maxitems according to your deployment, default 100.
cert_server = (require "resty.ssl-cert-server").new({
backend = '127.0.0.1:8999',
allow_domain = allow_domain,
lru_maxitems = 100,
})
}
# HTTPS Server
server {
listen 443 ssl;
# Works also with non-default HTTPS port.
listen 8443 ssl;
server_name hello.example.com;
# Dynamic handler for issuing or returning certs for SNI domains.
ssl_certificate_by_lua_block {
cert_server:ssl_certificate()
}
# Fallback certificate required by nginx, self-signed is ok.
# ssl-cert-server generate-self-signed \
# -days 3650 \
# -cert-out /etc/nginx/certs/fallback-self-signed.crt \
# -key-out /etc/nginx/certs/fallback-self-signed.key
ssl_certificate /etc/nginx/certs/fallback-self-signed.crt;
ssl_certificate_key /etc/nginx/certs/fallback-self-signed.key;
location / {
content_by_lua_block {
ngx.say("It works!")
}
}
}
# HTTP Server
server {
listen 80;
server_name hello.example.com;
# Endpoint used for performing domain verification with Let's Encrypt.
location /.well-known/acme-challenge/ {
content_by_lua_block {
cert_server:challenge_server()
}
}
}
}
Golang lib/tlsconfig
您可以使用包 lib/tlsconfig
来运行带有 TLS 的 Golang 程序。例如
func main() {
handler := func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("It works!"))
}
// See doc of tlsconfig.Options for available options.
tlsConfig := tlsconfig.NewConfig("127.0.0.1:8999", tlsconfig.Options{})
listener, err := tls.Listen("tcp", ":8443", tlsConfig)
if err != nil {
log.Fatal(err)
}
http.Serve(listener, http.HandlerFunc(handler))
}
依赖关系
OpenResty >= 1.9.7.2
lua-resty-http >= 0.16.1
变更历史
v0.6.0 @ 2022-09-03
从头开始的主要重构。
新增:支持除 Let's Encrypt 之外的其他 ACME 服务器
新增:支持颁发和更新 SAN 证书
新增:使用新的配置格式(v2)
新增:支持根据配置的名称查询证书
变更:重构 HTTP api 以使用 [drpc][drpc],以提高可维护性和一致性
变更:更改为使用 [acmez][acmez](而不是
acme/autocert
和lego
)与 ACME 服务器通信
[drpc]: https://github.com/storj/drpc [acmez]: https://github.com/mholt/acmez
v0.5.0 @ 2022-06-12
修复:查询证书之前查询 OCSP 装订时的错误行为
新增:支持通配符证书,使用 Lego 解决 dns-01 挑战
变更:使
lib/tlsconfig
成为独立模块变更:将依赖项升级到最新版本
变更:重构代码以使用更复杂的 cli 和日志记录库
变更:重构代码以提高可维护性
v0.4.3 @ 2022-05-17
修复:由于选择了错误的证书作为颁发者证书而导致的 OCSP 装订失败,感谢 @cedricdubois (#6)
新增:Redis 存储的可选“前缀”选项
v0.4.2 @ 2021-06-02
修复:当只配置了默认证书时,请求失败,#2
修复:当 OCSP 服务器返回错误时,抑制日志消息,#3
变更:将依赖项升级到最新版本
v0.4.1 @ 2020-08-23
新增:支持 Golang 库的 tls-alpn-01 挑战
新增:使用 cdata 指针而不是 der 作为 LRU 缓存
变更:从 LRU 缓存中删除 OCSP 装订,因为它是多余的,并且没有被正确刷新
v0.4.0 @ 2020-08-16
更新:此版本存在已知错误,请升级到更新的版本。
新增:支持管理证书
新增:支持自签名证书
新增:Golang 库,用于与需要 TLS 支持的任意 Golang 程序一起使用
新增:生成自签名证书的子命令
新增:(lua)多层缓存,为了获得最佳性能(每个工作进程的 LRU 缓存 + 共享内存缓存)
新增:像 Nginx 一样优雅地重启,不会丢失任何请求
变更:使用 YAML 配置文件替换命令行标志,因为我们支持更多特性,命令行标志不足以进行配置
变更:(内部)将代码重构为更小的文件,以提高可维护性
变更:(内部)优化 Lua 共享内存缓存,以提高性能
修复:在证书和 OCSP 装订缓存中添加指纹,以确保我们为相应的证书获取正确的 OCSP 装订,如果没有,在证书更新后的一小段时间内可能会使用错误的 OCSP 装订缓存
此版本是一个重大更改,包含许多新特性和改进。
v0.3.0 @ 2020-03-13
新增:可选的 Redis 作为缓存存储
变更:更新 autocert 以支持 ACMEv2
变更:使用 go 模块来管理 golang 依赖项
v0.2.1 @ 2018-10-10
变更:整理日志消息
变更:小幅改进
v0.2.0 @ 2018-08-11
修复:OCSP 装订更新程序在长时间运行后出现死循环
变更:删除不必要的 golang 依赖项(
gocraft/web
、jxskiss/glog
),导致二进制文件大小更小,安装更容易变更:由于 glog 依赖项已删除,glog 提供的标志不再可用
变更:使用官方的
acme/autocert
包而不是分叉,使代码更清晰,并允许更容易地跟踪上游更改新增:使用 glide 来管理 golang 依赖项
v0.1.2 @ 2018-06-20
修复:来自 OCSP 装订服务器的 408 请求超时
v0.1.1 @ 2018-01-06
初始公开发布。
作者
Shawn Wang (jxskiss)
许可证
mit
依赖关系
ledgetech/lua-resty-http >= 0.16.1, openresty >= 1.9.7.2
版本
-
jxskiss/ssl-cert-server 0.6.0使用 Let's Encrypt 自动颁发和更新 SSL 证书 2022-09-03 07:30:58
-
jxskiss/ssl-cert-server 0.4.3使用 Let's Encrypt 自动颁发和更新 SSL 证书 2022-05-17 16:03:08
-
jxskiss/ssl-cert-server 0.4.2使用 Let's Encrypt 自动颁发和更新 SSL 证书 2021-06-02 16:25:46
-
jxskiss/ssl-cert-server 0.4.1使用 Let's Encrypt 自动颁发和更新 SSL 证书 2020-08-21 16:27:17
-
jxskiss/ssl-cert-server 0.4.0使用 Let's Encrypt 自动颁发和更新 SSL 证书 2020-08-16 08:21:50
-
jxskiss/ssl-cert-server 0.2.0使用 Let's Encrypt 自动颁发和更新 SSL 证书 2018-08-11 05:46:03
-
jxskiss/ssl-cert-server 0.1.1使用 Let's Encrypt 自动颁发和更新 SSL 证书 2018-01-07 08:16:21