Traefik 证书配置完全指南:用户自定义证书、证书存储与默认证书(Certificates  Stores) Traefik 证书配置完全指南用户自定义证书、证书存储与默认证书Certificates Stores【免费下载链接】traefikThe Cloud Native Application Proxy项目地址: https://gitcode.com/GitHub_Trending/tr/traefik本篇技术指南围绕 Traefik云原生应用代理动态配置体系中的 TLS 证书模块展开系统讲解tls.certificates与tls.stores两大配置区的设计初衷、字段语义与使用限制。你将掌握如何在不重启、不中断服务的前提下为入口点动态加载/卸载用户自备证书理解 Traefik 基于 SNI 选择证书的内部机制、默认证书与 ACME 默认证书的区别及优先级并能在 Docker、Swarm、Kubernetes 等典型场景中正确落地证书配置。全文以 docs/content/reference/routing-configuration/http/tls/tls-certificates.md 为主线并结合仓库中pkg/tls的真实实现代码印证底层原理。前置认知路由器如何进入 HTTPS 通道Traefik 本身并不区分 HTTP 与 HTTPS 入口点是否启用 TLS 取决于路由器Router定义中是否携带tls字段。文档明确给出约定当路由器需要处理 HTTPS 流量时应在路由器定义中用tls字段予以声明。只有带tls字段的 HTTP 路由才会参与 TLS 握手阶段的证书协商tls字段可以与tls-options.mdTLS 选项如最低版本、密码套件、SNI 严格校验等关联决定握手细节。也就是说证书的“存储与选择”和“握手行为”虽然分属tls.stores/tls.certificates与tls.options两套配置但最终都在 TLS 握手中协同生效。Certificates Definition证书的两种来源在 Traefik 中一份证书指一对证书文件certFile与私钥文件keyFile。证书配置层面存在两条供给路径供给方式说明适用场景自动化Automated由 ACME 类证书解析器如 Lets Encrypt按需签发、自动续期需要公开信任证书、不想手工维护证书生命周期用户自定义User defined在动态配置中显式列出certFile/keyFile指向自备证书内网证书、自有 CA 签发证书、迁移既有证书自动化签发的完整流程不在本文展开它归属于 ACME 解析器体系详见 docs/content/reference/install-configuration/tls/certificate-resolvers/acme.md。本文重点剖析用户自定义这条路径。用户自定义证书动态配置语法用户自定义证书的最大特点是运行时热更新——即使 Traefik 已经启动也可以随时把证书定义加入动态配置的tls.certificates段从而动态添加/移除证书无需重启进程。文档给出的结构化配置如下tls: certificates: - certFile: /path/to/domain.cert keyFile: /path/to/domain.key - certFile: /path/to/other-domain.cert keyFile: /path/to/other-domain.key[[tls.certificates]] certFile /path/to/domain.cert keyFile /path/to/domain.key [[tls.certificates]] certFile /path/to/other-domain.cert keyFile /path/to/other-domain.key证书字段的源码级细节路径还是内联内容certFile/keyFile对应的 Go 类型定义在 pkg/tls/certificate.go// Certificate holds a SSL cert/key pair // Certs and Key could be either a file path, or the file content itself. type Certificate struct { CertFile types.FileOrContent json:certFile,omitempty toml:certFile,omitempty yaml:certFile,omitempty KeyFile types.FileOrContent json:keyFile,omitempty toml:keyFile,omitempty yaml:keyFile,omitempty loggable:false }从源码注释与字段声明可以确认两个实用细节FileOrContent双重语义CertFile/KeyFile既可以填写本地文件路径也可以直接内联 PEM 内容实现见 pkg/tls/certificate.go 的FileOrContent.Read()先尝试按路径os.ReadFile路径不存在时把字符串本身当作内容读取。私钥不进日志KeyFile字段标记了loggable:false而CertFile提供了GetTruncatedCertificateName()方法对超长 PEM 内容做截断避免敏感信息与超长内容污染日志。最终加载时Certificate.GetCertificate() 读取两者内容并调用 Go 标准库crypto/tls的tls.X509KeyPair(certContent, keyContent)完成 PEM 解析与配对校验——因此证书与私钥必须匹配、格式必须为可被标准库解析的 PEM否则该证书会被丢弃并在日志中记录错误Certificates.GetCertificates() 对单个失败证书只跳过、不阻塞整批加载。提供方式的限制File provider 与 Kubernetes Secret文档特别标注了一条Restriction限制需要读者特别注意在上面的例子中我们使用了 File provider 来处理这些定义。它是配置证书以及 options、stores的唯一可用方法。而在 Kubernetes 中证书必须且只能通过 Secrets 提供。也就是说无论你使用 Docker、Swarm、Consul、etcd 还是其他 Provider 作主数据源tls.certificates/tls.stores这类敏感密钥型动态配置只能经由 File provider可参考 file provider 文档写入动态配置——逻辑上保证密钥数据只存在于本地方可审计的路径中Kubernetes 场景下证书来源被统一收口到Secrets由 kubernetes-crd provider 与 TLSStore 资源协作完成装载不直接书写certFile。Certificate selection (SNI)握手阶段如何挑选证书TLS 握手中服务端在看到 HTTP 内容之前就必须决定向客户端出示哪张证书。Traefik 的策略是Traefik 依据客户端在 ClientHello 中发送的Server Name Indication (SNI)来选择握手时出示的证书。由于 HTTP 路由规则例如Host()在 TLS 建立之后才被求值因此它们不会影响证书选择。对应源码位于 pkg/tls/certificate_store.go 的GetBestCertificate(clientHello *tls.ClientHelloInfo)其核心逻辑可以概括为归一化 SNI对clientHello.ServerName做小写化与去空白若客户端完全未携带 SNI则退而尝试用本地连接的对端地址作匹配键certificate_store.go。命中缓存优先证书匹配结果会被缓存默认 1 小时过期见NewCertificateStore同一 serverName 的后续握手直接复用避免每次握手重复遍历。精确匹配 单层通配遍历动态证书时先比较证书 SAN 域名与 serverName 是否完全相等否则把 serverName 的第一个标签替换为*再做匹配matchDomaincertificate_store.go——这意味着*.example.com能覆盖api.example.com但不匹配多层子域a.api.example.com与浏览器通配证书约定一致。遍历有序性证书以“去重排序后的 SAN 列表用逗号连接”为键存储于DynamicCerts映射遍历时按键逆序保证匹配行为确定。每张证书参与匹配的“身份集合”由parseCertificate提取Subject 的 CommonName、全部 DNSName SAN 与 IP SAN 统一小写化后构成匹配域certificate_store.go。换句话说一张证书能否被某域名命中取决于证书自身携带的 CN/DNS SAN/IP SAN而不是配置文件里写了什么名字。Strict SNI Checking严格模式与默认证书回退默认情况下若客户端未发送 SNI或没有任何证书能匹配请求的服务器名Traefik 会回退使用 TLS Store 中配置的默认证书该证书仅在有配置时存在。如果你希望拒绝这类连接而不是默默回退到默认证书可以在 TLS Options 中开启sniStrict严格 SNI 校验。从 pkg/tls/tlsmanager.go 的配置装配可见sniStrict取自 TLS Options 的布尔字段并直接参与握手回调逻辑——开启后当GetBestCertificate无法返回匹配证书且无默认证书兜底路径可用时握手即被终止。适合多租户、证书白名单严控等场景。Certificates Stores证书存储的真相在 Traefik 中证书并非平铺存放而是按证书存储Certificate Store分组。理解存储模型需要把握以下要点。全局唯一default store文档给出的第一条Restriction信息量很大除默认存储名为default之外的任何 store 定义都会被忽略因此全局仅存在一个 TLS 存储。这也解释了为什么你从未见过多 store 的生产配置虽然语法上tls.stores支持任意键名Traefik 只会真正维护名为default的那一个。事实上从数据结构看Store 本身只承担两类职责——承载默认证书、以及承载 ACME 默认证书的解析意图见 pkg/tls/tls.gotype Store struct { DefaultCertificate *Certificate json:defaultCertificate,omitempty ... DefaultGeneratedCert *GeneratedCert json:defaultGeneratedCert,omitempty ... }为证书指定归属语法上在tls.certificates段中你可以通过stores列表声明证书“存储到哪里”tls: certificates: - certFile: /path/to/domain.cert keyFile: /path/to/domain.key stores: - default # Note that since no store is defined, # the certificate below will be stored in the default store. - certFile: /path/to/other-domain.cert keyFile: /path/to/other-domain.key[[tls.certificates]] certFile /path/to/domain.cert keyFile /path/to/domain.key stores [default] [[tls.certificates]] # Note that since no store is defined, # the certificate below will be stored in the default store. certFile /path/to/other-domain.cert keyFile /path/to/other-domain.key紧接着文档又给出第二条Restriction直接挑明了该字段的现实地位stores列表实际上会被忽略并自动被设置为[default]。因此实践中可以有两种等价写法——显式写stores: [default]或者干脆省略最终效果相同全部进入全局唯一defaultstore。对应数据结构为CertAndStorespkg/tls/tls.go其中Stores []string仅作配置面占位。运行期证书去重则发生在 certificate_store.go 的appendCertificate同一 store 内若出现 SAN 键完全相同的证书后者会被跳过并记录 debug 日志。各 Provider 下如何实际“启用 TLS”并挂载这些证书文档给出了逐场景示例锚点Docker启用 TLSSwarm启用 TLSKubernetes启用 TLSDefault Certificate显式默认证书与内建回退对于无 SNI或SNI 无任何证书命中的连接Traefik 需要一个“最后防线”证书。此时可通过tls.stores.default.defaultCertificate显式指定tls: stores: default: defaultCertificate: certFile: path/to/cert.crt keyFile: path/to/cert.key[tls.stores] [tls.stores.default] [tls.stores.default.defaultCertificate] certFile path/to/cert.crt keyFile path/to/cert.key文档特别说明如果未提供defaultCertificateTraefik 将使用其自动生成的那张证书。这段回退链与 pkg/tls/tlsmanager.go 中buildDefaultCertificate的实现相呼应显式配置的默认证书会被读取解析、注册到证书存储甚至为它装配 OCSP 装订OCSP Stapling一旦读取/解析失败或压根未配置则落到 Traefik 进程内自签/自生成的默认证书保证任何情况下握手都有证书可用。需要留意的是由于兜底证书是自动生成的客户端通常会看到不受信任的证书告警——因此生产环境建议要么显式配置可信默认证书要么用下面介绍的 ACME 默认证书方案。ACME Default Certificate让解析器代劳默认证书除了静态指定一张默认证书你还可以让 Traefik 通过 ACME 解析器如 Lets Encrypt动态取得一张默认证书并把解析意图写进 TLS storetls: stores: default: defaultGeneratedCert: resolver: myresolver domain: main: example.org sans: - foo.example.org - bar.example.org[tls.stores] [tls.stores.default.defaultGeneratedCert] resolver myresolver [tls.stores.default.defaultGeneratedCert.domain] main example.org sans [foo.example.org, bar.example.org]同样地在 Docker/Swarm 的Labels或 Consul 等 Provider 的Tags中可以按点分键名书写同一份意图labels: - traefik.tls.stores.default.defaultgeneratedcert.resolvermyresolver - traefik.tls.stores.default.defaultgeneratedcert.domain.mainexample.org - traefik.tls.stores.default.defaultgeneratedcert.domain.sansfoo.example.org, bar.example.org{ Name: default, Tags: [ traefik.tls.stores.default.defaultgeneratedcert.resolvermyresolver, traefik.tls.stores.default.defaultgeneratedcert.domain.mainexample.org, traefik.tls.stores.default.defaultgeneratedcert.domain.sansfoo.example.org, bar.example.org ] }三个关键字段字段语义resolver负责签发的 ACME 解析器名称需先在静态配置中定义domain.main默认证书的主域名domain.sans追加的 SAN 列表与main一起进入证书签名请求从类型定义可见其落点pkg/tls/tls.gotype GeneratedCert struct { // Resolver is the name of the resolver that will be used to issue the DefaultCertificate. Resolver string json:resolver,omitempty ... // Domain is the domain definition for the DefaultCertificate. Domain *types.Domain json:domain,omitempty ... }优先级defaultGeneratedCert 高于 ACME 默认证书这里有一处文档反复强调、容易踩坑的优先级规则defaultGeneratedCert的定义优先于 ACME 默认证书的配置。结合 tlsmanager.go 中的默认证书装配顺序可以还原完整逻辑若DefaultGeneratedCert非空且同时具备resolver与有效domainTraefik 会先尝试经由 ACME 管理器按main/sans取回/签发证书域非法或解析器取不到证书时才回退到进程内生成的默认证书。也就是说一旦你在 store 里写了defaultGeneratedCert它会取代“解析器在默认规则下顺手产出的 ACME 默认证书”成为首选回退证书而显式defaultCertificate属于另一条静态路径。三者的完整取舍关系为显式默认证书 / ACME 默认证书 →defaultGeneratedCert所指定的动态签发结果 → 进程内自生成证书。实战小结与配置自查清单归纳本文涉及的全部事实可作为排查 TLS 证书问题的速查表路由器须声明tls字段才会进入 HTTPS/证书协商证书选择只看SNIHost()等 HTTP 规则在握手后才生效无法参与选证。用户自定义证书写在动态配置的tls.certificates支持热增/热删certFile/keyFile既可以是路径也可以是内联 PEM但私钥永不进日志。证书定义含 options、stores只能通过 file provider 提供Kubernetes 中必须经由 Secrets参见 kubernetes-crd provider。全局只有一个defaultstorestores字段会被忽略并强制为[default]。无 SNI / 无匹配时默认回退到默认证书需要严格拒绝时在 TLS Options 中开启sniStrict。默认证书可用静态defaultCertificate指定否则落到 Traefik 自生成证书用defaultGeneratedCert可把默认证书交给 ACME 解析器签发且其优先级高于解析器自身的 ACME 默认证书。证书匹配以证书实体的 CN/DNS SAN/IP SAN 为准支持单层*通配与浏览器通配约定一致。如需深入自动化签发与校验体系可继续阅读 ACME 解析器文档及 TLS 选项相关章节完整源码可回溯 pkg/tls/tls.go、pkg/tls/certificate.go、pkg/tls/certificate_store.go 与 pkg/tls/tlsmanager.go。【免费下载链接】traefikThe Cloud Native Application Proxy项目地址: https://gitcode.com/GitHub_Trending/tr/traefik创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考