分布式数据库一旦跨节点通信不加密,等于把整个数据库的内脏暴露在网络上。任何一个能接触到交换机镜像端口的人,都能直接看到 SQL 语句、查询结果、甚至用户凭据。这不是理论风险,而是每天都在发生的横向移动攻击场景。解决这个问题不是简单“开启TLS”就完事,证书管理、性能损耗、协议兼容、密钥轮换,每一个环节处理不好都会变成生产事故。
节点间通信到底暴露了什么先搞清楚威胁面。分布式数据库节点间通信主要包括几类流量:Gossip 协议的心跳和元数据同步、数据分片在不同节点间的复制和再平衡、客户端请求被协调节点转发到数据节点、以及跨数据中心的双活同步。这些流量如果不加密,攻击者可以被动嗅探出完整的表结构、查询模式、写入热点,甚至直接注入伪造的节点下线消息,触发集群脑裂。更隐蔽的风险是元数据泄露,比如 TiDB 的 PD 组件、CockroachDB 的 Range Lease 信息,一旦被劫持,攻击者可以精确重定向流量。
TLS 双向认证是基线,不是可选项很多人以为节点间通信加密就是服务端开启 TLS,客户端验证证书。这在分布式数据库里远远不够。节点之间是平等的,没有固定的服务端和客户端角色,所以必须做双向 TLS,也就是 mTLS。每个节点都要有自己的证书和私钥,同时要配置信任的 CA 链。以 CockroachDB 为例,启动时必须指定 --certs-dir 参数,里面包含 ca.crt、node.crt、node.key 三个文件,缺任何一个都会导致节点无法加入集群。TiDB 的 TiKV 和 PD 之间同样要求配置 security.ssl-ca、security.ssl-cert、security.ssl-key 三组路径。这里有个容易踩的坑:证书的 Common Name 必须与节点的主机名或内部通信 IP 严格匹配,否则 mTLS 握手阶段就会失败,错误日志往往是 x509: certificate is valid for xxx, not yyy,排查起来非常耗时。
mTLS 配置好只是第一步,证书过期才是真正的噩梦。分布式数据库节点数量动辄几十上百,手动轮换证书根本不可行。业界成熟的方案是引入内部 CA 和自动化证书管理工具。Hashicorp Vault 的 PKI 引擎可以签发短期证书,通过 vault agent 自动续期并重载数据库进程。但这里有一个关键细节:数据库进程是否支持证书热加载。CockroachDB 从 v21.1 开始支持 SIGHUP 信号重载证书,不需要重启进程。TiDB 则需要通过 reload-cert 接口或滚动重启来实现。如果你的数据库不支持热加载,那证书有效期就不能设得太短,否则频繁重启会严重影响集群稳定性。建议生产环境证书有效期控制在 30 到 90 天之间,配合监控告警在到期前 15 天触发自动化轮换流程。
加密不是免费的。TLS 握手有 CPU 开销,对称加密对吞吐也有影响。根据实际压测数据,在万兆网络环境下,开启 mTLS 后 TiKV 的 RawKV 写入吞吐下降约 8% 到 12%,P99 延迟增加 2 到 5 毫秒。这个损耗主要来自两方面:一是 TLS 握手阶段的非对称加密运算,二是 AES-GCM 加密对 CPU 的持续消耗。优化手段包括:使用支持 AES-NI 指令集的 CPU,这几乎是现代 x86 服务器的标配,但需要确认数据库编译时是否开启了相关优化;选择更高效的加密套件,比如 ECDHE-ECDSA-AES128-GCM-SHA256 比 RSA-AES256-GCM-SHA384 快 30% 以上;启用会话复用,减少完整握手次数。CockroachDB 和 ScyllaDB 都支持 TLS 会话票据,可以在 --ssl-enable-session-tickets 参数中开启。
如果集群节点分布在同一个 VPC 内,网络层面已经有 VPC 隔离,很多人会犹豫要不要再加一层应用层加密。答案是必须加。VPC 隔离防不了内部威胁,也防不了云平台自身的运维人员误操作。但跨数据中心的情况更复杂,因为流量会经过公网或专线。专线本身不加密,运营商可以在物理层做镜像。所以跨数据中心通信必须做双层加密:底层用 IPsec 或 WireGuard 建立加密隧道,上层仍然保持 mTLS。这样即使隧道被意外关闭或配置错误,应用层加密仍然有效。具体配置上,WireGuard 比 IPsec 性能更好,配置也更简单,在节点初始化脚本中加入 wg-quick up wg0 即可,但要确保 WireGuard 的 MTU 设置正确,避免 TCP 分片导致性能骤降。
不同数据库的加密配置差异很大,逐个说明。CockroachDB 的证书模式比较严格,集群初始化时就必须指定 --certs-dir,后续添加节点也必须使用同一 CA 签发的证书。如果证书过期,节点会直接退出集群,不会降级为明文通信,这个设计是安全的但运维压力大。TiDB 相对灵活,可以在配置文件中通过 security 段逐组件开启,而且支持在线修改后通过 reload 接口生效。ScyllaDB 使用 server_encryption_options 和 client_encryption_options 两套配置分别控制节点间和客户端通信,支持选择性地对特定数据中心开启加密,这个功能在多活架构中非常实用。MongoDB 的副本集内部通信通过 net.tls.mode 设置为 requireTLS,同时需要配置 net.tls.clusterFile 指定节点间通信专用的证书,可以与客户端证书分开。
私钥存储是另一个容易被忽略的薄弱点。节点上的 node.key 文件如果以明文存储在磁盘上,任何有文件系统读取权限的进程都能窃取。生产环境应该把私钥存储在硬件安全模块或者至少是内核级的密钥管理服务中。CockroachDB 企业版支持通过 PKCS#11 接口对接 HSM,配置参数 --enterprise-encryption 可以指定密钥存储后端。开源方案可以用 Linux 内核的 keyctl 配合 systemd-creds 来管理私钥,确保私钥不会以明文落盘。更轻量的做法是使用 tmpfs 挂载私钥目录,节点启动后由运维脚本注入私钥,进程读取后立即卸载,但这要求进程不能将私钥 swap 到磁盘,需要配合 mlockall 系统调用锁定内存。
加密配置完成后,必须建立持续的监控体系。证书过期监控是最基本的,Prometheus 的 ssl_certificate_expiry exporter 可以定时检查各节点的证书有效期。更关键的是 TLS 版本和加密套件的监控,防止因为配置漂移导致某些节点回退到低版本 TLS 或不安全的加密套件。可以在网络层部署 Zeek 或 Suricata 做旁路分析,检测是否有明文数据库协议流量出现在网段内。审计方面,数据库自身的审计日志应该记录每次 TLS 握手失败事件,包括源 IP、证书指纹、失败原因,这些数据是事后溯源的关键。如果发现某个节点频繁出现证书验证失败,很可能是横向移动的前兆。
节点间通信加密不是一次性配置项,而是一个需要持续运营的安全能力。证书轮换自动化、性能基线监控、加密套件生命周期管理,这三件事缺一不可。安全团队和 DBA 需要共同维护一份加密配置基线文档,每次数据库版本升级前都要重新验证加密相关参数是否兼容。真正把节点间通信加密做到位的团队,往往不是安全预算最高的,而是把这件事融入日常运维流程的团队。
