通信加密
通信加密
TimechoDB 可以加密客户端与服务端以及集群节点之间的通信。客户端可通过 Java Session、SessionPool、JDBC、CLI、Python 或 Go 建立加密连接,Pipe 支持加密同步。Client RPC 支持标准 TLS 单向认证和 SSL 双向认证(mTLS);满足 Kona JDK、SM2 双证书和客户端兼容性要求时,也可配置 TLCP 1.1。
本页介绍的功能自 V2.0.11.1 起提供,默认关闭。启用后,客户端和集群节点必须使用与服务端兼容的协议,并信任服务端或节点证书,否则无法建立连接。
1. 功能说明
| 通信场景 | 服务端开关 | 客户端配置 |
|---|---|---|
| 客户端与服务端 DataNode 的 Client RPC 通信 | enable_thrift_ssl | 默认使用单向 TLS:客户端配置协议、TrustStore 及其口令以验证服务端证书。设置 thrift_ssl_client_auth=true 后启用 mTLS,客户端还必须提供其证书和私钥。 |
| ConfigNode、DataNode 等节点间通信 | enable_internal_ssl | 各节点同时配置 KeyStore、TrustStore 和相同的协议策略 |
标准 TLS 可使用兼容的 RSA 或 ECDSA 证书;TLCP 1.1 需要使用符合要求的 SM2 签名证书和加密证书。thrift_ssl_client_auth 仅控制 Client RPC 的客户端证书认证,不影响 REST API 的 client_auth 配置,也不改变节点间通信的认证方式。

