全链路加密需覆盖服务通信、配置加载、日志脱敏、数据落盘四环节;禁用insecureskipverify,启用双向tls;bbolt落盘须aead加密+kms密钥;envoy管传输层,go管业务层加密;日志须结构化脱敏。

Go 云原生场景下,全链路加密不是加个 TLS 就完事——它必须覆盖服务间通信、配置加载、日志脱敏、数据落盘四个关键环节,否则任何一环裸奔都会让加密形同虚设。
为什么 http.Transport 的 TLSClientConfig 常被配错
很多团队只在客户端配了 TLSClientConfig,却忘了服务端默认不校验客户端证书;或者误把 InsecureSkipVerify: true 当成“快速上线方案”,结果整个 mTLS 链路直接降级为明文。
- 生产环境必须禁用
InsecureSkipVerify,改用RootCAs+ClientCAs双向验证 - 证书轮换时,
tls.Config.GetCertificate比重启服务更安全,避免连接中断 - Kubernetes Ingress 或 Service Mesh(如 Istio)接管了 TLS 终止?那应用层就该走纯 HTTP,但必须确认 mesh 控制面已开启 mTLS 策略(
PeerAuthentication+DestinationRule)
go.etcd.io/bbolt 落盘加密要绕开哪些坑
BoltDB 本身不支持透明加密,强行在文件层用 LUKS 或 eCryptfs 会破坏 WAL 日志一致性,导致 page not found 或 panic。
- 正确做法是用
bbolt.Open的Options设置NoFreelistSync: true+ 自行对bucket.Put的 value 做 AEAD 加密(推荐golang.org/x/crypto/chacha20poly1305) - 密钥不能硬编码,应从 KMS(如 AWS KMS / HashiCorp Vault)按需获取,且每次写入用新 nonce
- 注意:加密后 value 长度变长,若原字段有长度校验(如 JSON schema),需同步放宽限制
Envoy Sidecar 和 Go 应用之间,谁该负责请求头加密
Envoy 默认透传所有 header,包括含敏感信息的 X-User-ID 或 X-Auth-Token。如果让 Go 应用自己解密,等于把密钥和逻辑耦合进业务代码;如果全交给 Envoy,又丧失对 payload 内容的细粒度控制。
立即学习“go语言免费学习笔记(深入)”;
- 推荐分层:Envoy 负责 transport 层加密(mTLS),Go 应用负责业务层加密(如用
crypto/aes加密 header 中的 token payload) - Envoy 的
envoy.filters.http.jwt_authn插件可校验 JWT,但别让它解密自定义加密字段——那是业务逻辑,不该由 proxy 承担 - 调试时用
curl -v看到的X-Encrypted-Header是 base64 编码后的密文,不是原始值,别误当成明文日志抓取
日志中 fmt.Printf 和 logrus.Fields 的脱敏差异
用 logrus.WithFields(logrus.Fields{"user_id": u.ID}) 打印,即使字段名是 user_id,只要结构体字段没打 json:"-" 标签,序列化时仍可能泄露;而 fmt.Printf("user_id=%s", u.ID) 如果 u.ID 是明文,就直接上日志了。
- 统一用结构体 +
json.Marshal输出日志前,先遍历字段做redact(比如匹配.*password|.*token|.*key$正则) - 不要依赖 logrus 的
Formatter插件自动脱敏——它只处理最终字符串,对嵌套 map/slice 里的敏感字段无效 - 本地开发用
log.SetFlags(0)关闭时间戳,避免把调试用的临时密钥混进日志路径里
真正难的不是选哪个加密库,而是判断哪一层该由谁加密、密钥生命周期怎么管、以及当 Envoy、Go、K8s Secret、Vault 四方密钥策略不一致时,以谁为准——这些细节不会报错,但会在审计时突然暴露。










