3. Kong 网关 TLS 架构:证书存储、SNI 与监听器配置

Kong 网关作为南北向流量的统一入口,其 TLS 架构直接决定了 HTTPS 服务的可用性、安全性与性能。本章深入剖析 Kong 的证书存储机制、SNI(服务器名称指示)工作原理以及监听器配置策略,帮助你在升级窗口内精准完成证书更新并优化 TLS 握手性能。

3.1 证书存储机制:从数据库到内存的路径

Kong 将 TLS 证书与私钥存储在自身的数据库中(PostgreSQL 或 Cassandra),而非依赖操作系统或外部密钥管理服务(KMS)。这种设计使得证书管理完全融入 Kong 的声明式配置体系,支持通过 Admin API、Konga 或声明式配置文件(declarative config)进行统一管理。

3.1.1 核心数据模型

实体 字段 说明
Certificate cert(PEM 格式证书链) 包含服务器证书及中间 CA 证书,按顺序拼接
key(PEM 格式私钥) RSA/ECDSA 私钥,Kong 不会以明文形式暴露
tags 用于分组和过滤,方便批量操作
SNI name(域名) 如 api.example.com,支持通配符 *.example.com
certificate(外键) 关联到具体的 Certificate 实体
最佳实践:证书更新时,建议创建新的 Certificate 实体(新 ID),再更新 SNI 的 certificate 引用。这种方式可以避免在更新过程中出现证书与私钥不匹配的窗口期,且支持快速回滚。

3.1.2 证书加载与缓存机制

Kong 在启动时或接收到 Admin API 的证书变更通知后,会执行以下流程:

  1. 数据库查询:从 certificates 和 snis 表中加载所有有效记录。
  2. PEM 解析:验证证书链完整性、私钥匹配性及有效期。
  3. 内存缓存:将解析后的 SSL_CTX 对象存入共享内存(LMDB 或 shm),供所有 Worker 进程使用。
  4. 热更新:通过 POST /certificates 或 PATCH /snis 触发时,Kong 仅更新变更的 SSL_CTX,无需 reload 整个进程。
注意:如果使用声明式配置文件(kong.yml)进行证书更新,必须确保配置文件的 _format_version 正确,且证书内容经过 Base64 编码(当使用 cert 和 key 字段时)。错误的格式会导致 Kong 解析失败,进而影响 TLS 握手。

3.2 SNI 工作原理:多域名 TLS 的核心

SNI(服务器名称指示)是 TLS 协议的扩展,允许客户端在握手阶段(ClientHello)携带目标域名,服务端据此选择对应的证书进行响应。Kong 利用 SNI 实现单 IP 多证书的虚拟托管。

3.2.1 SNI 匹配流程

SNI 匹配与证书选择流程 客户端 ClientHello (SNI: api.example.com) Kong 网关 SNI 匹配引擎 证书存储 匹配结果 返回匹配证书 返回默认证书 / 拒绝 匹配优先级 1. 精确域名匹配 2. 通配符匹配 3. 默认 SNI 回退

3.2.2 通配符与默认 SNI

  • 精确匹配:api.example.com 完全匹配 SNI 记录。
  • 通配符匹配:*.example.com 可匹配 sub1.example.com、sub2.example.com,但不匹配 example.com 本身。
  • 默认 SNI:当客户端未携带 SNI 或所有匹配失败时,Kong 使用 default 标签的 SNI 对应的证书。建议始终配置一个默认 SNI,避免 TLS 握手失败。
性能要点:SNI 匹配发生在 TLS 握手阶段,属于 CPU 密集型操作。当证书数量超过 1000 个时,建议启用 Kong 的 ssl_cert_cache_ttl 参数(默认 3600 秒),减少数据库查询频率。同时,使用 ECDSA 证书而非 RSA 证书可以降低握手时的计算开销。

3.3 监听器配置:代理与 Admin 分离

Kong 的监听器配置决定了网关如何暴露 TLS 端口。合理的监听器配置不仅能提升安全性,还能通过端口分离实现性能隔离。

3.3.1 核心监听器参数

参数 默认值 说明
proxy_listen 0.0.0.0:8000, 0.0.0.0:8443 ssl 代理端口,ssl 标记启用 TLS
admin_listen 127.0.0.1:8001, 127.0.0.1:8444 ssl Admin API 端口,建议仅监听本地回环地址
stream_listen off TCP/UDP 流式监听,支持 TLS 透传

3.3.2 生产环境推荐配置

# kong.conf 片段
proxy_listen = 0.0.0.0:443 ssl, 0.0.0.0:80
admin_listen = 127.0.0.1:8001, 127.0.0.1:8444 ssl
stream_listen = 0.0.0.0:8443 ssl

# TLS 优化参数
ssl_cert_cache_ttl = 3600
ssl_cipher_suite = modern
ssl_protocols = TLSv1.2 TLSv1.3
ssl_prefer_server_ciphers = on
ssl_session_cache_size = 50m
ssl_session_timeout = 5m
安全警告:切勿将 Admin API 监听在公网 IP 上(如 0.0.0.0:8444)。Admin API 拥有完全控制权,暴露在公网将导致严重安全风险。始终使用 127.0.0.1 或内网 IP,并配合防火墙规则。

3.3.3 多端口监听与性能隔离

Kong 支持在同一进程中监听多个端口,每个端口可以独立配置 TLS 参数。这种设计允许你将不同安全等级的流量隔离到不同端口:

  • 443 端口:面向公网的 HTTPS 流量,启用完整 TLS 验证。
  • 8443 端口:内部微服务通信,使用 mTLS(双向 TLS)进行身份验证。
  • 8445 端口:仅用于证书更新后的验证测试,绑定内网 IP,不对外暴露。

3.4 证书更新与 TLS 性能优化策略

3.4.1 零停机证书更新流程

  1. 预创建新证书:通过 Admin API 创建新的 Certificate 实体,包含新证书链和私钥。
  2. 更新 SNI 引用:将目标 SNI 的 certificate 字段指向新证书的 ID。
  3. 验证生效:使用 openssl s_client -connect yourdomain:443 -servername yourdomain 验证新证书是否生效。
  4. 清理旧证书:确认新证书正常工作后,删除旧的 Certificate 实体。

3.4.2 TLS 握手性能优化清单

优化项 操作 预期效果
会话复用 启用 ssl_session_cache 并设置合理大小 减少重复握手,降低延迟 30%-50%
OCSP Stapling 配置 ssl_ocsp 为 on 客户端无需单独查询 OCSP 响应,提升握手速度
HSTS 预加载 在响应头添加 Strict-Transport-Security 强制客户端使用 HTTPS,减少重定向开销
证书链优化 移除根证书,仅保留服务器证书 + 中间 CA 减少握手数据量,降低带宽消耗
TLS 1.3 优先 设置 ssl_protocols = TLSv1.2 TLSv1.3 TLS 1.3 握手仅需 1-RTT,比 TLS 1.2 快 33%
升级窗口建议:在证书更新前,先通过 Kong 的 /schemas/certificates 端点验证新证书的格式是否正确。使用 curl -X POST http://localhost:8001/certificates -F "cert=@new_cert.pem" -F "key=@new_key.pem" 进行测试,避免因证书格式错误导致生产故障。