Skip to content

TLS 配置 ​

原文:https://gateway-api.sigs.k8s.io/guides/user-guides/tls/

Gateway API 提供了多种配置 TLS 的方式。本文档详细列出了各种 TLS 设置,并给出通用的指导原则,帮你高效地使用它们。

尽管本文覆盖了使用 Gateway API 进行 TLS 配置的最常见形式,部分实现也会提供实现特有的扩展,允许你以不同或更高级的方式配置 TLS。除了本文档之外,也值得读一下你所用的 Gateway API 实现自身关于 TLS 的文档。

客户端/服务端与 TLS ​

对 Gateway 来说,有两条连接:

  • downstream(下游):客户端与 Gateway 之间的连接。
  • upstream(上游):Gateway 与 Route 指定的后端资源之间的连接。这些后端资源通常是 Service。

在 Gateway API 中,downstream 和 upstream 连接的 TLS 配置是相互独立的。

对于 downstream 连接,根据 Listener 协议的不同,支持的 TLS 模式和 Route 类型也不同。

Listener ProtocolTLS ModeRoute Type Supported
TLSPassthroughTLSRoute
TLSTerminateTLSRoute(扩展)
HTTPSTerminateHTTPRoute
GRPCTerminateGRPCRoute

在 Passthrough TLS 模式下,TLS 设置不生效——因为客户端发起的 TLS 会话不会在 Gateway 终止,而是加密地透传过 Gateway。

对于 upstream 连接,使用的是 BackendTLSPolicy;此时 listener 协议和 TLS 模式都不适用于 upstream TLS 配置。BackendTLSPolicy 是一个 Union Feature,这意味着它适用于任何把流量转发到后端的 Route 或 filter。对 HTTPRoute、GRPCRoute 以及 TLSRoute(在 Terminate 模式下)来说,使用 BackendTLSPolicy 就开启了"在 Gateway 处终止、再重新加密"的连接模式。

TLSRoute 的 Terminate 模式在 Extended Support Level 下提供。

Downstream TLS ​

Downstream TLS 设置通过 Gateway 层级的 listener 来配置。

Listeners 与 TLS ​

Listener 按 domain 或 subdomain 维度暴露 TLS 设置。Listener 的 TLS 设置会作用于所有满足 hostname 匹配条件的域名。

在下面这个示例中,Gateway 为所有请求提供 default-cert Secret 中定义的 TLS 证书。尽管该示例引用的是 HTTPS 协议,同样可以把这一特性用于纯 TLS 协议 + TLSRoute 的组合。

yaml
listeners:
- protocol: HTTPS # 另一个可能的取值是 `TLS`
  port: 443
  tls:
    mode: Terminate # 如果 protocol 是 `TLS`,另一个可能的取值是 `Passthrough`
    certificateRefs:
    - kind: Secret
      group: ""
      name: default-cert

示例 ​

携带不同证书的 Listeners ​

下面这个示例中,Gateway 被配置为同时服务 foo.example.com 和 bar.example.com 两个域名。它们的证书都在 Gateway 中指定。

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: tls-basic
spec:
  gatewayClassName: example
  listeners:
  - name: foo-https
    protocol: HTTPS
    port: 443
    hostname: foo.example.com
    tls:
      certificateRefs:
      - kind: Secret
        group: ""
        name: foo-example-com-cert
  - name: bar-https
    protocol: HTTPS
    port: 443
    hostname: bar.example.com
    tls:
      certificateRefs:
      - kind: Secret
        group: ""
        name: bar-example-com-cert

通配符 TLS Listeners ​

在下面这个示例中,Gateway 为 *.example.com 配置了通配符证书,并同时为 foo.example.com 配置了一张独立的证书。由于"更具体的匹配会优先",Gateway 会对**foo.example.com 的请求使用 foo-example-com-cert,对其它**请求使用 wildcard-example-com-cert。

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: wildcard-tls-gateway
spec:
  gatewayClassName: example
  listeners:
  - name: foo-https
    protocol: HTTPS
    port: 443
    hostname: foo.example.com
    tls:
      certificateRefs:
      - kind: Secret
        group: ""
        name: foo-example-com-cert
  - name: wildcard-https
    protocol: HTTPS
    port: 443
    hostname: "*.example.com"
    tls:
      certificateRefs:
      - kind: Secret
        group: ""
        name: wildcard-example-com-cert

跨命名空间的证书引用 ​

下面这个示例中,Gateway 引用了另一个命名空间下的证书。这种引用是被允许的,前提是目标命名空间中创建了对应的 ReferenceGrant。没有 ReferenceGrant 的话,跨命名空间引用会无效。

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: cross-namespace-tls-gateway
  namespace: gateway-api-example-ns1
spec:
  gatewayClassName: example
  listeners:
  - name: https
    protocol: HTTPS
    port: 443
    hostname: "*.example.com"
    tls:
      certificateRefs:
      - kind: Secret
        group: ""
        name: wildcard-example-com-cert
        namespace: gateway-api-example-ns2
---
apiVersion: gateway.networking.k8s.io/v1
kind: ReferenceGrant
metadata:
  name: allow-ns1-gateways-to-ref-secrets
  namespace: gateway-api-example-ns2
spec:
  from:
  - group: gateway.networking.k8s.io
    kind: Gateway
    namespace: gateway-api-example-ns1
  to:
  - group: ""
    kind: Secret

客户端证书校验(Frontend mTLS) ​

Gateway API 支持在 TLS 握手阶段校验前端客户端出示的 TLS 证书。

