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。对 HTTPRouteGRPCRoute 以及 TLSRoute(在 Terminate 模式下)来说,使用 BackendTLSPolicy开启了"在 Gateway 处终止、再重新加密"的连接模式。

TLSRouteTerminate 模式在 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.combar.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 证书包,用作校验客户端证书的信任锚
  • 其他选项opt1opt2)也可以视情况使用。
  • 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 包含 TargetRefsValidation 两部分。TargetRefs必填的,它指明你的 HTTPRoute 需要为哪些 Service 启用 TLS。Validation 配置包含一个必填Hostname以及 CACertificateRefsWellKnownCACertificates 二选一。

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 协议发布