# Webship中的TLS证书:嵌入式ACME CA
TLS 证书有两个作用:它有助于加密连接,并告诉客户端它正在与哪个身份进行通信。加密可以很强,但对受众来说信任决策可能是错误的。这就是为什么证书自动化必须从一个问题开始:谁必须信任这个网站?
Webship 1.4.0 会为每个配置的网站独立做出该选择。公共网站可以使用浏览器信任的 ACME 证书,内部服务可以使用 Webship 内置的私有证书颁发机构,而具有现有 PKI 的网站可以保留由操作员管理的证书文件。它们都可以共享一个 Webship 进程,而无需共享一个私钥或一个信任边界。
四种自动证书模式,每个网站可选择
certificate_mode 字段属于每个 [[sites]] 条目。它不是全局开关。
| 模式 | 信任来源 | 最佳匹配 | 验证路径 | | --- | --- | --- | --- | | 每个站点 | 公共浏览器和操作系统信任的存储 | 拥有一个确切主机名的公共站点 | 使用 TLS-ALPN-01 的公共 ACME | | 队列 | 公共浏览器和操作系统信任存储 | 在显式注册域下的大量三级和四级名称集合 | 公共 ACME,带 DNS-01 和稳定的证书分片 | | 嵌入式 | 由操作员安装的私人 Webship 根 | 内部服务、托管设备、私人车队和测试环境 | 进程内签发;无外部挑战 | | 共享 | 公共浏览器和操作系统信任存储 | 故意使用单个公共多 SAN 组的传统部署 | 使用 TLS-ALPN-01 的公共 ACME |
默认是 per_site。它为网站的精确名称订购一个公共证书。Fleet 模式是适用于许多深层子域的可扩展公共选项。Embedded 模式使用 Webship 的私有进程内 CA。Shared 模式仍可用于兼容性,但它不是默认设置。
在 [sites.tls] 下,完整的证书和密钥总是优先于该站点的自动签发。
“嵌入式 ACME CA” 的意思
配置部分名为 [acme_ca],但嵌入的 CA 不是公共或网络可访问的 ACME 服务。它不提供任何目录端点,不接受远程注册,不调用任何注册器 API,也不执行任何控制权证明挑战。
相反,Webship 将整个私人发行路径保存在一个流程中:
- 该站点选择 certificate_mode = "embedded"。
- Webship 在配置的状态目录中加载或创建私有根身份。
- Webship 为该网站生成一个新的私钥。
- 嵌入式根为该确切名称签署了一份叶子证书。
- Webship 在将完整的身份安装到实时 TLS 解析器之前,会验证该身份。
- 该证书随后可用于该站点的每个启用的协议。
一种 ACME 风格的网络挑战只会向 Webship 本身证明,因此嵌入的路径故意没有网络协议。[acme_ca] 部分是私有 PKI 状态:它定义了根的位置以及签发的叶证书的有效期。
为一个站点配置嵌入式证书
这是私人网站的最小形状:
~~~toml listen = "0.0.0.0:443"
[tls] unknown_sni = "reject"
[自动_tls] 已启用 = 真 cache_dir = "/var/lib/webship/acme"
[acme_ca] state_dir = "/var/lib/webship/acme-ca" leaf_validity_days = 90
[[站点]] domain = "service.internal.example" root = "/srv/service" certificate_mode = "embedded"
[站点.协议] h1 = 真 h2 = 真 h3 = 真 ~~~
根身份在嵌入站点首次需要它时懒惰地创建。Webship 将根密钥以受限权限保存在 state_dir 中。根证书的有效期为十年;叶证书的有效期由 leaf_validity_days 控制。
将两个存储位置都视为生产状态:
- ACME 缓存保存自动管理的站点身份。
- 嵌入式 CA 状态目录保存着私有根身份。
- 服务账户需要访问权限,但应用程序用户不需要。
- 备份必须保持机密性和文件权限。
- 生产、开发和测试应使用不同的根目录和不同的目录。
删除根目录并不会“重置 TLS”。它会创建一个新的信任锚。信任旧根目录的客户端会拒绝由替换根颁发的证书,直到它们的信任存储被更新。
私人信托是有意的
嵌入式 CA 的证书不会被公共浏览器或操作系统自动信任。只有在操作员将导出的 Webship 根证书安装到客户端的信任存储中后,它们才会被信任。
这使得嵌入模式非常适合于:
- 通过设备管理注册的公司管理的笔记本电脑和手机;
- 具有显式 CA 捆绑的内部服务间流量;
- 私人电器和受控边缘设备队列;
- 必须执行真实 TLS 行为的开发和测试环境;
- 无法依赖公共 CA 的断开网络。
这不是普通公共网站的正确模式,普通网站的访问者使用未管理的浏览器。对于准确的公共名称,请使用每站点公共签发;对于大型公共子域集合,请使用群发签发;仅对有意的传统多 SAN 部署使用共享;或使用已信任 PKI 的手动文件。
仅将根证书分发给客户端。绝不要分发根私钥。持有该密钥的人可以颁发每个已注册客户端都信任的身份。
公有证书和私有证书可以共存
Webship 1.4.0 可以在同一个监听器上混合使用证书策略:
~~~toml listen = "0.0.0.0:443"
[tls] unknown_sni = "reject"
[自动_tls] 已启用 = 真 directory_url = "https://acme-v02.api.letsencrypt.org/directory" cache_dir = "/var/lib/webship/acme" contacts = ["mailto:ops@example.com"] 接受服务条款 = true
[acme_ca] state_dir = "/var/lib/webship/acme-ca" leaf_validity_days = 90
[[站点]] 域名 = "www.example.com" root = "/srv/public" certificate_mode = "每站点"
[[站点]] 域名 = "control.internal.example" root = "/srv/control" certificate_mode = "embedded"
[[站点]] domain = "payments.example.com" root = "/srv/payments"
[sites.tls] cert = "/etc/webship/payments-fullchain.pem" key = "/etc/webship/payments-private-key.pem" ~~~
在这里,www.example.com 接收其自己的公共 ACME 证书。control.internal.example 从嵌入的 CA 接收私有证书。payments.example.com 仍然处于运营商的外部 PKI 之下,因为其显式文件优先。
公众 ACME 目录会被嵌入的网站忽略。嵌入的根从不签署公共网站。手动网站从不被静默地加入任何自动工作流程。
一个证书解析器,适用于 H1、H2、H3 和 WebTransport
证书选择发生在 TLS 握手期间,在 HTTP 请求存在之前。Webship 使用 ClientHello 中的服务器名称来选择站点身份,然后协商应用协议。
- HTTP/1.1 和 HTTP/2 在 TCP 上使用 TLS。
- HTTP/3 和 WebTransport 在 UDP 上的 QUIC 内使用 TLS。
- 一个有效的网站身份可以用于每个启用的协议。
- HTTP/3 还需要 UDP 可达性;H1 和 H2 使用 TCP 路径。
- Alt-Svc 可以在保留 TCP 回退的同时宣传 H3。
TCP、TLS 和 QUIC 使用相同的站点感知身份模型。精确名称优先,在配置了通配符证书的情况下,最长有效通配符优先,并且可以拒绝未知名称的 SNI,而不是接收无关的默认证书。
当必须让未识别的主机名关闭失败时,在多站点侦听器上使用 unknown_sni = "reject"。在生产发布前,测试已识别的名称、未识别的名称以及预期的无 SNI 行为。
在没有服务间隙的情况下旋转嵌入身份
Webship 通过其经过认证、仅限环回的 MCP 服务器暴露证书状态和受控变更:
- webship.tls.get_status 报告活动的证书解析器和续订状态。
- webship.tls.reissue_certificate 仅当站点使用嵌入模式时,才会立即重新签发自动管理的站点证书。
- webship.tls.reload 通过正常的受保护 TLS 路径重新加载证书状态。
- webship.acme_ca.status 报告是否选择了私有 CA、其状态目录、叶证书有效期、签发数量、吊销数量以及最近的域名示例。
- webship.sites.apply 根据固定的配置版本添加或删除站点。
对于嵌入式重新发布,Webship 会在切换到服务之前创建并验证替代品。当前有效的身份会持续提供服务,直到新身份准备就绪。仅在安装了替代品之后才记录已退役的身份。
即时重新签发操作故意拒绝公共每站点证书。公共续订必须保持在公共 ACME 生命周期内,而不能与私有处理中签名混淆。共享模式成员身份也被重新启动冻结,因为更改多 SAN 组会重建身份边界。
MCP 是一个特权控制面。保持其在回环模式,要求使用 TLS 和强身份验证令牌,远程管理时使用经过认证的隧道,并审计每一次变更。
重要的失败界限
一个安全的证书系统必须朝正确的方向失败。
- 新配置的嵌入式站点在发放等待期间不会接收其他站点的身份。
- 无效的替换不会安装在有效证书上。
- 明确的手动文件阻止该网站的自动所有权。
- 在 HTTP 路由之前,未知的命名 SNI 可以被拒绝。
- 嵌入式 CA 保持私有,并且没有远程注册端点。
- 公共和嵌入式身份在自动 TLS 状态中使用不同的缓存路径。
嵌入式 CA 未初始化的警告意味着 Webship 无法激活配置的状态目录。在向受影响的网站发送流量之前,请修复所有权、权限、持久性或存储可用性。不要通过复制其他环境的根密钥来规避此错误。
生产清单
启用嵌入模式之前:
- 识别必须信任该网站的每个客户群体。
- 创建用于导出和安装根证书的受控流程。
- 为生产、开发和测试使用单独的根状态。
- 坚持并保护嵌入式 CA 状态目录和自动 TLS 缓存。
- 在专用服务账户下运行 Webship,该账户仅能访问所需的密钥材料。
- 在每个必须明确其信任边界的网站上选择 certificate_mode。
- 设置并测试未知 SNI 策略。
- 故意启用 H1、H2 和 H3,并验证 TCP 和 UDP 路径。
- 在生产环境之外进行重新发布、重启、备份、恢复和客户端信任验证的演练。
- 在部署前运行 webship --check-config,然后从真实客户端验证颁发者、名称、有效性、链和协商的协议。
先选择信任,再选择自动化
嵌入式 CA 消除了私有基础设施对外部证书服务的依赖。它并不会使私有根证书在全球范围内受信任,也不会免除运营商的 PKI 责任。
Webship 自动执行密钥生成、签名、验证、安装、轮换以及协议范围内的证书选择。操作员仍然拥有根管理权、客户端注册、环境隔离、备份、恢复,以及选择使用公共或私有信任路径的决定权。
这种分离就是特点。一个独立的服务器可以自动执行私有 TLS,而无需假装是公共 CA——而公共网站仍然可以在同一过程中使用浏览器信任的每站点或集群签发。
在部署之前阅读版本化的 Webship 1.4.0 文档。RFC 5280 定义了证书配置文件和验证,RFC 6066 定义了 TLS 服务器名称信号,RFC 8446 定义了 TLS 1.3,RFC 8555 定义了公共 ACME,RFC 9525 定义了服务身份验证。