ACME协议自动证书管理器
项目描述
ACME协议自动证书管理器。
此工具使用ACME协议从证书机构获取和维护证书,类似于EFF的Certbot。虽然该工具是在使用Let’s Encrypt开发和测试的,但它应能与任何使用ACME协议的证书机构一起工作。
功能
此工具不是Certbot的替代品,并且不尝试复制Certbot的所有功能,特别是它不会修改其他服务的配置文件,或提供服务器以执行独立域名验证。然而,它确实做了Certbot没有做的几件事,简化了更高级环境中的证书管理。除了自动颁发和维护证书外,该工具还可以维护相关的HPKP头和TLSA(DANE)记录。
主/从模式
此工具将授权(域名验证)和证书颁发过程分开,允许一台机器维护授权(主机),而另一台机器颁发证书(从机)。这对于需要隔离服务器提供服务的场景很有用,例如在防火墙后面的XMPP服务器,没有能力通过http执行授权或配置DNS记录,但仍需要获取和定期更新一个或多个证书。
超文本公钥固定(HPKP)支持
该工具可以自动生成并维护适合直接包含在服务器配置文件中的HPKP头部信息。默认提供Apache和Nginx的支持,用户可以添加其他服务器。
自动管理备份私钥
使用HPKP需要第二个公钥,以便在私钥更改时提供备份。该工具可以自动生成备份密钥,并在轮换私钥时切换到预先生成的备份密钥。私钥轮换可以自动进行,并且独立于证书到期进行计划。在备份HPKP固定时间不足的情况下,会阻止私钥轮换。
并行RSA和ECDSA证书
该工具可以生成RSA和ECDSA证书。默认情况下,它将并行生成和维护这两种类型的证书。
证书透明度/签名证书时间戳支持
该工具可以自动将您的证书注册到多个证书透明度日志,并为每个证书检索签名证书时间戳(SCT)。检索到的SCT适合通过TLS扩展进行传输,Apache和Nginx都提供了SCT TLS扩展模块,分别见Apache和Nginx。
OCSP响应文件支持
该工具可以自动获取和维护每个配置证书的OCSP响应文件。这些文件可用于从您的服务器提供粘性OCSP响应,而不依赖于服务器自身的OCSP粘性机制。某些服务器,如Nginx,会懒加载粘性OCSP响应并将响应缓存到内存中。当使用OCSP Must-Staple扩展时,这可能导致在OCSP响应刷新之前服务器不可达,在OCSP响应者故障期间,这可能会导致长时间的中断。使用磁盘上的OCSP响应可以缓解此问题。仅存储状态为“良好”的OCSP响应。
加密私钥
主密钥和备份密钥可以选择性地使用密码和您选择的加密算法进行加密。
自动本地或远程DNS更新
该工具可以自动添加和删除dns-01授权以及TLSA记录的DNS记录。可以通过外部区域文件处理器(如bindtool)更新本地服务器的更新,或者通过使用nsupdate使用RFC 2136动态DNS更新到远程DNS服务器。可以在区域级别选择本地和远程DNS更新的选择。
可配置输出文件名称
服务器管理员通常开发自己的文件命名约定或需要与其他工具的命名约定相匹配。所有证书、密钥和相关文件的名和输出目录都是可配置的。默认值旨在用于标准的Debian安装。
可配置部署钩子
每次写入密钥、证书或相关文件的操作都有可选的钩子,可以调用用户指定的程序来协助将资源部署到远程服务器或与其他工具协调。
证书安装验证
此工具可以自动连接到配置的服务器,并验证生成的证书是否通过TLS正确提供服务。还会进行额外的检查,包括OCSP基础和可选的HPKP头。
支持ACME协议V1和V2
此工具支持运行ACME V1和V2 API的服务。在使用V2 API时,可能会颁发通配符证书。
安装
需要Python 3.7+和OpenSSL支持。
在Debian Stretch及以后的版本中
sudo apt-get install python3-pip libssl-dev libffi-dev sudo pip3 install acmebot
您可能希望在虚拟环境中创建acmebot并安装它。将acmebot.example.json文件或acmebot.example.yaml文件复制到acmebot.json(或acmebot.yaml)中,并编辑配置选项。配置文件可以放置在运行工具的当前目录、/etc/acmebot目录或acmebot工具安装的同目录中。
默认情况下,调试级别的输出将写入日志文件。在logrotate.d目录中提供了一个日志轮转配置文件,您可能希望将其复制或链接到/etc/logrotate.d。
请注意,当通过本地DNS服务器使用dns-01授权时,此工具需要能够添加、删除和更新DNS记录。这可以通过在主DNS服务器上安装它并使用bindtool来管理区域文件来实现,或者您可以使用自定义的shell脚本来更新DNS记录。
当通过远程服务器使用dns-01授权时,需要更新密钥,允许创建和删除TXT记录,以及可选的TLSA记录类型。
可选:一些服务需要包括根证书在内的完整证书链(例如Nginx上的OCSP stapling)。为了生成这些文件,将您选择的证书颁发机构的根证书副本放置在配置文件的同一目录中,文件名为root_cert.rsa.pem和root_cert.ecdsa.pem,分别用于RSA和ECDSA证书根。请注意,根证书是用于签名RSA和ECDSA客户端证书的,可能不一定是同一类型,例如,Let’s Encrypt目前使用RSA根证书签名ECDSA证书。如果您的证书颁发机构使用RSA证书签名ECDSA证书类型,请将RSA根证书放置在root_cert.ecdsa.pem中。Let’s Encrypt的根证书可以从这里获取。
升级
从工具的2.0.0版本开始,默认使用Let’s Encrypt ACME V2 API。当升级到2.0.0+或更改API端点时,客户端密钥将被重新生成,并执行新的注册。如果在主/从模式下运行,请确保首先在主服务器上运行工具,然后将新的客户端密钥和注册文件复制到从服务器,再在从服务器上运行。
快速入门
基本配置
虽然示例配置文件可能看起来很复杂,但它旨在展示所有可能的配置选项及其默认值,而不是展示一个基本简单的配置。
要在配置文件中创建和维护证书,必须存在的唯一项是您的账户电子邮件地址和证书的文件名。默认情况下,证书的通用名称将与证书文件名相同。
例如
{ "account": { "email": "admin@example.com" }, "certificates": { "example.com": { "alt_names": { "example.com": ["@", "www"] } } } }
将创建一个名为example.com的证书,其通用名称为example.com,以及替代名称example.com和www.example.com。
可以根据需要配置任意数量的证书。替代名称的数量受证书颁发机构限制(Let’s Encrypt 目前允许 100 个)。替代名称在 DNS 区域的基础上指定,每个证书可以指定多个区域。区域名称使用 "@" 表示。
首次运行
一旦配置文件就位,只需执行该工具即可。对于首次运行,您可能希望选择详细输出以查看工具的确切操作。
acmebot --detail
如果一切顺利,该工具将生成用于客户端认证证书颁发机构的公钥/私钥对,在证书颁发机构注册账户,提示接受证书颁发机构的条款和条件,为每个配置的域名获取授权,根据需要生成配置证书的主要私钥,颁发证书,生成备份私钥,生成自定义 Diffie-Hellman 参数,从证书透明度日志中检索签名证书时间戳,从证书颁发机构检索 OCSP 响应,并将证书和私钥安装到 /etc/ssl/certs 和 /etc/ssl/private。
如果需要,您可以使用 Let’s Encrypt 的测试服务器测试该工具。为此,在 acme_directory_url 设置中指定测试服务器的目录 URL。有关详细信息,请参阅 Staging Environment。在从测试服务器切换到生产服务器时,您应该删除客户端密钥和注册文件 (/var/local/acmebot/*.json),以确保在生产环境中进行新的注册。
文件位置
在成功颁发证书后,每个证书将创建多达 21 个文件。
这些文件的位置可以通过配置文件的 directories 部分进行控制。这里使用默认位置以简化说明。
输出文件将作为一个单一事务写入,要么写入所有文件,要么不写入任何文件。这是为了防止在文件创建过程中发生错误时证书和私钥不匹配。
私钥
对于每种密钥类型,将在 /etc/ssl/private 中创建两个私钥文件。主私钥: <private-key-name>.<key-type>.key;以及一个备份密钥: <private-key-name>_backup.<key-type>.key。
私钥文件将以 PEM 格式写入,并且只能由所有者和组读取。
证书文件
对于每种密钥类型,将创建两个证书文件,一个位于 /etc/ssl/certs 中,命名为 <certificate-name>.<key-type>.pem,包含证书,然后是证书颁发机构发送的任何中间证书,然后是自定义 Diffie-Hellman 和椭圆曲线参数;第二个文件将创建在 /etc/ssl/private 中,命名为 <certificate-name>_full.<key-type>.key,将包含私钥,然后是证书,然后是证书颁发机构发送的任何中间证书,然后是自定义 Diffie-Hellman 和椭圆曲线参数。
<certificate-name>_full.<key-type>.key 文件对需要私钥和证书在同一文件中的服务很有用,例如 ZNC。
中间证书链文件
如果证书颁发机构使用中间证书来签名您的证书,将在 /etc/ssl/certs 中创建一个文件,文件名为 <证书名称>_chain.<密钥类型>.pem,每个密钥类型一个,包含证书颁发机构发送的中间证书。
如果将 chain 目录设置为 null,则不会创建此文件。
请注意,证书颁发机构可能使用不同类型的证书作为中间证书,例如,一个ECDSA客户端证书可能由RSA中间证书签名,因此中间证书密钥类型可能与文件名(或证书类型)不匹配。
完整链证书文件
如果存在 root_cert.<密钥类型>.pem 文件(见 安装),则将为每个密钥类型在 /etc/ssl/certs 中生成一个额外的证书文件,文件名为 <证书名称>+root.<密钥类型>.pem。此文件将包含证书,然后是证书颁发机构发送的任何中间证书,然后是根证书,最后是自定义的Diffie-Hellman和椭圆曲线参数。
如果 root_cert.<密钥类型>.pem 文件不在配置文件相同的目录中,则不会创建此证书文件。
此文件对配置Nginx服务器上的OSCP stapling非常有用。
Diffie-Hellman参数文件
如果配置了自定义Diffie-Hellman参数或自定义椭圆曲线,将在 /etc/ssl/params 中创建一个文件,文件名为 <证书名称>_param.pem,包含Diffie-Hellman参数和椭圆曲线参数。
如果将 param 目录设置为 null,则不会创建此文件。
超文本公共密钥固定(HPKP)文件
将在 /etc/ssl/hpkp 中创建两个额外的文件,分别命名为 <私有密钥名称>.apache 和 <私有密钥名称>.nginx。这些文件包含设置每个密钥类型主备私钥的HTTP头部指令。
每个文件适合分别包含在Apache或Nginx的服务器配置中。
如果将 hpkp 目录设置为 null,则不会创建这些文件。
签名证书时间戳(SCT)文件
将为每个密钥类型和配置的证书透明度日志在 /etc/ssl/scts/<证书名称>/<密钥类型>/<日志名称>.sct 中创建一个额外的文件。这些文件包含适合包含在TLS扩展中的二进制SCT信息。默认情况下,SCT将从Google Icarus和Google Pilot证书透明度日志检索。Google Test Tube证书透明度日志可用于Let’s Encrypt测试环境。
OCSP响应文件
将为每个密钥类型在 /etc/ssl/ocsp 中创建一个OCSP响应文件,文件名为 <证书名称>.<密钥类型>.ocsp。这些文件包含适合用作stapled OCSP响应的二进制OCSP响应。
存档目录
每次运行工具时替换现有文件,例如在证书续订或私钥滚动时,所有现有文件都将保存在存档目录 /etc/ssl/archive 中。
在存档目录中,将创建一个以私钥命名的目录,其中包含一个带时间戳的目录,用于文件交易时间(YYYY-MM-DD_HHMMSS)。如果需要恢复,所有现有文件都将移动到带时间戳的目录中。
服务器配置
由于证书文件需要定期更换以进行续订,因此最好让服务器配置简单引用创建证书的目录中的证书和密钥文件。这样可以防止在更换证书文件时更新服务器配置。
如果服务器需要证书或密钥文件位于特定位置或具有不同的文件名,最好简单地创建一个指向证书或密钥文件的软链接,而不是重命名或复制文件。
另一个好的做法是将每个证书的配置单独保存在一个片段文件中,例如使用Apache,创建文件 /etc/apache2/snippets/ssl/example.com 包含
SSLCertificateFile /etc/ssl/certs/example.com.rsa.pem SSLCertificateKeyFile /etc/ssl/private/example.com.rsa.key CTStaticSCTs /etc/ssl/certs/example.com.rsa.pem /etc/ssl/scts/example.com/rsa # requires mod_ssl_ct to be installed SSLCertificateFile /etc/ssl/certs/example.com.ecdsa.pem SSLCertificateKeyFile /etc/ssl/private/example.com.ecdsa.key CTStaticSCTs /etc/ssl/certs/example.com.ecdsa.pem /etc/ssl/scts/example.com/ecdsa # requires mod_ssl_ct to be installed Header always set Strict-Transport-Security "max-age=63072000" Include /etc/ssl/hpkp/example.com.apache
然后在每个使用该证书的主机配置中,简单地添加
Include snippets/ssl/example.com
对于Nginx,/etc/nginx/snippets/ssl/example.com 文件将包含
ssl_ct on; # requires nginx-ct module to be installed ssl_certificate /etc/ssl/certs/example.com.rsa.pem; ssl_certificate_key /etc/ssl/private/example.com.rsa.key; ssl_ct_static_scts /etc/ssl/scts/example.com/rsa; # requires nginx-ct module to be installed ssl_stapling_file /etc/ssl/ocsp/example.com.rsa.ocsp; ssl_certificate /etc/ssl/certs/example.com.ecdsa.pem; # requires nginx 1.11.0+ to use multiple certificates ssl_certificate_key /etc/ssl/private/example.com.ecdsa.key; ssl_ct_static_scts /etc/ssl/scts/example.com/ecdsa; # requires nginx-ct module to be installed ssl_stapling_file /etc/ssl/ocsp/example.com.ecdsa.ocsp; # requires nginx 1.13.3+ to use with multiple certificates ssl_trusted_certificate /etc/ssl/certs/example.com+root.rsa.pem; # not required if using ssl_stapling_file ssl_dhparam /etc/ssl/params/example.com_param.pem; ssl_ecdh_curve secp384r1; add_header Strict-Transport-Security "max-age=63072000" always; include /etc/ssl/hpkp/example.com.nginx;
并且可以通过以下方式使用
include snippets/ssl/example.com;
配置
配置文件 acmebot.json 或 acmebot.yaml 可以放置在当前工作目录、/etc/acmebot 或 acmebot工具安装的同一目录中。可以在命令行上指定不同的配置文件名。如果指定的文件名不是绝对路径,它将在同一位置进行搜索,例如 acmebot --config config.json 将加载 ./config.json、/etc/acmebot/config.json 或 <install-dir>/config.json。如果省略文件扩展名,工具将在每个位置搜索具有扩展名: .json、.yaml 和 .yml 的文件。如果指定的文件是绝对路径,则只在该位置进行搜索。
额外的配置文件可以放置在配置文件同一目录下的 conf.d 子目录中。该子目录中所有具有扩展名: .json、.yaml 或 .yml 的文件将被加载并合并到配置中,覆盖主配置文件中的任何设置。例如,每个证书的配置可以放在单独的文件中,而通用设置保留在主配置文件中。
配置文件必须遵循标准的JSON或YAML格式。本文件中给出的示例为JSON格式,然而,等效的结构也可以用YAML表示。
acmebot.example.json 和 acmebot.example.yaml 文件提供了所有配置选项及其默认值的模板。尖括号 "<example>" 内的内容必须替换(不带尖括号),所有其他值可以删除,除非您想覆盖默认值。
账户
输入您希望与证书颁发机构上的账户关联的电子邮件地址。如果您丢失客户端密钥,该电子邮件地址可能有助于恢复您的账户。
示例
{ "account": { "email": "admin@example.com" }, ... }
设置
工具的各种设置。所有这些仅在所需值与默认值不同时需要存在。
follower_mode 指定工具是否应以主模式或从模式运行。默认值是 false(主模式)。主模式将获取授权并颁发证书,从模式将不会尝试获取授权但可以颁发证书。
log_level 用于指定写入日志文件的信息量。可能的值有 null、"normal"、"verbose"、"debug" 和 "detail"。设置 "verbose"、"debug" 和 "detail" 与命令行选项 --verbose、--debug 和 --detail 相关。
color_output 用于指定是否应对输出进行着色。非tty设备上会抑制着色输出。此选项可以通过命令行选项覆盖。默认值为 true。
key_types 用于指定默认生成的私钥类型。默认值是 ['rsa', 'ecdsa']。
key_size 用于指定RSA私钥的大小(以位为单位)。默认值是 4096。通过将此值设置为 0 或 null 来关闭RSA证书。
key_curve 用于指定ECDSA私钥所使用的曲线。默认值是 "secp384r1"。可用的曲线有 "secp256r1"、"secp384r1" 和 "secp521r1"。通过将此值设置为 null 来关闭ECDSA证书。
key_cipher 用于指定加密私钥所使用的加密算法。默认值是 "blowfish"。可用的加密算法是您OpenSSL版本接受的那些。
key_passphrase 用于指定加密私钥所使用的密码短语。默认值是 null。值为 null 或 false 将导致私钥以未加密的形式写入。值为 true 将导致从命令行、环境、提示或stdin读取密码。字符串值将用作密码短语而无需进一步输入。
key_provided 用于指定私钥由外部来源提供,并且工具不应修改它们。默认值是 false。
dhparam_size 用于指定自定义Diffie-Hellman参数的大小(以位为单位)。默认值是 2048。通过将此值设置为 0 或 null 来关闭自定义Diffie-Hellman参数。此值应至少等于 key_size 的一半。
ecparam_curve 用于指定用于ECDHE协商的曲线或曲线列表。此值可以是字符串或字符串列表。默认值是 ["secp521r1", "secp384r1", "secp256k1"]。通过将此值设置为 null 来关闭自定义EC参数。您可以运行 openssl ecparam -list_curves 来查找可用的曲线列表。
file_user 用于指定将拥有证书和私钥文件的用户名称。默认值是 "root"。请注意,此工具必须以root用户身份运行,或者运行另一个有权将文件所有权设置为该用户的用户。
file_group 指定将拥有证书和私钥文件的组名。默认值为 "ssl-cert"。请注意,此工具必须以 root 或具有将文件所有权设置为该组的权限的其他用户身份运行。
log_user 指定将拥有日志文件的用户名。默认值为 "root"。请注意,此工具必须以 root 或具有将文件所有权设置为该用户的权限的其他用户身份运行。
log_group 指定将拥有日志文件的组名。默认值为 "adm"。请注意,此工具必须以 root 或具有将文件所有权设置为该组的权限的其他用户身份运行。
warning_exit_code 指定警告是否会产生非零退出码。默认值为 false。
hpkp_days 指定HPKP pin应该缓存的天数。默认值为 60。通过将此值设置为 0 或 null 来关闭HPKP pin文件。
pin_subdomains 指定是否应在HPKP头中包含 includeSubdomains 指令。默认值为 true。
hpkp_report_uri 指定报告HPKP失败的uri。默认值为 null。如果不为null,则将在HPKP头中包含 report-uri 指令。
ocsp_must_staple 指定是否将OCSP Must-Staple扩展添加到证书中。默认值为 false。
ocsp_responder_urls 指定如果证书没有提供它们,则要使用的OCSP响应者列表。默认值为 ["http://ocsp.int-x3.letsencrypt.org"]。
ct_submit_logs 指定将证书提交到的证书透明度日志列表。默认值为 ["google_icarus", "google_pilot"]。对于Let’s Encrypt测试环境,可以使用值 ["google_testtube"]。
renewal_days 指定在证书到期前多少天,工具将尝试续订证书。默认值为 30。
expiration_days 指定私钥应使用的天数。默认值为 730(两年)。当备份密钥达到这个年龄时,工具将通知用户应执行密钥滚动,或者如果 auto_rollover 设置为 true,则自动滚动私钥。可以通过将此值设置为 0 或 null 来禁用自动滚动和到期通知。
auto_rollover 指定工具是否应自动滚动已过期的私钥。默认值为 false。请注意,当以主/从配置运行并在主节点和从节点之间共享私钥时,必须在主节点上执行密钥滚动,并手动将其传输到从节点,因此不应使用自动滚动,除非独立运行。
max_dns_lookup_attempts 指定在尝试授权之前检查已部署DNS记录的次数。默认值为 60。
dns_lookup_delay 指定DNS查询之间的等待秒数。默认值为 10。
max_domains_per_order 用于指定每个授权订单允许的最大域名数量。默认值是 100,这是Let’s Encrypt设定的限制。
max_authorization_attempts 用于指定检查完成授权的次数。默认值是 30。
authorization_delay 用于指定在授权检查之间等待的秒数。默认值是 10。
cert_poll_time 用于指定等待证书颁发的秒数。默认值是 30。
max_ocsp_verify_attempts 用于指定在验证过程中检查OCSP staples的次数。仅在证书具有OCSP Must-Staple扩展时才会进行重试。默认值是 10。
ocsp_verify_retry_delay 用于指定在OCSP staple验证尝试之间的等待秒数。默认值是 5。
min_run_delay 用于指定如果存在 --randomwait 命令行选项时,等待的最小秒数。默认值是 300。
max_run_delay 用于指定如果存在 --randomwait 命令行选项时,等待的最大秒数。默认值是 3600。
acme_directory_url 用于指定ACME服务的默认URL。默认值是 "https://acme-v02.api.letsencrypt.org/directory",即Let’s Encrypt的生产API。您可以替换为Let’s Encrypt的测试环境或其他证书机构的URL。
acme_directory_verify_ssl 用于指定是否验证ACME服务的证书。默认值是 True。不建议将其设置为 False,但在使用私有ACME服务器的情况下可能有必要。
reload_zone_command 用于指定执行重新加载本地DNS区域信息的命令。当使用 bindtool 时,"reload-zone.sh" 脚本提供此服务。如果不使用本地DNS更新,可以将其设置为 null 以避免警告。
nsupdate_command 用于指定执行DNS更新的命令。默认值是 "/usr/bin/nsupdate"。
verify 用于指定执行安装验证的默认端口。默认值是 null。
services 用于指定与证书关联的默认服务。默认值是 null。
示例
{ ... "settings": { "follower_mode": false, "log_level": "debug", "key_size": 4096, "key_curve": "secp384r1", "key_cipher": "blowfish", "key_passphrase": null, "key_provided": false, "dhparam_size": 2048, "ecparam_curve": ["secp521r1", "secp384r1", "secp256k1"], "file_user": "root", "file_group": "ssl-cert", "hpkp_days": 60, "pin_subdomains": true, "hpkp_report_uri": null, "ocsp_must_staple": false, "ocsp_responder_urls": ["http://ocsp.int-x3.letsencrypt.org"], "ct_submit_logs": ["google_icarus", "google_pilot"], "renewal_days": 30, "expiration_days": 730, "auto_rollover": false, "max_dns_lookup_attempts": 60, "dns_lookup_delay": 10, "max_authorization_attempts": 30, "authorization_delay": 10, "min_run_delay": 300, "max_run_delay": 3600, "acme_directory_url": "https://acme-v02.api.letsencrypt.org/directory", "reload_zone_command": "/etc/bind/reload-zone.sh", "nsupdate_command": "/usr/bin/nsupdate", "verify": [443] }, ... }
目录
用于存储工具输入和输出文件的目录。相对路径将被视为相对于配置文件目录的相对路径。只有当所需的值与默认值不同时,才需要这些目录。
pid 用于指定存储进程ID文件的目录。默认值是 "/var/run"。
log 用于指定存储日志文件的目录。默认值是 "/var/log/acmebot"。
resource 用于指定存储ACME账户客户端密钥和注册文件的目录。默认值是 "/var/local/acmebot"。
private_key 用于指定存储主私钥文件的目录。默认值是 "/etc/ssl/private"。
backup_key 用于指定存储备份私钥文件的目录。默认值是 "/etc/ssl/private"。
previous_key 指定了在密钥轮换后存储以前使用的私钥文件的目录。默认值为 null。
full_key 指定了存储包含证书链的原始私钥文件的目录。默认值为 "/etc/ssl/private"。可以通过将其设置为 null 来省略完整密钥文件。
certificate 指定了存储证书文件的目录。默认值为 "/etc/ssl/certs"。
full_certificate 指定了存储包含根证书的完整链证书文件的目录。默认值为 "/etc/ssl/certs"。可以通过将其设置为 null 来省略完整证书文件。
chain 指定了存储证书中间链文件的目录。默认值为 "/etc/ssl/certs"。可以通过将其设置为 null 来省略链文件。
param 指定了存储Diffie-Hellman参数文件的目录。默认值为 "/etc/ssl/params"。可以通过将其设置为 null 来省略参数文件。
challenge 指定了存储ACME dns-01挑战文件的目录。默认值为 "/etc/ssl/challenge"。
http_challenge 指定了存储ACME http-01挑战文件的目录。默认值为 null。
hpkp 指定了存储HPKP头部文件的目录。默认值为 "/etc/ssl/hpkp"。可以通过将其设置为 null 来关闭HPKP头部文件。
sct 指定了存储已签名证书时间戳文件的目录。默认值为 "/etc/ssl/scts/<certificate-name>/<key-type>"。可以通过将其设置为 null 来关闭SCT文件。
ocsp 指定了存储OCSP响应文件的目录。默认值为 "/etc/ssl/ocsp"。可以通过将其设置为 null 来关闭OCSP响应文件。
update_key 指定了搜索DNS更新密钥文件的目录。默认值为 "/etc/ssl/update_keys"。
archive 指定了存储此工具替换的旧版本文件的目录。默认值为 "/etc/ssl/archive"。
temp 指定了写入临时文件的目录。如果值为 null,则使用系统定义的临时目录。临时目录必须位于与输出文件目录相同的文件系统上。默认值为 null。
示例
{ ... "directories": { "pid": "/var/run", "log": "/var/log/acmebot", "resource": "/var/local/acmebot", "private_key": "/etc/ssl/private", "backup_key": "/etc/ssl/private", "full_key": "/etc/ssl/private", "certificate": "/etc/ssl/certs", "full_certificate": "/etc/ssl/certs", "chain": "/etc/ssl/certs", "param": "/etc/ssl/params", "challenge": "/etc/ssl/challenges", "http_challenge": "/var/www/{zone}/{host}/.well-known/acme-challenge", "hpkp": "/etc/ssl/hpkp", "ocsp": "/etc/ssl/ocsp/", "sct": "/etc/ssl/scts/{name}/{key_type}", "update_key": "/etc/ssl/update_keys", "archive": "/etc/ssl/archive" }, ... }
目录值被视为Python格式字符串,可用于目录的字段有:name、key_type、suffix、server。字段 name 是私钥或证书的名称。"http_challenge" 目录使用字段:zone、host 和 fqdn 分别表示区域名称、主机名(不带区域)和完全限定域名。如果fqdn与区域名称相同,则 host 值将是 "."。
服务
本部分指定了由颁发的证书使用的服务列表以及当颁发或更改证书时重启或重新加载服务所需的命令。根据需要,您可以添加或删除服务。服务列表是任意的,它们从单个证书定义中引用。
示例
{ ... "services": { "apache": "systemctl reload apache2", "coturn": "systemctl restart coturn", "dovecot": "systemctl restart dovecot", "etherpad": "systemctl restart etherpad", "mysql": "systemctl reload mysql", "nginx": "systemctl reload nginx", "postfix": "systemctl reload postfix", "postgresql": "systemctl reload postgresql", "prosody": "systemctl restart prosody", "slapd": "systemctl restart slapd", "synapse": "systemctl restart matrix-synapse", "znc": "systemctl restart znc" }, ... }
要指定一个或多个证书使用的服务,请将一个 services 部分添加到证书定义中,列出使用该证书的服务。
例如
{ "certificates": { "example.com": { "alt_names": { "example.com": ["@", "www"] }, "services": ["nginx"] } } }
这将导致在颁发、续订或更新证书 example.com 时执行命令 "systemctl reload nginx"。
证书
本节定义了要颁发和维持的证书集。每个证书的名称用作证书文件的名称。
common_name 指定证书的通用名称。如果省略,则使用证书名称。
alt_names 指定证书的主题备用名称集。如果指定,证书的通用名称必须作为备用名称之一包含。备用名称按 DNS 区域指定为主机名列表,以便在正确的区域中发生相关的 DNS 更新。区域名称可以直接通过为主机名指定 "@" 来使用。可以指定多个区域。默认值是按照 Public Suffix List 的第一个注册域名的区域中证书的通用名称。例如,如果通用名称是“example.com”,则默认的 alt_names 将是: {"example.com": ["@"] };如果通用名称是“foo.bar.example.com”,则默认的 alt_names 将是: { "example.com": ["foo.bar"] }。
services 指定在颁发、续订或修改证书时重新加载的服务列表。这可以省略。默认值是 settings 部分中指定的值。
dhparam_size 指定用于证书的自定义 Diffie-Hellman 参数的位数。默认值是 settings 部分中指定的值。通过将此值设置为 0 或 null,可以从证书中省略自定义 Diffie-Hellman 参数。该值应至少等于私钥使用的位数的一半。
ecparam_curve 指定用于椭圆曲线参数的曲线或曲线。默认值是 settings 部分中指定的值。通过将此值设置为 null,可以从证书中省略自定义椭圆曲线参数。
key_types 指定为该证书创建的密钥类型。默认值是所有可用的密钥类型。提供密钥类型列表以限制证书仅限于这些类型。可用的类型是 "rsa" 和 "ecdsa"。
key_size 指定用于证书 RSA 私钥的位数。默认值是 settings 部分中指定的值。通过将此值设置为 0 或 null,可以关闭 RSA 证书。
key_curve 指定用于 ECDSA 私钥的曲线。默认值是 settings 部分中指定的值。可用的曲线是 "secp256r1"、"secp384r1" 和 "secp521r1"。通过将此值设置为 null,可以关闭 ECDSA 证书。
key_cipher 用于指定加密私钥所使用的加密算法。默认值是设置部分指定的值。可用的加密方式是 OpenSSL 的 EVP_get_cipherbyname() 所接受的那些。
key_passphrase 用于指定加密私钥所使用的密码短语。默认值是设置部分指定的值。如果值为 null 或 false,则私钥将未加密写入。如果值为 true,则密码将从命令行、环境、提示或 stdin 读取。如果值为字符串,则将使用该字符串作为密码短语,无需进一步输入。
key_provided 用于指定私钥由外部来源提供,工具不应修改它们。默认值是设置部分指定的值。这在同一私钥在工具的多个实例之间共享时很有用,例如用于 HPKP 目的。
expiration_days 用于指定备份私钥被视为有效的天数。默认值是设置部分指定的值。当备份密钥达到这个年龄时,工具将通知用户应该执行密钥轮换,或者如果 auto_rollover 设置为 true,则自动轮换私钥。可以通过将此值设置为 0 或 null 来禁用自动轮换和过期通知。
auto_rollover 用于指定工具是否应在密钥过期时自动轮换私钥。默认值是设置部分指定的值。
hpkp_days 用于指定客户端缓存 HPKP 指针的天数。默认值是设置部分指定的值。可以通过将此值设置为 0 或 null 来关闭 HPKP 指针文件。
pin_subdomains 用于指定是否应在 HPKP 标头中包含 includeSubdomains 指令。默认值是设置部分指定的值。
hpkp_report_uri 用于指定报告 HPKP 错误的 URI。默认值是设置部分指定的值。如果非空,则将在 HPKP 标头中包含 report-uri 指令。
ocsp_must_staple 用于指定是否将 OCSP Must-Staple 扩展添加到证书中。默认值是设置部分指定的值。
ocsp_responder_urls 用于指定如果证书没有提供它们,则应使用的 OCSP 响应者列表。默认值是设置部分指定的值。
ct_submit_logs 用于指定提交证书的证书透明度日志列表。默认值是设置部分指定的值。可以使用值 ["google_testtube"] 与 Let’s Encrypt 测试环境一起用于测试。
verify 用于指定执行证书安装验证的端口号列表。默认值是设置部分指定的值。
示例
{ ... "certificates": { "example.com": { "common_name": "example.com", "alt_names": { "example.com": ["@", "www"] }, "services": ["nginx"], "dhparam_size": 2048, "ecparam_curve": ["secp521r1", "secp384r1", "secp256k1"], "key_types": ["rsa", "ecdsa"], "key_size": 4096, "key_curve": "secp384r1", "key_cipher": "blowfish", "key_passphrase": null, "key_provided": false, "expiration_days": 730, "auto_rollover": false, "hpkp_days": 60, "pin_subdomains": true, "hpkp_report_uri": null, "ocsp_must_staple": false, "ocsp_responder_urls": ["http://ocsp.int-x3.letsencrypt.org"], "ct_submit_logs": ["google_icarus", "google_pilot"], "verify": [443] } } }
私钥
本节定义了生成的私钥集及其相关证书。多个证书可能共享单个私钥。当希望为某些子域使用不同的证书,同时为也应用于子域的根域指定 HPKP 标头时,这很有用。
每个私钥的名称用作私钥文件的文件名。
请注意,在“证书”部分配置的证书与在此部分配置的具有与私钥相同名称的单个证书的私钥等效。因此,在“证书”和“私钥”部分中指定具有相同名称的证书是错误的。
私钥和证书设置与在“证书”部分指定的设置相同,只是与私钥相关的设置:key_size、key_curve、key_cipher、key_passphrase、key_provided、expiration_days、auto_rollover、hpkp_days、pin_subdomains 和 hpkp_report_uri 都在私钥对象中指定,而不是在证书对象中指定。可以在证书、私钥或两者中指定 key_types 设置。
示例
{ ... "private_keys": { "example.com": { "certificates": { "example.com": { "common_name": "example.com", "alt_names": { "example.com": ["@", "www"] }, "services": ["nginx"], "key_types": ["rsa"], "dhparam_size": 2048, "ecparam_curve": ["secp521r1", "secp384r1", "secp256k1"], "ocsp_must_staple": true, "ct_submit_logs": ["google_icarus", "google_pilot"], "verify": [443] }, "mail.example.com": { "alt_names": { "example.com": ["mail", "smtp"] }, "services": ["dovecot", "postfix"], "key_types": ["rsa", "ecdsa"] } }, "key_types": ["rsa", "ecdsa"], "key_size": 4096, "key_curve": "secp384r1", "key_cipher": "blowfish", "key_passphrase": null, "key_provided": false, "expiration_days": 730, "auto_rollover": false, "hpkp_days": 60, "pin_subdomains": true, "hpkp_report_uri": null } }, ... }
上述示例将生成一个主/备份私钥集和两个证书,分别是 example.com 和 mail.example.com,都使用相同的私钥。仅会为 mail.example.com 生成 ECDSA 证书。
TLSA 记录
当使用远程 DNS 更新时,工具可以自动为每个证书维护 TLSA 记录。请注意,这需要为包含 TLSA 记录的每个区域配置区域更新密钥。
当使用本地 DNS 更新时,在证书颁发、续订或修改后,将调用 reload_zone 命令,以便通过像 bindtool 这样的工具更新 TLSA 记录。在从属模式下不会调用 reload_zone 命令。
要指定 TLSA 记录,在每个证书定义中添加一个 tlsa_records 名称/对象对,无论是在 certificates 或 private_keys 部分中。TLSA 记录按 DNS 区域指定,类似于 alt_names,以指定每个 TLSA 记录应更新哪个区域。
对于 TLSA 记录对象中的每个区域,指定一个主机名字符串或对象列表。
{ "host": "<host-name>" }
对象的值如下:
host 指定 TLSA 记录的主机名。默认值是 "@"。主机名 "@" 用来表示区域本身的名称。
port 指定 TLSA 记录的端口号。默认值是 443。
usage 是以下之一:"pkix-ta"、"pkix-ee"、"dane-ta" 或 "dane-ee"。默认值是 "pkix-ee"。当指定端效 TLSA 记录("pkix-ee" 或 "dane-ee")时,生成的哈希将是证书或公钥本身。当指定信任锚 TLSA 记录("pkix-ta" 或 "dane-ta")时,将为中间证书和根证书生成记录。
选择器可以是以下之一:"cert" 或 "spki"。默认值是 "spki"。当指定 "spki" 值和末端执行器使用时,将生成主备份公钥的记录。
协议指定 TLSA 记录的协议。默认值是 "tcp"。
ttl 指定 TLSA 记录的 TTL 值。默认值是 300。
示例
{ ... "private_keys": { "example.com": { "certificates": { "example.com": { "alt_names": { "example.com": ["@", "www"] }, "services": ["nginx"], "tlsa_records": { "example.com": [ "@", { "host": "www", "port": 443, "usage": "pkix-ee", "selector": "spki", "protocol": "tcp", "ttl": 300 } ] } }, "mail.example.com": { "alt_names": { "example.com": ["mail", "smtp"] }, "services": ["dovecot", "postfix"], "tlsa_records": { "example.com": [ { "host": "mail", "port": 993 }, { "host": "smtp", "port": 25, "usage": "dane-ee" }, { "host": "smtp", "port": 587 } } } } } } }, ... }
HTTP 挑战
默认情况下,该工具将尝试使用本地或远程 DNS 更新为每个指定的替代名称进行 dns-01 域授权。
要使用 http-01 授权,请在配置文件中配置 http_challenges 部分,指定每个完全限定域名(FQDN)的挑战目录,或配置一个 http_challenge 目录。
可以在主机级别混合使用 dns-01 和 http-01 域授权,只需为需要 http-01 认证的特定主机指定 http 挑战目录即可。
示例
{ ... "http_challenges": { "example.com": "/var/www/htdocs/.well-known/acme-challenge" "www.example.com": "/var/www/htdocs/.well-known/acme-challenge" }, ... }
http_challenges 必须指定本地文件系统上的目录,这样放置在该目录中的文件将通过为每个给定的域名运行的已运行的 http 服务器提供。在上面的示例中,放置在 /var/www/htdocs/.well-known/acme-challenge 的文件必须在以下位置公开可用:http://example.com/.well-known/acme-challenge/file-name 和 http://www.example.com/.well-known/acme-challenge/file-name
或者,如果您主要使用 http-01 授权,并且所有挑战目录具有相似的路径,您可以使用具有字段 zone、host 和 fqdn 的 Python 格式字符串配置单个 http_challenge 目录。
示例
{ ... "directories": { "http_challenge": "/var/www/{zone}/{host}/.well-known/acme-challenge" }, ... }
如果配置了 http_challenge 目录,所有域授权默认为 http-01。要为选定的域名使用 dns-01 授权,请添加一个配置为 null 值的 http_challenges 条目。
区域更新密钥
当使用远程 DNS 更新时,需要指定用于签名更新请求的 TSIG 密钥。
对于使用远程 DNS 更新的每个区域,指定包含 TSIG 密钥文件名的字符串,或指定一个具有更多选项的对象。
TSIG 文件名可以是绝对路径或相对于 update_key 目录设置的相对路径。必须同时存在 <key-file>.key 文件和 <key-file>.private 文件。
任何在证书、私钥或授权中引用但没有相应区域更新密钥的区域将使用本地 DNS 更新,除非已为该区域中的每个主机指定 HTTP 挑战目录。
file 指定 TSIG 密钥文件的名称。
server 指定发送更新请求的DNS服务器名称。如果省略,则使用区域SOA记录中的主名称服务器。
port 指定发送更新请求的端口号。默认值为 53。
示例
{ ... "zone_update_keys": { "example1.com": "update.example1.com.key", "example2.com": { "file": "update.example2.com.key", "server": "ns1.example2.com", "port": 53 } }, ... }
密钥类型后缀
每个证书和密钥文件都有一个后缀,位于文件扩展名之前,表示该文件是哪种密钥。
每个密钥类型的默认后缀可以在 key_type_suffixes 节中覆盖。如果您只使用一种密钥类型或想省略一种密钥类型的后缀,请将其设置为空字符串。请注意,如果使用多种密钥类型,后缀必须唯一,否则文件将被覆盖。
示例
{ ... "key_type_suffixes": { "rsa": ".rsa", "ecdsa": ".ecdsa" }, ... }
文件名模式
所有输出文件名都可以使用标准的Python格式字符串进行覆盖。可用于文件名的字段有:name(名称)、key_type(密钥类型)、suffix(后缀)、server(服务器)。name 字段是私钥或证书的名称。
log 指定日志文件的名称。
private_key 指定主要私钥文件名称。
backup_key 指定备份私钥文件名称。
full_key 指定包含证书链的主要私钥文件名称。
certificate 指定证书文件名称。
full_certificate 指定包含根证书的证书文件名称。
chain 指定中间证书文件名称。
param 指定Diffie-Hellman参数文件名称。
challenge 指定用于本地DNS更新的ACME挑战文件名称。
hpkp 指定HPKP头部文件名称。
ocsp 指定OCSP响应文件名称。
sct 指定SCT文件名称。
示例
{ ... "file_names": { "log": "acmebot.log", "private_key": "{name}{suffix}.key", "backup_key": "{name}_backup{suffix}.key", "full_key": "{name}_full{suffix}.key", "certificate": "{name}{suffix}.pem", "full_certificate": "{name}+root{suffix}.pem", "chain": "{name}_chain{suffix}.pem", "param": "{name}_param.pem", "challenge": "{name}", "hpkp": "{name}.{server}", "ocsp": "{name}{suffix}.ocsp", "sct": "{ct_log_name}.sct" }, ... }
HPKP头部
本节定义了将要生成的HPKP头部文件集及其内容。可以随意添加附加服务器的头部文件,每个服务器将生成一个文件。使用标准的Python格式字符串,{header} 字段将被HPKP头部替换,{key_name} 字段将被私钥名称替换,{server} 将被服务器名称替换。可以通过将头部设置为 null 来省略默认服务器。
示例
{ ... "hpkp_headers": { "apache": "Header always set Public-Key-Pins \"{header}\"\n", "nginx": "add_header Public-Key-Pins \"{header}\" always;\n" }, ... }
证书透明度日志
本节定义了可用于提交证书并从中检索SCT的证书透明度日志集。可以随意添加附加日志。每个日志定义需要日志的主API URL和日志的base64格式ID。可以找到当前活动日志及其ID的列表,请参阅 certificate-transparency.org。
示例
{ ..., "ct_logs": { "google_pilot": { "url": "https://ct.googleapis.com/pilot", "id": "pLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BA=" }, "google_icarus": { "url": "https://ct.googleapis.com/icarus", "id": "KTxRllTIOWW6qlD8WAfUt2+/WHopctykwwz05UVH9Hg=" } }, ... }
部署钩子
本节定义了一组在给定操作发生时通过shell可以调用的钩子。钩子的参数使用Python格式字符串指定。每个钩子可用的字段如下所述。钩子输出的内容将被捕获在日志中。返回非零状态码的钩子将生成警告,但不会以其他方式影响此工具的操作。
set_dns_challenge 在设置每个DNS挑战记录时被调用。可用字段有 domain(域名)、zone(区域)和 challenge(挑战)。
对于每个被删除的DNS挑战记录,都会调用 clear_dns_challenge。可用的字段有 domain、zone 和 challenge。
当通过本地或远程更新更新DNS区域时,会调用 dns_zone_update。可用的字段是 zone。
对于每个安装的HTTP挑战文件,都会调用 set_http_challenge。可用的字段是 domain 和 challenge_file。
对于每个被删除的HTTP挑战文件,都会调用 clear_http_challenge。可用的字段是 domain 和 challenge_file。
当使用备份私钥替换私钥时,会调用 private_key_rollover。可用的字段有 key_name、key_type、backup_key_file、private_key_file、previous_key_file 和 passphrase。
当安装私钥时,会调用 private_key_installed。可用的字段是 key_name、key_type、private_key_file 和 passphrase。
当安装备份私钥时,会调用 backup_key_installed。可用的字段是 key_name、key_type、backup_key_file 和 passphrase。
在密钥轮换后安装之前私钥时,会调用 previous_key_installed。可用的字段是 key_name、key_type、previous_key_file 和 passphrase。
当安装HPKP头文件时,会调用 hpkp_header_installed。可用的字段是 key_name、server、header 和 hpkp_file。
当安装证书文件时,会调用 certificate_installed。可用的字段是 key_name、key_type、certificate_name 和 certificate_file。
当安装包含根证书的证书文件时,会调用 full_certificate_installed。可用的字段是 key_name、key_type、certificate_name 和 full_certificate_file。
当安装证书中间链文件时,会调用 chain_installed。可用的字段是 key_name、key_type、certificate_name 和 chain_file。
当安装包含完整证书链的私钥时,会调用 full_key_installed。可用的字段是 key_name、key_type、certificate_name 和 full_key_file。
当安装params文件时,会调用 params_installed。可用的字段是 key_name、certificate_name 和 params_file。
当安装SCT文件时,会调用 sct_installed。可用的字段是 key_name、key_type、certificate_name、ct_log_name 和 sct_file。
当安装OCSP文件时,会调用 ocsp_installed。可用的字段是 key_name、key_type、certificate_name 和 ocsp_file。
示例
{ ... "hooks": { certificate_installed": "scp {certificate_file} remote-server:/etc/ssl/certs/" }, ... }
证书安装验证
该工具可以被配置为执行证书安装验证。在验证安装时,该工具将连接到所有可用的IP地址上的每个证书的每个主体替代主机名,按照每个配置的端口号,执行TLS握手,并将提供的证书链与指定的证书进行比较。
每个配置的端口号可以是一个整数端口号,或者一个指定连接详情的对象。
当使用对象时,可用的字段包括
port 指定要连接的端口号。这是必需的。
starttls 指定用于启动TLS会话的STARTTLS机制。允许的值有:null、smtp、pop3、imap、sieve、ftp、ldap 和 xmpp。默认值是 null。
protocol 指定用于获取验证所需额外信息的协议。目前这可以检索Public-Key-Pins HTTP头以确保它们被正确设置。允许的值有:null 和 http。默认值是 null。
hosts 指定要测试的完全合格域名列表。这允许仅测试证书指定的替代名称的子集。每个主机名都必须作为证书的替代名称存在。默认值是所有替代名称。
key_types 指定要测试的密钥类型列表。这允许仅测试可用的密钥类型的子集。默认值是所有可用的密钥类型。
示例
{ ... "verify": [ { "port": 443, "protocol": "http" }, { "port": 25, "starttls": "smtp", "hosts": "smtp.example.com", "key_types": "rsa" }, 993 ] ... }
配置本地DNS更新
为了执行dns-01授权,并保持TLSA记录更新,该工具需要能够添加、删除和更新各种DNS记录。
为了在本地服务器上更新DNS,该工具被设计为使用bind区域文件预处理器,例如bindtool,但也可以使用其他工具。
当使用bindtool时,请确保将bindtool的acme_path配置为等于challenge目录的值,以便它可以找到ACME挑战文件。
当该工具需要更新DNS区域时,它将使用区域名称作为参数调用配置的reload_zone命令。当需要设置_acme-challenge记录时,将在包含区域名称的challenge目录中放置一个文件,例如/etc/ssl/challenges/example.com。挑战文件是一个JSON格式文件,包含一个对象。该对象的名称/值对是需要设置的记录的完全合格域名及其值,例如
{ "www.example.com": "gfj9Xq...Rg85nM" }
这将导致在区域中创建以下DNS记录
_acme-challenge.www.example.com. 300 IN TXT "gfj9Xq...Rg85nM"
请注意,包含通配符的域名必须在相应的TXT记录中删除通配符组件,例如
{ "example.com": "jc87sd...kO89hG" "*.example.com": "gfj9Xq...Rg85nM" }
必须导致在区域中创建以下DNS记录
_acme-challenge.example.com. 300 IN TXT "jc87sd...kO89hG" _acme-challenge.example.com. 300 IN TXT "gfj9Xq...Rg85nM"
如果challenge目录中没有与区域同名的文件,应删除所有_acme-challenge记录。
每次调用reload_zone时,还应根据存在的证书或私钥更新与区域关联的任何TLSA记录。
所有这些功能都由bindtool自动提供,通过在区域文件中使用{{acme:}}和{{tlsa:}}命令实现。例如,区域文件
{{soa:ns1.example.com:admin@example.com}} {{ip4=192.0.2.0}} @ NS ns1 @ NS ns2 @ A {{ip4}} www A {{ip4}} {{tlsa:443}} {{tlsa:443:www}} {{acme:}} {{caa:letsencrypt.org}}
将定义使用名称服务器ns1.example.com和ns1.example.com的区域example.com,并提供主机example.com和www.example.com,使用TLSA记录锁定主备密钥。
配置远程DNS更新
如果工具不在同时托管DNS服务器的机器上运行,则必须使用http-01授权或远程DNS更新。
通过RFC 2136动态更新使用远程DNS更新,为每个区域配置一个区域更新密钥。有关更多信息,请参阅区域更新密钥部分。
还需要安装nsupdate工具,并在settings配置部分中配置nsupdate_command。
区域更新密钥可以通过dnssec-keygen工具生成。
例如
dnssec-keygen -r /dev/urandom -a HMAC-MD5 -b 512 -n HOST update.example.com
将生成两个文件,分别命名为Kupdate.example.com.+157+NNNNN.key和Kupdate.example.com.+157+NNNNN.private。将.key文件指定为区域更新密钥。
要配置bind允许远程DNS更新,将包含私钥文件中的密钥值的条目添加到named.conf.keys中,例如
key update.example.com. { algorithm hmac-md5; secret "sSeWrBDen...9WESlnEwQ=="; };
然后向区域配置添加一个allow-update条目,例如
zone "example.com" { type master; allow-update { key update.example.com.; }; ... };
运行工具
首次运行时,工具将生成客户端密钥,将该密钥注册到证书颁发机构,接受证书颁发机构的条款和条件,执行所有必要的域名授权,生成主私钥,颁发证书,生成备份私钥,生成自定义Diffie-Hellman参数,安装证书和密钥文件,更新TLSA记录,从配置的证书透明度日志中检索当前的签名证书时间戳(SCTs),检索OCSP staples,重新加载与证书关联的服务,并执行配置的证书安装验证。
每次后续运行都将确保所有授权保持有效,检查是否有任何备份私钥已过期,检查是否有任何证书的到期日期在续订窗口内,或者配置的通用名称、主题备用名称已更改,或者不再匹配其关联的私钥文件。
如果备份私钥已过期,则工具将轮换私钥或发出警告,建议轮换私钥,有关更多信息,请参阅私钥轮换部分。
如果需要续订证书或已修改证书,则将重新颁发和重新安装证书。
颁发或重新颁发证书时,将尝试进行本地DNS更新(以更新TLSA记录)并重新加载相关服务。
在使用远程DNS更新时,将在每次运行时验证并更新所有配置的TLSA记录。
将查询配置的证书透明度日志,并根据需要更新SCT文件。
通常,每次运行都会处理所有证书和私钥,要限制处理特定的私钥(及其证书),您可以在命令行上列出要处理的私钥的名称。
通过cron每天运行
为了确保正在使用的证书不会过期,建议至少每天通过cron作业运行一次工具。
默认情况下,工具仅在采取操作时生成输出,使其适合cron。可以通过--quiet命令行选项抑制正常输出。
为了防止同时运行多个实例,可以通过--randomwait
命令行选项引入随机等待时间。最小和最大等待时间可以通过min_run_delay
和max_run_delay
设置来控制。
示例cron条目,位于文件/etc/cron.d/acmebot
MAILTO=admin@example.com 20 0 * * * root /usr/local/bin/acmebot --randomwait
这将每天午夜20分钟后运行工具,并加上5分钟到1小时的随机延迟。任何输出都会通过电子邮件发送到admin@example.com。
如果使用OCSP响应文件,可能需要更短的时间间隔来刷新OCSP响应。(目前Let’s Encrypt每三天更新一次OCSP响应。)要每六小时刷新OCSP响应,请添加以下行
20 6,12,18 * * * root /usr/local/bin/acmebot –ocsp –randomwait
输出选项
通常,工具只在证书签发或需要滚动私钥时向标准输出生成输出。可以通过在命令行上使用--verbose
、--debug
或--detail
选项来获取更详细的信息。
可以使用--quiet
选项来抑制正常输出。
错误和警告输出将被发送到标准错误,并且无法被抑制。
可以通过添加--color
选项来按类型着色输出,或者可以通过--no-color
选项来抑制着色输出。
私钥滚动更新
在正常操作中,证书的私钥不会修改,这允许在不更新相关固定信息的情况下续订或修改证书,例如使用spki选择器的HPKP头或TLSA记录。
然而,定期更换私钥或认为主私钥可能已被泄露时立即更换私钥是一种良好的安全实践。此工具为每个主私钥维护一个备份私钥,并根据需要生成包括备份密钥在内的固定信息,以便平滑过渡到备份密钥。
当备份私钥达到通过expiration_days
设置指定的年龄时,工具将通知您是时候滚动更新私钥了,除非已将auto_rollover
设置设置为true
,在这种情况下,它将自动执行滚动更新。
滚动更新过程将归档当前主私钥,使用现有的备份密钥作为新的主密钥重新签发证书,生成新的备份私钥,生成新的自定义Diffie-Hellman参数,并适当重置HPKP头和TLSA记录。
如果指定了previous_key
目录,当前主私钥将存储在该目录中作为之前的私钥。当存在之前的私钥文件时,它们的密钥签名将被添加到HPKP固定和TLSA记录中。这有助于在密钥用于子域且私钥在多个服务器之间共享时进行密钥滚动更新。一旦将新的主密钥和备份密钥分发给其他服务器,可以安全地删除之前的私钥文件。
要手动滚动更新私钥,只需使用--rollover
选项运行工具。您可以在命令行上指定要滚动的单个私钥的名称,否则将滚动所有私钥。
请注意,如果当前备份密钥比HPKP持续时间短,则工具将拒绝覆盖私钥。在此期间覆盖私钥可能会导致网站对之前已缓存HPKP头部但尚未检索当前备份密钥pin的客户端不可访问。如果无论如何需要覆盖私钥,例如,如果相信备份密钥也已被破坏,请在命令行上添加--force选项以强制覆盖私钥。
强制证书更新
通常,当工具在证书更新窗口内运行时,证书将自动更新,例如在证书到期日期前的renewal_days天内。要在此时间之前更新证书,请在命令行上使用--renew选项运行工具。
撤销证书
如果需要撤销证书,例如,如果相信私钥已被破坏,请在命令行上使用--revoke选项运行工具。
在撤销证书时,作为一种安全措施,还必须指定应撤销的私钥(或密钥)的名称。使用该私钥的所有证书都将被撤销,证书文件和主要私钥文件将移动到存档,并删除远程DNS TLSA记录。
撤销后下一次运行工具时,任何仍然配置的已撤销证书将自动执行私钥滚动更新。
仅证书
使用命令行上的--certs选项将限制工具仅颁发和更新证书和密钥,以及更新相关文件,例如Diffie-Hellman参数和HPKP头部。
远程TLSA更新
使用命令行上的--tlsa选项将限制工具仅通过远程DNS更新验证和更新配置的TLSA记录。
签名证书时间戳更新
使用命令行上的--sct选项将限制工具仅验证和更新配置的签名证书时间戳文件。
OCSP响应更新
使用命令行上的--ocsp选项将限制工具仅更新配置的OCSP响应文件。
证书安装验证
使用命令行上的--verify选项将限制工具仅执行证书安装验证。
多操作
可以组合使用--auth、--certs、--tlsa、--sct、-ocsp和--verify选项来执行一系列操作。如果没有指定这些选项中的任何一个,将根据需要和配置执行所有操作。操作顺序不受命令行选项顺序的影响。
私钥加密
在加密私钥时,必须提供密码短语。提供密钥有几种选项。
密码短语可以直接在配置文件中指定,既可以作为适用于所有密钥的默认密码短语,也可以为每个密钥指定特定的密码短语。如果配置文件存储在与密钥相同的机器上,将密码短语以明文形式存储在配置文件中对保护私钥显然帮助不大。请保护配置文件或使用其他提供密码短语的方法。
或者,通过在配置文件中将密码短语设置为 true(二进制值,而非字符串 "true"),工具将尝试在运行时获取密码短语。
运行时密码短语可以通过命令行、环境变量、文本提示或输入文件提供。
命令行密码短语通过 --pass 选项传递,例如。
acmebot --pass "passphrase"
要使用环境变量,请在 ACMEBOT_PASSPHRASE 中设置密码短语。
通过命令行或环境变量传递的密码短语将用于每个将其 key_passphrase 设置为 true 的私钥。如果为不同的密钥需要不同的密码短语,请在命令行中为每个密钥指定私钥名称,以限制处理范围到该密钥。
如果未在命令行或环境变量中提供密码短语,并且通过 TTY 设备(例如在终端中手动)运行工具,它将根据需要提示用户输入每个密码短语。可以为每个私钥提供不同的密码短语(同一密码短语将用于该密钥的所有密钥类型)。
最后,密码短语可以存储在文件中,每行一个,然后从该文件重定向输入,例如。
acmebot < passphrase_file.txt
通过输入文件传递的密码短语将按照配置文件中定义的私钥定义顺序使用。如果同时定义了证书和私钥部分,则首先处理私钥,然后是证书。您可能首先运行工具不使用输入文件以验证私钥顺序。
主/从设置
在某些情况下,以主/从配置运行工具是有用的。在这种设置中,主服务器执行域名授权,而从服务器颁发和维护证书。
当从服务器没有执行域名授权的能力时,例如,位于防火墙后且没有端口 80 开放或无法访问 DNS 服务器的 XMPP 服务器时,此设置很有用。
要创建主/从设置,首先以正常方式安装并配置主服务器上的工具。主服务器也可以颁发证书,但这不是必需的。
在主服务器上配置任何必需的域名授权(请参阅 授权 部分)并运行工具。
然后从从服务器上安装工具。在从服务器上不需要配置 HTTP 挑战或远程 DNS 更新密钥。
在从服务器上运行工具之前,从主服务器复制客户端密钥和注册文件。这些文件通常位于 /var/local/acmebot,但可以在 resource 目录设置中配置其他位置。
如果主服务器也为与从服务器相同的域名或父域名颁发证书,则可能需要将这些证书的主备私钥复制到从服务器。这将导致从服务器证书使用相同的密钥,从而允许 HPKP 标头安全地包括子域名。
将从服务器的 follower_mode 设置设置为 true 并在从服务器上配置所需的证书。
在从服务器上运行工具。
在为主节点和从节点设置cron任务时,请确保从节点在主节点启动后运行几分钟,以便所有授权都已完成。理论上,主节点可能需要 (max_dns_lookup_attempts x dns_lookup_delay) + (max_authorization_attempts x authorization_delay) 秒来获取域名授权(默认设置为15分钟)。
可以为每个主节点运行多个从节点服务器,但不应同时运行所有从节点的cron任务。
如果从节点上配置了远程DNS更新,从节点可能维护TLSA记录;否则,建议使用spki选择器为TLSA记录,以便从节点的证书续订不会使TLSA记录失效。
如果主节点和从节点之间共享私钥,请确保关闭auto_rollover,并且仅在主节点上执行私钥轮换。指定previous_key目录也有用,可以在密钥轮换过程中保留旧密钥固定。私钥轮换后,将新的主备私钥文件复制到从节点。从节点将自动检测新的私钥,并在下一次运行时重新颁发证书。一旦所有从节点都已将其证书更新到新密钥,就可以安全地删除旧私钥文件。
项目详情
下载文件
下载适合您平台的应用程序。如果您不确定选择哪个,请了解更多关于安装包的信息。
源分发
构建分发
acmebot-2.13.0.tar.gz的散列
算法 | 散列摘要 | |
---|---|---|
SHA256 | 45e4fb7789953ed4781b98924de8e8fdc82b8407838df8c1ff6073436b46dd8f |
|
MD5 | c4432bfc67441801fc7c258f023e96e3 |
|
BLAKE2b-256 | 8f843ca7c820741796ce6d6cb3290adc1d99e5adbb8089bbb914c1bf336689d0 |
acmebot-2.13.0-py3-none-any.whl的散列
算法 | 散列摘要 | |
---|---|---|
SHA256 | 04dfa8683578cf041e0109a4049d98c6fa6c67c7b7d314f7cd9b9afb6b9d88dc |
|
MD5 | 6576b5362b794ac5aac94f55be47f7fd |
|
BLAKE2b-256 | 645d258732a270290ccd5ca21ce90ff1ebbdde976a1cc96adeae0ee8fc849430 |