兄弟们,白嫖党们。现在证书为了治你们这些人,都已经只有 30 天的免费期了。我们在这介绍怎么样使用 openresty 来自动生成证书的功能。
这次的主人工是 simplessl 这个 Go 的工具,可以为 OpenResty/nginx、Envoy 和 Golang TLS 程序提供即时免费的自动 SSL 注册与续期功能,支持 Let's Encrypt。该工具能在收到请求时自动签发 SSL 证书,并在后台异步续期。
所以我们的 OpenResty 是结合这个一起来工作,所以可以一个 simplessl 来管理所有的证书,其它的 OpenResty 的主机都连接它来拿证书。
我们先介绍一下
功能特性
-
最小依赖:易于部署,适合分布式环境
-
高性能:用户请求延迟极低
-
多种证书支持:HTTP-01、TLS-ALPN-01 挑战,通配符证书(DNS-01 挑战)
-
混合证书管理:支持自动签发与手动管理证书共存
-
OCSP 装订:带缓存和异步续期
-
自签名证书:支持生成和提供自签名证书
-
无感更新:证书更新无需重载服务
-
多级缓存:LRU 缓存 + 共享内存缓存 + 服务端缓存 + 持久存储
-
中心化证书服务:统一管理所有证书
概念
这有一些基本的介绍,就是当证书签发的机构,在验证你对域名的控制权时,ACME 协议(如 Let's Encrypt)申请证书有如下三种验证方式。
-
HTTP-01 挑战: CA 要求你在域名对应的服务器上放置一个特定文件(通过 HTTP 访问),以证明你拥有该域名。
-
TLS-ALPN-01 挑战: 在 TLS 握手过程中,通过 ALPN(应用层协议协商)扩展完成验证,无需 HTTP 请求。CA 通过连接到域名的 443 端口,验证 TLS 握手时的 ALPN 扩展。
-
DNS-01 挑战:要求你在域名的 DNS 记录中添加一条特定的 TXT 记录,以证明你拥有该域名。
安装 OpenResty 的前端 simplessl 步骤
这个服务,需要同时安装二个应用,前端使用 OpenResty 来加载 simplessl 的模块做为前端,在需要证书的时候,从后端 go 写的 simplessl 的后端服务来取证书。
你的商业服务,就跑在这个 OpenResty 上。只是由这个 simplessl 模块来管理你的证书,并去后端服务上取合适的证书。
安装服务
-
OPM 安装 simplessl 到 openresty 当中
这个用于来从 simplessl 中来读证书的 openresty 的模块。
opm get jxskiss/simplessl
nginx 配置
events {
worker_connections 1024;
}
http {
lua_package_path "/usr/local/openresty/site/?.lua;/etc/openresty/lua/?.lua;;"; # 路径加进去
lua_shared_dict ssl_certs_cache 1m;
init_by_lua_block {
function allow_domain(domain)
-- 允许 example.com 后缀的域名
return domain:find("example.com$")
end
simplessl = (require "resty.simplessl").new({
backend = '127.0.0.1:8999', # simplessl 服务地址
allow_domain = allow_domain,
lru_maxitems = 100,
})
}
# HTTPS 服务
server {
listen 80;
listen 443 ssl;
server_name *.example.com;
# 后备自签名证书(需预先生成)
ssl_certificate /etc/nginx/certs/fallback.crt;
ssl_certificate_key /etc/nginx/certs/fallback.key;
ssl_certificate_by_lua_block {
simplessl:ssl_certificate()
}
# 文件验证的地址
location /.well-known/acme-challenge/ {
content_by_lua_block { simplessl:challenge_server() }
}
# 内容
location / {
}
}
}
安装 go 的 simplessl 后端
这个是主要的服务,分离做不同的事情,签发机构来取证书,更新证书,管理所有证书服务是由这个服务来做的,还有修改 dns 和通过认证之类。
依赖要求
- OpenResty >= 1.9.7.2
- lua-resty-http >= 0.16.1
-
下载二进制文件 从 Release 页面 下载预编译版本或自行构建:
-
golang 程序安装
go env -w GOPROXY=https://goproxy.cn,direct
go get github.com/jxskiss/simplessl/lib/tlsconfig@latest
go install github.com/jxskiss/simplessl@latest
- 配置服务 复制示例配置文件并修改:
cp example.conf.yaml /path/to/your-conf.yaml
vi /path/to/your-conf.yaml # 根据需求调整配置
- 启动服务
/path/to/simplessl run -c /path/to/your-conf.yaml
simplessl 配置简介
go 程序的 simplessl 需要创建一个配置文件, 如叫 list.yaml 这种。 我使用了阿里云,这时因为泛域名需要修改 dns ,所以我使用了 DNS-01 挑战
version: "2"
listen: "127.0.0.1:8999"
pid_file: "simplessl.pid"
storage:
type: "dir_cache"
dir_cache: "./certs" # 证书存储目录
acme:
directory_url: "https://acme-v02.api.letsencrypt.org/directory"
force_rsa: false
renew_before: 10 # days
default_account:
email: "你的邮箱"
accounts:
- email: "你的邮箱"
dns_credentials:
- name: alidns
provider: alidns
env:
ALICLOUD_ACCESS_KEY: ""
ALICLOUD_SECRET_KEY: ""
on_demand: # 首次访问匹配的域名时动态申请, 通常为 HTTP-01(需域名解析到服务器)
domain_regex:
- "(\w+)\.domain\.com"你要的泛域名
named: # 服务启动时自动申请或续期, 通配符必须用 DNS-01(需配置 DNS 凭证)
certificates:
- name: "_wildcard.domain.com 你要的泛域名"
account: "iakuf@163.com"
dns_credential: alidns
force_rsa: false
domains:
- "*.listlive.space"
完整 simplessl 配置文件说明
version: "2" # 配置文件格式版本,0.6.0 版本新增
listen: "127.0.0.1:8999" # simplessl 服务监听地址,请勿对外暴露
pid_file: "simplessl.pid" # PID 文件路径,用于优雅重启
# Envoy SDS 配置
enable_sds: true # 是否启用 Envoy SDS(Secret Discovery Service),默认 false
sds_listen: "127.0.0.1:8998" # SDS 服务监听地址,需 enable_sds 为 true
sds_ca_cert: "./secret-dir/ca.cert" # SDS gRPC 客户端验证的根证书路径
sds_server_cert: "./secret-dir/sds-server.cert" # SDS gRPC 服务器证书路径
sds_server_key: "./secret-dir/sds-server.key" # SDS gRPC 服务器私钥路径
# 存储配置
storage:
type: "dir_cache" # 存储类型,支持 "dir_cache" 或 "redis"
dir_cache: "./secret-dir" # 如果类型为 "dir_cache",指定证书缓存目录
redis: # 如果类型为 "redis",配置 Redis 连接
addr: "redis://<user>:<password>@<host>:<port>/<db_number>" # Redis 连接字符串
prefix: "" # 证书键名前缀,可选
# 自签名证书配置
self_signed:
enable: false # 是否启用自签名证书,默认 false
check_domain_name: false # 是否检查域名,默认 false
domains: # 允许使用自签名证书的域名列表
- "a.example.com"
- "a.example-1.com"
domain_regex: # 允许使用自签名证书的正则表达式域名
- "[a-z]+\.example\.com"
- "a\.example-1\.com"
valid_days: 3650 # 自签名证书有效期(天)
organization: "SSL Cert Server Self-Signed" # 自签名证书的组织名称
# 托管证书配置
managed:
reload_interval: "10m" # 从存储中重新加载托管证书的时间间隔
certificates: # 托管证书配置列表
- name: "abc.example.com" # 证书名称
domains: # 证书域名列表
- "abc.example.com"
domain_regex: # 证书域名正则表达式
- "(abc|def)\.example\.com"
- "img-\d+\.example\.com"
no_ocsp_stapling: false # 是否禁用 OCSP 装订,默认 false
- name: "_wildcard.example.com" # 通配符证书示例
domains:
- "example.com"
- "*.example.com"
domain_regex:
- "(abc|def)\.example\.com"
- "biz-\w+\.example\.com"
no_ocsp_stapling: false
# ACME 配置
acme:
directory_url: "https://acme-v02.api.letsencrypt.org/directory" # ACME 目录 URL
force_rsa: false # 是否强制使用 2048 位 RSA 密钥,默认 false
renew_before: 30 # 证书到期前多少天续期,默认 30 天
default_account: # 默认 ACME 账户
email: "acme@example.com" # 默认账户邮箱
accounts: # 其他 ACME 账户
- email: "another@somedomain.com"
dns_credentials: # DNS 凭证配置,用于 DNS-01 挑战
- name: example_alidns # 凭证名称
provider: alidns # DNS 提供商类型
env: # 所需环境变量
ALICLOUD_ACCESS_KEY: "my_access_key_xxxx"
ALICLOUD_SECRET_KEY: "my_secret_key_xxxx"
- name: another_godaddy_1
provider: godaddy
env:
GODADDY_API_KEY: "my_api_key_xxxx"
GODADDY_API_SECRET: "my_api_secret_xxxx"
- name: another_cloudflare_1
provider: cloudflare
env:
CLOUDFLARE_EMAIL: "my_email_xxxx"
CLOUDFLARE_API_KEY: "my_api_key_xxxx"
on_demand: # 按需证书配置
domains: # 允许按需签发证书的域名列表
- a.example-2.com
- b.example-2.com
domain_regex: # 允许按需签发证书的正则表达式域名
- "api-1-(\w+)\.example\.com"
- "api-2-(\w+)\.example\.com"
named: # 命名证书配置
certificates:
- name: "z_san_example_com" # 证书名称
account: "acme@example.com" # 使用的 ACME 账户
dns_credential: example_alidns # 使用的 DNS 凭证
force_rsa: false # 是否强制使用 RSA 密钥
domains: # 证书域名列表
- "z1.example.com"
- "z2.example.com"
- "z3.example.com"
- name: "_wildcard.y.somedomain.com" # 通配符证书示例
account: "another@somedomain.com"
dns_credential: another_cloudflare_1
force_rsa: false
domains:
- "y.somedomain.com"
- "*.y.somedomain.com"
- 当前版本主要设计用于内网环境
- 务必做好证书服务器的安全防护
- 关注后续安全更新