如何强制所有客户端使用 TLS 1.3?

解读

面试官抛出“强制 TLS 1.3”这一问,表面看是考察协议细节,实质想验证候选人是否真正理解 Cloud SQL 的“全托管边界”与“安全责任共担模型”。国内金融、政企客户去 GCP 立项时,等保 2.0 与关基条例都要求“传输加密最低 TLS 1.2,建议 1.3”,因此能否给出合规、可落地的方案,直接决定项目能否过审。答题时必须区分“Cloud SQL 实例侧能控制什么”与“客户端侧必须配合什么”,并给出可白盒审计的闭环证据,否则会被认为“纸上谈兵”。

知识点

  1. Cloud SQL 服务端 TLS 策略:由 Google 全局负载均衡层统一协商,实例本身无法指定仅 TLS 1.3,最低版本由平台侧滚动升级,用户只能“建议”不能“强制”。
  2. 连接路径差异:
    • Public IP:走 Google Front End(GFE),TLS 版本由 GFE 与客户端协商,Cloud SQL 实例无感知。
    • Private IP:通过 VPC-SC 或 Private Service Connect,仍由 GFE 终结 TLS,实例侧同样不可调。
  3. 客户端可验证的“证据链”:
    • serverCertificateCert 字段在 SSL 握手时可被应用代码读取,结合 openssl s_clientgsutil 拉取 Google 根证书链,可二次校验“仅 1.3 成功、1.2 失败”。
  4. 国内合规常用“反向强制”思路:在云原生七层入口(Cloud Armor + HTTPS 负载均衡)或 Istio Ingress Gateway 统一设置 minTlsVersion: TLS_1_3,把 Cloud SQL 包进内网,仅暴露该入口,实现“客户端侧不可绕过”。
  5. Terraform 模板中需显式关闭 require_ssl = false 的误解:该字段仅控制“是否允许非 SSL”,并不限制 TLS 版本;真正版本过滤需靠外层代理或代码层校验。

答案

“Cloud SQL 实例本身无法直接强制 TLS 1.3,因为 TLS 协商发生在 Google Front End,平台侧目前开放给用户的只有‘require_ssl’开关,没有‘min_tls_version’参数。
在国内落地时,我们采用‘双层强制’方案:

  1. 外层:用** Google Cloud Armor 关联全球 HTTPS 负载均衡**,在自定义规则里写入 tlsVersion() != 'TLSv1.3' ? deny() : allow(),把 Cloud SQL 的 Public IP 完全关闭,只暴露该负载均衡入口;
  2. 内层:所有业务 Pod 通过** Cloud SQL Auth Proxy 的 Private IP 通道**接入,Proxy 侧启动参数加 --require-tls,并在应用代码里用 database/sql 驱动拿到 tls.Config,显式设置 MinVersion: tls.VersionTLS13,若握手失败直接抛错,形成代码层兜底;
  3. 审计:每周用 nmap --script ssl-enum-ciphers -p 3306 扫一次代理入口,结合 Cloud Logging 导出 ssl_version 标签到 BigQuery,发现非 1.3 连接立即触发云函数告警。
    该方案已通过央行某清算机构 POC,满足等保 2.0 四级‘传输加密不可降级’条款。”

拓展思考

如果后续 Google 在 cloud_sql_flags 里新增 tls_version_min 参数,仍需评估“灰度升级”对存量连接的影响——国内很多老旧 JDBC 驱动(如 5.1.x)默认不带 TLS 1.3 套件,强制升级会导致业务中断。因此面试时可以补充:“我会先通过** Traffic Director 把 1% 流量镜像到新策略桶**,用 Cloud Monitoring 观测 database/mysql/error_count 指标,确认无 ERROR 2026 (SSL connection error) 后再全量切流,实现业务无感强制。” 这样体现出“可灰度、可回滚”的云原生运维思维,比单纯背参数更能打动面试官。