peter_sslers-lua-resty
用于 peter_sslers SSL 证书管理器的 openresty ssl 证书例程
$ opm get aptise/peter_sslers-lua-resty
lua-resty-peter_sslers
OpenResty 中用于 https://github.com/aptise/peter_sslers 证书管理器的 Lua 支持
状态
该软件包几乎已准备好投入生产。
安装
一行代码...
sudo opm install aptise/peter_sslers-lua-resty
概述
lua-resty-peter_sslers
是一个可以在 openresty/nginx 环境中使用的库,用于为给定域名动态提供正确的 SSL 证书。
它支持 peter_sslers
的两种主要缓存类型 1 和 2。
它作为带有调用它的示例脚本的库实现。
核心库
ssl_certhandler.lua
示例
ssl_certhandler-lookup.lua
ssl_certhandler-expire.lua
ssl_certhandler-status.lua
-lookup.lua
、-expire.lua
、-status.lua
脚本可以复制到一个块中。
该库被硬编码为使用 redis 中的 db9。如果你想要其他选项,请编辑或对看起来像这样的行进行 PR 修复
ngx.log(ngx.ERR, "changing to db 9: ", times) redcon:select(9)
Redis 不是必需的,但建议使用。作为替代,你可以故障转移到直接查询 peter_sslers 金字塔实例。
要使用 Peter SSlers 金字塔回退,将使用以下库
lua-resty-http https://github.com/pintsized/lua-resty-http
来自回退 API 的命中和未命中将被缓存到共享缓存字典中。如果你需要删除值,你需要重启服务器或使用一个 nginx/lua 示例来清除缓存。回退 API 请求将通知金字塔应用程序请求应具有写入缓存行为。
缓存说明
为了最大限度地提高性能,nginx/openresty 中有 2 层缓存
证书在给定工作进程中以
ssl_certhandler.lru_cache_duration
秒(默认 60 秒)的原生 cdata 格式保存在 LRU 缓存中证书在所有工作进程中以 PEM 格式保存在
ssl_certhandler.cert_cache_duration
秒(默认 600 秒)中
这些值可以调整。
为什么?
nginx 共享字典很容易查询、刷新/过期/覆盖值,但它只能存储 PEM 证书(而不是 cdata 指针),因此证书需要被反复解析。
LRU 缓存可以保存 cdata 指针,但 nginx/openresty 的实现细节不允许轻松查询和操作缓存。所有工作进程之间用于覆盖/过期的消息传递也是一项艰巨的任务。
处理部署问题的一种简单方法是使用对 LRU 缓存的超时,该超时足够长以在负载下表现良好,但也足够短以允许共享字典中的更改传播。
用法
确保你的 nginx 包含
`` server { init_by_lua_block { require "resty.core" local ssl_certhandler = require "peter_sslers.ssl_certhandler" ssl_certhandler.initialize() } init_worker_by_lua_block { require "resty.core" local ssl_certhandler = require "peter_sslers.ssl_certhandler" -- cert_cache_duration, lru_cache_duration, lru_maxitems ssl_certhandler.initialize_worker(90, 30, 200) } }
``
initialize
当前什么都不做。initialize_worker
接受三个参数cert_cache_duration
秒,用于 ngx.shared.DICT 中的 PEM 缓存lru_cache_duration
秒,用于工作进程中 cdata 指针的 LRU 缓存lru_maxitems
,用于工作进程中 cdata 指针的 LRU 缓存的最大项数
然后实现示例路由
由于 lua/luajit 的实现细节,以下示例必须在块/文件中实现,并且不能“require(/path/to/example)”。这是因为 redis 连接是如何实例化的。(参见 https://github.com/openresty/lua-resty-redis/issues/33 https://github.com/openresty/lua-nginx-module/issues/376)
ssl_certhandler.lua
核心库。公开多个函数。
examples/ssl_certhandler-lookup.lua
这非常简单,它只是指定缓存、持续时间和 prime_version
在 nginx 中调用...
`` server { listen 443 default_server; ... // nginx 必须具有一个默认配置的 ssl_certificate /path/to/default/fullchain.pem; ssl_certificate_key /path/to/default/privkey.pem; ssl_certificate_by_lua_block { }
``
examples/ssl_certhandler-expire.lua
nginx 共享内存缓存会在配置重新加载后持续存在。服务器必须完全重启才能清除内存。
解决方法?用于“刷新”缓存或过期某些键(域名)的 API 端点。
peter_sslers.ssl_certhandler-expire
提供了一个简单的示例,可以很容易地在 nginx 中调用
`` server { listen 443 default_server; ... location /.peter_sslers { auth_basic "peter_sslers-nginx"; auth_basic_user_file /path/to/peter_sslers-nginx.htpasswd; location /.peter_sslers/nginx/shared_cache/expire { content_by_lua_block { -- requirements local ssl_certhandler = require "peter_sslers.ssl_certhandler"
-- alias functions
local ssl_certhandler_expire = ssl_certhandler.expire_ssl_certs
ssl_certhandler_expire()
}
}
}
}
C<>``
此过期工具创建以下路由
/peter_sslers/nginx/shared_cache/expire/all
刷新整个 nginx 证书缓存/peter_sslers/nginx/shared_cache/expire/domain/{DOMAIN}
刷新证书缓存中域名的 pkey 和 chain 条目
成功后,这些路由会在 HTTP-200-OK 文档中返回 JSON。
{"result": "success", "expired": "all"}
{"result": "success", "expired": "domain", "domain": "{DOMAIN}"}
{"result": "error", "expired": "None", "reason": "Unknown URI"}
发生错误时,这些路由应生成错误状态代码。
金字塔组件可以自动为您查询这些端点。
examples/ssl_certhandler-status.lua
状态路由显示有关系统的一些信息
`` server { listen 443 default_server; ... location /.peter_sslers/nginx { auth_basic "peter_sslers-nginx"; auth_basic_user_file /path/to/peter_sslers-nginx.htpasswd; location /.peter_sslers/nginx/shared_cache/status { content_by_lua_block { -- requirements local ssl_certhandler = require "peter_sslers.ssl_certhandler"
-- alias functions
local ssl_certhandler_status = ssl_certhandler.status_ssl_certs
ssl_certhandler_status()
}
}
}
}
C<>``
examples/ssl_certhandler-lookup.lua
这是核心工作
`` ssl_certificate_by_lua_block { -- requirements local ssl_certhandler = require "peter_sslers.ssl_certhandler"
-- alias functions
local ssl_certhandler_set = ssl_certhandler.set_ssl_certificate
local prime_version = 1
local fallback_server = 'http://0.0.0.0:6543/.well-known/admin'
ssl_certhandler_set(prime_version, fallback_server)
}
C<>``
完全配置的示例
完全配置的示例可在主要 peter_sslers 仓库中找到:https://github.com/aptise/peter_sslers/blob/master/tools/nginx_conf/enabled.conf
详细信息
这种方法积极利用了 nginx 工作进程(通过工作进程 LRU 和共享字典)和 Redis 中的缓存;缓存命中和未命中。
nginx 工作进程字典在重新加载(kill -HUP {PID}
)后共享;因此,如果一个错误的值进入了那里,你必须重启或等待超时。
伪代码中的逻辑
`` cert_cdata = lru_cache.get(domain) # 检查工作进程缓存 if hit(cert_cdata): if invalid(cert_cdata): return else: cert_pem = cert_cache.get(domain) # 检查共享缓存 if hit(cert_pem): if invalid(cert_pem): lru_cache.set(domain, invalid) return else: cert_pem = redis.get(domain) if hit(cert_pem): if invalid(cert_pem): lru_cache.set(domain, invalid) cert_cache.set(domain, invalid) return else: cert_pem = upstream_https.get(domain) if hit(cert_pem): if invalid(cert_pem): lru_cache.set(domain, invalid) cert_cache.set(domain, invalid) return if valid(cert_pem) lru_cache.set(domain, cert_cdata) cert_cache.set(domain, cert_pem) cert_cdata = parse(cert_pem) if valid(cert_cdata): set_ssl_certificate(cert_cdata)
``
集成/调试方法
不同级别的信息被发送到以下 nginx 调试级别。更改 nginx 调试级别将公开更多数据
ERR
NOTICE
DEBUG
注意工作进程是如何初始化的
-- cert_cache_duration, lru_cache_duration, lru_maxitems ssl_certhandler.initialize_worker(90, 30, 100)
为了调试,你可能想要将这些值降低以将 LRU 缓存缩短为可忽略不计的数字
ssl_certhandler.initialize_worker(5, 1, 100)
“/status” 和 “/expire” 路由只显示共享缓存中的信息 - 信息被缓存到每个工作进程自己的 LRU 缓存中,并且对这些路由不可用。如果使用“/expire”,域名将从共享缓存中删除,并且“/status” 路由将... 但是可能仍然存在于工作进程的 LRU 中。
检查状态
curl -k https://peter:sslers@127.0.0.1/.peter_sslers/nginx/shared_cache/status
过期 curl -k https://peter:sslers@127.0.0.1/.peter_sslers/nginx/shared_cache/expire
已知问题
作者
Jonathan Vanasco <jonathan@findmeon.com>
最初在 https://github.com/aptise/peter_sslers 中开始
许可证
该模块根据 MIT 许可证授权。请参阅 LICENSE.txt
作者
Jonathan Vanasco (github.com/jvanasco)
许可证
mit
依赖项
pintsized/lua-resty-http,openresty
版本
-
用于 peter_sslers SSL 证书管理器的 openresty ssl 证书例程 2016-12-06 23:57:24
-
用于 peter_sslers SSL 证书管理器的 openresty ssl 证书例程 2016-12-02 23:27:13