与"server 证书"按 listener 配置不同,客户端证书校验是在 spec.tls 字段的 Gateway 级别进行配置。这种设计专门用来降低 HTTP/2 与 TLS connection coalescing 带来的安全风险——在那种场景下,原本为一个 listener 建立的连接可能被同端口上的另一个 listener 复用,从而绕过 listener 级别的校验设置。

配置概览 ​

客户端校验通过 frontendValidation 结构体定义,指明 Gateway 应如何校验客户端的身份。

  • caCertificateRefs:Kubernetes 对象的引用列表(通常是 ConfigMap),其中保存 PEM 编码的 CA 证书包,用作校验客户端证书的信任锚。
  • 其他选项(opt1、opt2)也可以视情况使用。
  • clientValidationMode:客户端证书校验的模式:
    • AllowValidOnly(默认):只有当客户端出示了一张通过指定 CA 校验的有效证书时,Gateway 才接受该连接。
    • AllowInsecureFallback:即使客户端证书缺失或校验失败,Gateway 也接受该连接。这种模式通常会把授权决策委托给后端,因此需要慎用。

Gateway 级别作用域 ​

校验既可以对 Gateway 全局应用,也可以针对特定端口覆盖:

  1. 默认配置:除非在端口上有单独覆盖,否则该配置作用于 Gateway 上的所有 HTTPS listener。
  2. 按端口配置:允许做细粒度控制,对特定端口上所有 listener 的默认配置进行覆盖。

上述两种作用域可以组合使用,达到"全局基线 + 端口特例"的灵活效果。

示例 ​

基础客户端校验 ​

下面这个示例展示如何配置客户端证书校验(含默认配置 + 端口级覆盖):

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: client-validation-basic
spec:
  gatewayClassName: acme-lb
  tls:
    frontend:
      default:
        validation:
          caCertificateRefs:
          - kind: ConfigMap
            group: ""
            name: foo-example-com-ca-cert
      perPort:
      - port: 8443
        tls:
          validation:
            caCertificateRefs:
            - kind: ConfigMap
              group: ""
              name: bar-example-com-ca-cert
  listeners:
  - name: foo-https
    protocol: HTTPS
    port: 443
    hostname: foo.example.com
    tls:
      certificateRefs:
      - kind: Secret
        group: ""
        name: foo-example-com-cert
  - name: bar-https
    protocol: HTTPS
    port: 8443
    hostname: bar.example.com
    tls:
      certificateRefs:
      - kind: Secret
        group: ""
        name: bar-example-com-cert

Upstream TLS ​

Upstream TLS 设置通过 BackendTLSPolicy 来配置,它通过 target reference 挂到 Service 上。

这个资源可以用于描述:Gateway 应使用哪个 SNI 来连接后端,以及应如何校验后端 Pod 所出示的证书。

TargetRefs 与 TLS ​

BackendTLSPolicy 包含 TargetRefs 与 Validation 两部分。TargetRefs 是必填的,它指明你的 HTTPRoute 需要为哪些 Service 启用 TLS。Validation 配置包含一个必填的 Hostname,以及 CACertificateRefs 或 WellKnownCACertificates 二选一。

Hostname 指 Gateway 连接后端时应使用的 SNI,必须与后端 Pod 所出示的证书匹配。

CACertificateRefs 指一张或多张 PEM 编码的 TLS 证书。如果没有指定要使用哪张证书,就必须把 WellKnownCACertificates 设为 "System",以告知 Gateway 使用系统级的 CA 信任证书集合。不同实现所使用的"系统证书"集合可能略有不同,请参考你所选实现的文档了解详情。

INFO

限制 ​

  • 不允许跨命名空间证书引用。
  • 不允许通配符 hostname。

示例 ​

使用系统证书 ​

下面这个示例中,BackendTLSPolicy 被配置为使用系统证书来建立 TLS 加密的上游连接,期望为 dev Service 提供 Pod 后端服务的证书能对 dev.example.com 有效:

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: BackendTLSPolicy
metadata:
  name: tls-upstream-dev
spec:
  targetRefs:
    - kind: Service
      name: dev
      group: ""
  validation:
    wellKnownCACertificates: "System"
    hostname: dev.example.com

使用显式 CA 证书 ​

下面这个示例中,BackendTLSPolicy 被配置为使用 auth-cert ConfigMap 中定义的证书,来建立 TLS 加密的上游连接,期望为 auth Service 提供 Pod 后端服务的证书能对 auth.example.com 有效:

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: BackendTLSPolicy
metadata:
  name: tls-upstream-auth
spec:
  targetRefs:
    - kind: Service
      name: auth
      group: ""
  validation:
    caCertificateRefs:
      - kind: ConfigMap
        name: auth-cert
        group: ""
    hostname: auth.example.com

Gateway 的证书选择(Backend mTLS) ​

对 upstream 连接做 mTLS 时,除了要校验后端的证书之外,Gateway 还需要出示一张客户端证书给后端。这能保证后端只接受来自被授权 Gateway 的连接。

Gateway 客户端证书配置 ​

要配置 Gateway 连接后端时所使用的客户端证书,请在 Gateway 资源的 tls.backend.clientCertificateRef 字段中指定。

这一配置对该 Gateway 作为客户端发起的所有 upstream 连接都生效。

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: backend-tls
spec:
  gatewayClassName: acme-lb
  tls:
    backend:
      clientCertificateRef:
        kind: Secret
        group: ""
        name: foo-example-cert
  listeners:
  - name: foo-http
    protocol: HTTP
    port: 80
    hostname: foo.example.com

扩展 ​

Gateway 的 TLS 配置提供了一个 options 字段,可以补充实现特有的 TLS 设置。可以填进这里的特性例子包括:TLS 版本限制、可用的密码套件等。

基于 MIT 协议发布