跳转到主要内容

Go 1.27 TLS 默认值与 OIDC Discovery 故障形态

SILO 工具链迁移到 Go 1.27 后,Server TLS 修复 48e184652 (“fix(tls): honor Go key exchange defaults across transports”)移除了显式曲线覆盖。本文记录 TLS 层的变化、issue #154 调查中形成的按阶段诊断方法,以及管理员在身份系统启动即失踪时需要的事实。

发布边界,截至 2026-09-16: Server 20260903 已使用 Go 1.27.1,但不包含 48e184652;后者是 main 上的后续 TLS 修复。升级编译器与采纳该修复是两项不同变更。

先声明证据类别。 以下每个机制都经合成实验验证:ClientHello 抓取、新鲜进程 CA 探针、夹具复现。#154 客户的 discovery URL 与入口配置始终未获得,因此不对该部署做任何根因断言——两个本地已验证的机制都能产生所报症状:入口拒绝新握手,或代理拒绝变更后的 User-Agent,均有可能。#154 保持打开,等待受影响环境复测。

Go 1.27 改变了什么

  • 显式曲线偏好现在会压过 ML-KEM 兼容开关。 GODEBUG=tlsmlkem=0 从默认集合移除全部 ML-KEM 混合方案;tlssecpmlkem=0 只移除 Go 1.26 新增的 P-256/P-384 混合,仍保留 X25519MLKEM768。显式配置 CurvePreferences 的应用会在它给出的列表里保留 ML-KEM——这是 Go 1.27 的有意变更。SILO Server 有 8 个 TLS 配置点显式设置了含 X25519MLKEM768 的列表;修复移除这 8 处赋值并退役该 helper,使这些配置点遵循 Go 默认值,兼容开关重新生效。栈评审确认 pkg、mcli 和 Console 客户端原本已使用默认值;Console HTTPS 监听器保留单独的 P-256 策略。
  • ClientHello 新增 ML-DSA 签名算法编号0x09040x0906)。ML-DSA 是签名方案,与 ML-KEM 不同:禁用混合密钥交换不会禁用 ML-DSA offer,拒绝 ML-DSA 的入口不会被任何 ML-KEM 开关修复。
  • ClientHello 变大。 同源码同依赖实测:Go 1.26.5 默认 1497 字节;Go 1.27.1 默认 1509 字节;tlsmlkem=0 下的旧显式列表产生 275 字节、无 ML-KEM 的 hello,而 Go 1.27.1 加显式列表仍产生含 ML-KEM 的 1509 字节。仅更换编译器就改变了握手。
  • macOS 根 CA 行为随模块 go 指令翻转。 新鲜进程是遵循 SSL_CERT_FILE/SSL_CERT_DIR 还是 Keychain,由 x509sslcertoverrideplatform GODEBUG 默认值决定,而它跟随主模块的 go 指令:go 1.26 模块在 macOS 上忽略这两个变量(平台库优先),go 1.27 模块遵循——且以消费应用的指令为准,库模块更旧也不妨碍新行为。macOS 上的运维者应知道:设置任一变量都会用给定文件/目录整体替换 Keychain 信任;过期或不完整的路径会破坏 Keychain 本可接受的链,取消设置即可恢复。
  • 并非一切都变了。 TLS 版本、密码套件、证书与主机名校验、代理处理、HTTP/2 选择均不受影响。标准库 drain 上限(256 KiB / 50 ms)等已审计的 Go 1.27 变更无 SILO 依赖。Go 1.27 二进制要求 macOS 13 或更新。降级不受支持:模块图在 Server、Console、mc 三处都要求 Go ≥ 1.27.1。

为什么撤回了 OIDC 专用补丁

调查最初产出一个最小候选:只在 OIDC discovery transport 上清空 CurvePreferences。该候选没有发布。同一个 transport 还服务于身份插件、通知与 lambda 连通性检查、审计 webhook、S3 云后端分层——只修两个 OIDC 调用点会让其余消费者继续留在有缺陷的显式列表上。合并后的修复在这 8 个 Server 配置点移除显式曲线,使兼容开关在这些位置生效,保持证书校验严格,不加协议降级或自动回退。归档的单 transport 补丁不得再叠加到已合并修复之上。

按阶段诊断 discovery 故障

启动链是:服务器启动 → 身份系统初始化 → 抓取 .well-known/openid-configuration(discovery)→ 抓取 jwks_uri 密钥 → IAM 就绪 → Console 初始化。Console 自身的 OIDC 配置对话框经同一服务端 transport 校验。链条任何一环失败都会使 IAM 离线;discovery 成功不代表 JWKS 抓取成功,JWKS 503 与 discovery 失败一样阻塞 IAM。

按连接死在哪一层区分:

  • TLS ClientHello 之后立即 resettls_start 后 reset):怀疑入口的 ClientHello 处理——代理 CONNECT 规则、TLS 终止器、任何按键大小或内容匹配的逻辑。Go 1.27 的变化都落在这一层。
  • TLS 完成后 resetwrote_request 后 reset):TLS 层没问题;查 HTTP 层策略——WAF 规则、User-Agent 白名单(服务器 UA 已随 rebrand 从 MinIO 变为 Silo)、路由。此时换证书或换密钥交换没有针对性效果。
  • x509 错误:对比实际收到的链、SNI、以及进程解析到的信任库(见上文 macOS 一节)。
  • 务必从与故障进程相同的网络位置测试——新起容器不会继承故障容器的网络命名空间;同 IP、同代理的对照先行。

说真话的健康端点

IAM 离线期间,/minio/health/live/minio/health/ready 都保持 200——现有就绪检查不覆盖身份系统。真正报告它的是 /minio/health/cluster:它检查身份初始化,返回 503 并携带 X-Minio-Server-Status: iam-offline 标记。要捕捉 IdP 集成断裂的监控应探测 cluster health,外加一次已认证操作。

恢复是自动的:身份初始化以随机 0–3 秒间隔重试,IdP 恢复后 IAM 无需重启即回来(本地观测从亚秒到约 1.4 秒)。重试不能修复持续性不兼容——入口拒绝的 hello 会一直拒绝。

值得知道的 transport 事实

discovery/JWKS 客户端自建 transport:禁用 HTTP/2(无 ALPN、HTTP/1.1)、代理只取 HTTPS_PROXY/NO_PROXY(大写优先;不用 ALL_PROXY)、默认在 Kubernetes/Docker 中使用 30 秒 DNS 刷新、其它环境使用 10 分钟(可由 DNS cache TTL 设置覆盖)、拨号按序遍历地址不做 shuffle、超时为每次 TCP 拨号 5 秒、TLS 握手 10 秒、响应头 1 分钟。discovery 或 JWKS 抓取本身没有总超时——缓慢的 IdP 可以无限期拖住启动;收紧它是已评估过工作量的独立后续项。

归属

本文提炼自 issue #154 调查与九月的 Go 1.27 工具链栈评审;复现工件与完整证据链保留在文档树之外。可支持的表述是:合并后的修复在受影响的 8 个 Server 配置点恢复 Go 密钥交换默认值,并经合成负对照验证——它不声称诊断了任何特定隐藏部署,#154 在受影响环境复测前保持打开。

Go 行为以官方 1.27 发布说明及实际工具链为准。本文的 ClientHello 字节数属于所述夹具测量,不是所有连接的固定大小。