2. 协议选择
在 iotdb-system.properties 中使用 ssl_protocol 选择通信协议,默认值为 TLS。
ssl_protocol 值 | 说明 |
|---|---|
TLS | 允许客户端与服务端协商使用 TLS 1.3 或 TLS 1.2。 |
TLSv1.3 | 仅支持 TLS 1.3。 |
TLSv1.2 | 仅支持 TLS 1.2。 |
TLCP | 优先允许使用 TLCP 1.1,同时兼容 TLS 1.3 和 TLS 1.2。该配置不能保证连接最终使用国密协议。 |
TLCPv1.1 | 仅支持 TLCP 1.1。 |
如需确保连接仅使用国密协议,请将服务端和客户端均配置为 TLCPv1.1。使用 TLCP 时,连接可能回退到普通 TLS。
3. 服务端配置
3.1 客户端通信加密
在 DataNode 的 iotdb-system.properties 中启用 Client RPC 通信加密。默认情况下,客户端仅验证服务端证书:
enable_thrift_ssl=true
ssl_protocol=<protocol>
key_store_path=/path/to/server.keystore
key_store_pwd=<key_store_password>如需要求客户端提供证书,在上述基础上启用客户端认证,并配置用于验证客户端证书的 TrustStore:
enable_thrift_ssl=true
thrift_ssl_client_auth=true
ssl_protocol=<protocol>
# 服务端私钥和服务端证书
key_store_path=/path/to/server.keystore
key_store_pwd=<key_store_password>
# 信任客户端证书或签发客户端证书的 CA
trust_store_path=/path/to/server.truststore
trust_store_pwd=<trust_store_password>完成配置后重启 DataNode。启用后,通过 dn_rpc_port 访问该 DataNode 的客户端必须开启 SSL,否则无法建立连接。
当 thrift_ssl_client_auth=false(默认值)时,行为与历史版本一致,客户端只需配置 TrustStore 来验证服务端证书。当 thrift_ssl_client_auth=true 时,服务端在 TLS 握手中要求客户端提供证书;客户端未提供证书、证书不受服务端 TrustStore 信任,或证书与私钥不匹配时,连接不可用。
thrift_ssl_client_auth 仅在 enable_thrift_ssl=true 时生效。它不复用 REST API 的 client_auth,因此修改其中任一开关不会影响另一种协议。
3.2 节点间通信加密
在所有参与集群内部通信的节点上配置:
enable_internal_ssl=true
ssl_protocol=<protocol>
key_store_path=/path/to/node.keystore
key_store_pwd=<key_store_password>
trust_store_path=/path/to/cluster.truststore
trust_store_pwd=<trust_store_password>集群节点之间需要相互建立连接,因此每个节点都必须配置自己的 KeyStore,并通过 TrustStore 信任其他节点的证书。所有节点必须使用兼容的协议配置,并在 TrustStore 中导入为集群节点签发证书的 CA。
3.3 配置参数
| 参数 | 说明 |
|---|---|
enable_thrift_ssl | 是否启用 DataNode Client RPC 通信加密,默认关闭。 |
thrift_ssl_client_auth | 是否要求 Client RPC 客户端在 TLS 握手中提供证书,默认值为 false。仅在 enable_thrift_ssl=true 时生效;启用后需要配置 trust_store_path 和 trust_store_pwd。 |
enable_internal_ssl | 是否启用集群内部通信加密,默认关闭。 |
ssl_protocol | 通信协议,默认值为 TLS。 |
key_store_path | KeyStore 文件路径。 |
key_store_pwd | KeyStore 口令。 |
trust_store_path | TrustStore 文件路径。启用 Client RPC mTLS 时,服务端使用它信任客户端证书或签发客户端证书的 CA;启用集群内部通信时,各节点使用它信任其他节点证书。 |
trust_store_pwd | TrustStore 口令。 |
4. 标准 TLS 通信
按照第 3 章启用通信加密,并在服务端和客户端配置兼容的 TLS 版本。然后准备服务端证书,并在客户端 TrustStore 中导入签发该证书的 CA 或服务端证书。如需启用 mTLS,还需要准备客户端证书,并在服务端 TrustStore 中导入客户端证书或签发该证书的 CA,具体配置见 4.5 节。
4.1 准备 TLS 证书
服务端证书的 SAN 必须包含客户端实际访问的域名或 IP 地址,否则客户端可能因主机名校验失败而拒绝连接。以下命令仅展示证书生成和导入流程。
4.1.1 创建服务端 KeyStore
keytool -genkeypair \
-alias timechodb \
-keyalg RSA \
-validity <validity_days> \
-ext SAN=dns:<server_domain>,ip:<server_ip> \
-keystore server.keystore4.1.2 导出服务端证书
keytool -export \
-alias timechodb \
-keystore server.keystore \
-rfc \
-file server.cer4.1.3 创建客户端 TrustStore
keytool -import \
-alias timechodb \
-file server.cer \
-keystore client.truststore4.2 配置 Java 客户端
以下示例适用于 Java 客户端。请确保 sslProtocol 与服务端配置兼容,并在 trustStore 中指定信任服务端证书的 TrustStore。
4.2.1 SessionPool
SessionPool sessionPool =
new SessionPool.Builder()
.nodeUrls(nodeUrls)
.user("root")
.password("<password>")
.maxSize(3)
.useSSL(true)
.sslProtocol("TLS")
.trustStore("/path/to/client.truststore")
.trustStorePwd("<trust_store_password>")
.build();4.2.2 Session
Session session =
new Session.Builder()
.host("127.0.0.1")
.port(6667)
.username("root")
.password("<password>")
.useSSL(true)
.sslProtocol("TLS")
.trustStore("/path/to/client.truststore")
.trustStorePwd("<trust_store_password>")
.build();4.3 配置 JDBC
JDBC 可以通过连接 URL 或 Properties 配置通信加密。以下示例使用 Properties:
Properties info = new Properties();
info.setProperty("user", "root");
info.setProperty("password", "<password>");
info.setProperty("use_ssl", "true");
info.setProperty("ssl_protocol", "TLS");
info.setProperty("trust_store", "/path/to/client.truststore");
info.setProperty("trust_store_pwd", "<trust_store_password>");
try (Connection connection =
DriverManager.getConnection(
"jdbc:iotdb://127.0.0.1:6667?version=V_1_0", info);
Statement statement = connection.createStatement()) {
// 业务逻辑
}4.4 配置 CLI
使用交互方式输入数据库密码、TrustStore 路径和 TrustStore 口令:
./start-cli.sh \
-h 127.0.0.1 \
-p 6667 \
-u root \
-usessl true \
-ssl_protocol TLS \
-ts -tpw -pw执行命令后,根据提示依次输入 TrustStore 路径、TrustStore 口令和数据库密码。
4.5 客户端 SSL 双向认证(mTLS)
单向 TLS 中,客户端验证服务端身份,服务端不验证客户端证书。mTLS 在此基础上要求客户端在 TLS 握手中出示证书,服务端仅接受持有受信任客户端证书的连接。应用仍需使用用户名和密码完成数据库认证;客户端证书用于建立额外的传输层身份和接入控制边界。
4.5.1 证书与信任关系
CA 私钥和 CA 证书
|- 签发服务端证书 -> server.keystore
`- 签发客户端证书 -> client.keystore
client.truststore:保存服务端证书或其 CA,用于客户端验证服务端
server.truststore:保存客户端证书或其 CA,用于服务端验证客户端推荐将签发客户端证书的 CA 公钥证书导入 server.truststore。这样同一 CA 为多个应用签发独立客户端证书后,无需逐个修改服务端 TrustStore。若只需允许单一应用接入,也可以仅导入该应用的客户端证书。
4.5.2 准备客户端 KeyStore 和服务端 TrustStore
以下示例假设已经具备可用的 CA:先生成客户端私钥和 CSR,再由该 CA 签发客户端证书。生产环境应使用企业 CA 或受管 CA 服务完成签发。
# 1. 生成客户端私钥和 CSR
keytool -genkeypair \
-alias client \
-keyalg RSA \
-validity <validity_days> \
-dname "CN=<client_identity>" \
-keystore client.keystore
keytool -certreq \
-alias client \
-keystore client.keystore \
-file client.csr
# 2. 由企业 CA 或测试 CA 签发 client.csr,得到 client.crt
# 3. 先导入 CA 证书,再导入签发后的客户端证书,建立证书链
keytool -importcert \
-alias client-ca \
-file client-ca.crt \
-keystore client.keystore
keytool -importcert \
-alias client \
-file client.crt \
-keystore client.keystore
# 4. 将客户端 CA 证书导入服务端 TrustStore
keytool -importcert \
-alias client-ca \
-file client-ca.crt \
-keystore server.truststoreclient.keystore 中必须同时包含客户端私钥、客户端证书和完整证书链。server.truststore 中可导入客户端证书,也可导入签发客户端证书的 CA 证书。
4.5.3 配置 Java Session、SessionPool
在单向 TLS 配置的基础上,为客户端添加 keyStore 和 keyStorePwd:
Session session =
new Session.Builder()
.host("127.0.0.1")
.port(6667)
.username("root")
.password("<password>")
.useSSL(true)
.sslProtocol("TLS")
.trustStore("/path/to/client.truststore")
.trustStorePwd("<trust_store_password>")
.keyStore("/path/to/client.keystore")
.keyStorePwd("<key_store_password>")
.build();
session.open();SessionPool sessionPool =
new SessionPool.Builder()
.nodeUrls(nodeUrls)
.user("root")
.password("<password>")
.maxSize(3)
.useSSL(true)
.sslProtocol("TLS")
.trustStore("/path/to/client.truststore")
.trustStorePwd("<trust_store_password>")
.keyStore("/path/to/client.keystore")
.keyStorePwd("<key_store_password>")
.build();TableSessionBuilder 和 TableSessionPoolBuilder 同样支持 keyStore(String) 与 keyStorePwd(String),用法与上述示例一致。
4.5.4 配置 JDBC、CLI 与导入导出工具
JDBC URL 或 Properties 增加 key_store 和 key_store_pwd:
Properties info = new Properties();
info.setProperty("user", "root");
info.setProperty("password", "<password>");
info.setProperty("use_ssl", "true");
info.setProperty("ssl_protocol", "TLS");
info.setProperty("trust_store", "/path/to/client.truststore");
info.setProperty("trust_store_pwd", "<trust_store_password>");
info.setProperty("key_store", "/path/to/client.keystore");
info.setProperty("key_store_pwd", "<key_store_password>");jdbc:iotdb://127.0.0.1:6667?version=V_1_0&use_ssl=true&ssl_protocol=TLS&trust_store=/path/to/client.truststore&trust_store_pwd=<trust_store_password>&key_store=/path/to/client.keystore&key_store_pwd=<key_store_password>CLI、数据导入导出工具和 Schema 工具使用 -ks(或 --key_store)指定客户端 KeyStore,使用 -kpw(或 --key_store_pwd)指定其口令:
./start-cli.sh \
-h 127.0.0.1 \
-p 6667 \
-u root \
-usessl true \
-ssl_protocol TLS \
-ts /path/to/client.truststore \
-tpw <trust_store_password> \
-ks /path/to/client.keystore \
-kpw <key_store_password>当服务端未启用 thrift_ssl_client_auth 时,已有客户端无需配置 -ks 和 -kpw。
4.5.5 配置 Python 客户端
Python 客户端使用 PEM 格式的证书文件,而不直接读取 Java KeyStore/TrustStore。ca_certs 用于验证服务端证书;client_cert 与 client_key 用于向服务端出示客户端证书和私钥。
from iotdb.Session import Session
session = Session(
"127.0.0.1",
"6667",
"root",
"<password>",
use_ssl=True,
ca_certs="/path/to/ca.crt",
client_cert="/path/to/client-chain.crt",
client_key="/path/to/client.key",
)
session.open(False)SessionPool 的 PoolConfig、TableSession 的 TableSessionConfig 和 TableSessionPool 的 TableSessionPoolConfig 也支持 client_cert 与 client_key。两项必须同时设置;仅设置其中一项会导致连接失败。当前私钥文件应使用无密码 PEM 私钥。
4.5.6 配置 Go 客户端
Go 客户端通过 TLSConfig 启用 TLS。CAFile 用于验证服务端证书,CertFile 和 KeyFile 用于提供客户端证书和私钥:
config := &client.Config{
Host: "127.0.0.1",
Port: "6667",
UserName: "root",
Password: "<password>",
TLSConfig: &client.TLSConfig{
CAFile: "/path/to/ca.crt",
CertFile: "/path/to/client-chain.crt",
KeyFile: "/path/to/client.key",
},
}
session := client.NewSession(config)
if err := session.Open(false, 5000); err != nil {
log.Fatal(err)
}
defer session.Close()PoolConfig 和 ClusterConfig 同样支持 TLSConfig。TLSConfig 为 nil 时保持非 SSL 连接;设置 CertFile 和 KeyFile 时两者必须同时提供。Go 会校验服务端证书 SAN,连接使用的 host 必须出现在服务端证书的 SAN 中。
Python 和 Go 客户端本次仅支持普通 TLS/mTLS;TLCP/国密连接不在这两个客户端的支持范围内。
4.5.7 Pipe 加密同步
iotdb-thrift-ssl-sink 已使用 ssl.trust-store-path 和 ssl.trust-store-pwd 验证目标端 DataNode 的服务端证书。目标端启用 thrift_ssl_client_auth=true 时,Pipe sink 还需要配置客户端 KeyStore:
CREATE PIPE A2B
WITH SINK (
'sink'='iotdb-thrift-ssl-sink',
'node-urls'='127.0.0.1:6667',
'ssl.trust-store-path'='pki/client.truststore',
'ssl.trust-store-pwd'='<trust_store_password>',
'ssl.key-store-path'='pki/client.keystore',
'ssl.key-store-pwd'='<key_store_password>'
)| 参数 | 说明 |
|---|---|
ssl.trust-store-path / ssl.trust-store-pwd | Pipe sink 验证目标端 DataNode 服务端证书的 TrustStore 及其口令。 |
ssl.key-store-path / ssl.key-store-pwd | Pipe sink 在 TLS 握手中向目标端 DataNode 出示客户端证书的 KeyStore 及其口令。 |
带 sink. 前缀时语义相同,例如 sink.ssl.key-store-path。目标端只启用单向 SSL 时,Pipe sink 沿用原有 TrustStore 配置即可。
4.5.8 安全建议
- CA 私钥只能由证书管理员保管,绝不能分发到 DataNode 或客户端。
- TrustStore 中的 CA 公钥证书可以分发,用于校验证书链,但不具备签发证书的能力。
- 生产环境应为每个应用或客户端身份签发独立证书和私钥;需要撤销某个应用时,应通过证书生命周期管理和 TrustStore 信任策略处理。
- Python 和 Go 使用的无密码
client.key必须限制文件读取权限。 - 服务端证书的 SAN 必须包含客户端实际访问的域名或 IP;客户端证书的主体信息应能区分具体应用或接入方。
5. 国密通信加密
5.1 前置条件
使用 TLCP 1.1 前,必须满足以下条件:
- 使用腾讯 Kona JDK 启动服务端以及相关 Java 客户端,并确认该 JDK 支持 TLCP 1.1 和 SM2。
- 服务端 KeyStore 必须使用 PKCS12 格式,并同时包含 SM2 签名证书及私钥、SM2 加密证书及私钥。
- TrustStore 包含签发上述证书的 CA 证书。
- 服务端和客户端将协议配置为
TLCPv1.1。
以下示例使用 tlcp-sign 和 tlcp-enc 作为证书别名;如果实际证书使用其他别名,请以 KeyStore 中的条目名称为准。
| 条目 | 用途 |
|---|---|
tlcp-sign | TLCP 签名证书和私钥。 |
tlcp-enc | TLCP 加密证书和私钥。 |
ca | 签发签名证书和加密证书的 CA 证书。 |
5.2 配置服务端和节点
# 客户端通信加密
enable_thrift_ssl=true
# 节点间通信加密
enable_internal_ssl=true
# 强制使用 TLCP 1.1
ssl_protocol=TLCPv1.1
key_store_path=/path/to/tlcp-keystore.p12
key_store_pwd=<key_store_password>
trust_store_path=/path/to/tlcp-truststore.p12
trust_store_pwd=<trust_store_password>仅启用客户端通信加密时,可以根据场景保留 enable_internal_ssl=false;仅启用节点间通信加密时,可以保留 enable_thrift_ssl=false。
5.3 配置 Session 和 SessionPool
配置 Session 或 SessionPool 时,启用 SSL,将协议设置为 TLCPv1.1,并指定 TLCP TrustStore:
.useSSL(true)
.sslProtocol("TLCPv1.1")
.trustStore("/path/to/tlcp-truststore.p12")
.trustStorePwd("<trust_store_password>")5.4 TLCP 客户端双向认证
TLCP 客户端双向认证同样由 thrift_ssl_client_auth=true 启用。服务端 KeyStore 和客户端 KeyStore 都必须满足 TLCP 双证书要求:同时包含 SM2 签名证书及私钥、SM2 加密证书及私钥。服务端 TrustStore 应信任签发客户端两张证书的 CA,客户端 TrustStore 应信任签发服务端两张证书的 CA。
Java Session 或 SessionPool 在现有 TLCP 配置后增加:
.keyStore("/path/to/tlcp-client-keystore.p12")
.keyStorePwd("<key_store_password>")使用 TLCP 的服务端、Java 客户端、CLI 以及导入导出工具必须由支持 TLCP 1.1 的 Kona JDK 启动。Python 和 Go 客户端不支持 TLCP。
5.5 配置 JDBC
info.setProperty("use_ssl", "true");
info.setProperty("ssl_protocol", "TLCPv1.1");
info.setProperty("trust_store", "/path/to/tlcp-truststore.p12");
info.setProperty("trust_store_pwd", "<trust_store_password>");启用 TLCP mTLS 时,还需要设置 key_store 和 key_store_pwd,取值为客户端 TLCP KeyStore 及其口令。
5.6 配置 CLI 和导入导出工具
使用 CLI、导入工具或导出工具连接 TLCP 端口时,请指定 -ssl_protocol TLCPv1.1,并使用 Kona JDK 启动相应工具。
./start-cli.sh \
-h 127.0.0.1 \
-p 6667 \
-u root \
-pw <password> \
-usessl true \
-ssl_protocol TLCPv1.1 \
-ts /path/to/tlcp-truststore.p12 \
-tpw <trust_store_password>启用 TLCP mTLS 时,在上述命令后增加 -ks /path/to/tlcp-client-keystore.p12 和 -kpw <key_store_password>。
5.7 检查 TLCP 证书
生成或取得证书后,使用 Kona JDK 的 keytool 检查 KeyStore:
\${KONA_HOME}/bin/keytool -list -v \
-keystore /path/to/tlcp-keystore.p12 \
-storetype PKCS12KeyStore 中应包含一个签名证书私钥条目和一个加密证书私钥条目;TrustStore 中应包含对应的 CA 证书。证书的 SAN 必须覆盖实际使用的节点域名和 IP 地址。启用 TLCP mTLS 时,客户端 KeyStore 也应包含签名和加密私钥条目及完整证书链。
6. 集群变更注意事项
- 单个节点的证书错误、私钥错误或证书过期会导致该节点启动失败,日志中会记录对应原因。
- 集群节点的协议或信任关系不一致时,后启动节点可能因无法与 Seed ConfigNode 完成握手而启动失败。
- 运行中的证书过期可能中断节点间通信并导致集群不可用。应在证书到期前完成更换和集群验证。
- 集群中的所有节点必须使用一致的协议和信任配置。请先将证书和配置分发到所有节点,再按照集群停机和启动流程完成切换。
- 启用 Client RPC mTLS 前,应先在非生产环境验证所有客户端、Pipe 任务和自动化工具均已配置客户端证书;否则原有单向 TLS 客户端将无法接入。
7. 故障排查
| 现象或错误 | 可能原因 | 处理方法 |
|---|---|---|
TLCPv1.1 SSLContext not available | 当前 JDK 不支持 TLCP 1.1 | 使用腾讯 Kona JDK 启动服务端或 Java 客户端,并确认实际生效的 JAVA_HOME。 |
CLI 显示 Connection Error,且服务端已经正常启动 | 当前 JDK 不支持 TLCP 1.1,或客户端协议、TrustStore 配置错误 | 确认实际生效的 JAVA_HOME 指向支持 TLCP 的腾讯 Kona JDK,并检查 -usessl、-ssl_protocol、-ts 和 -tpw 参数。启用 mTLS 时还需检查 -ks 和 -kpw。 |
Unknown named curve: 1.2.156.10197.1.301 | 当前 JDK 无法识别 SM2 曲线 | 使用支持 SM2 的 JDK,并重新检查 KeyStore 和 TrustStore。 |
Failed to read key store or trust store | 文件路径、口令、格式或文件权限错误 | 检查路径、PKCS12 格式、口令和运行账号的读取权限。使用 Python/Go 时还需检查 PEM 文件格式与读取权限。 |
| 客户端无法连接已启用 SSL 的端口 | 客户端未启用 SSL,或协议与服务端不兼容 | 启用客户端 SSL,并检查 ssl_protocol 和 TrustStore。 |
| 节点无法加入集群 | 节点协议配置不一致,或证书不受其他节点信任 | 统一节点配置并检查 CA、SAN 和证书有效期。 |
启用 thrift_ssl_client_auth=true 后客户端无法连接或首次 RPC 失败 | 客户端未提供证书和私钥 | Java/JDBC/CLI/工具配置客户端 KeyStore;Python/Go 同时配置客户端证书与私钥。 |
| TLS 握手失败,服务端日志显示客户端证书不受信任 | server.truststore 未导入客户端证书或其 CA,或客户端证书链不完整 | 导入正确的客户端证书或 CA 证书,检查客户端是否携带完整证书链,然后重启 DataNode。 |
| Python/Go 在创建 SSL 上下文时失败 | 仅设置了客户端证书或仅设置了客户端私钥,或 PEM 私钥受密码保护 | 同时设置证书和私钥;使用与客户端库兼容的无密码 PEM 私钥。 |
| Go 客户端提示服务端证书主机名不匹配 | 连接地址未包含在服务端证书 SAN 中 | 以证书 SAN 中的域名或 IP 连接,或重新签发包含实际访问地址的服务端证书。 |