ScyllaDB 加密通信实践:使用 openssl 生成自签名证书链与信任库配置
【免费下载链接】scylladbNoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB项目地址: https://gitcode.com/GitHub_Trending/sc/scylladb
在 ScyllaDB 集群中启用 TLS/SSL 加密通信(无论是节点之间的数据传输,还是客户端与节点之间的 CQL 连接),第一步都是为集群准备可信的证书体系。本指南以 docs/operating-scylla/security/generate-certificate.rst 为核心,完整演示如何使用openssl构建一条自签名 CA 证书链,并详细讲解如何将生成的证书、私钥与信任库分别配置到 ScyllaDB 的server_encryption_options与client_encryption_options中。读完本文,你将能够独立为 ScyllaDB 生成一套可投入生产验证的证书链,并在日志中确认加密服务成功启动。
为什么需要自签名证书链
对于本地或内部网络通信,自签名证书配合私有信任库(private trust store)通常足以保证通信安全。ScyllaDB 官方文档明确说明:多个节点可以共享同一份证书,前提是确保信任配置不被篡改。这意味着你不需要为每个节点分别向公共 CA 申请证书,只需维护一个内部 CA(Certificate Authority)并让所有节点信任它。
自签名证书链的结构如下:
- CA 私钥与 CA 证书:内部自签名的根证书(示例中为
cadb.key与cadb.pem),仅用于签发其他证书; - 节点证书与私钥:由 CA 签名、供 ScyllaDB 数据库节点实际使用的证书(示例中为
db.crt与db.key); - 信任库:持有 CA 证书的文件,客户端或节点用它来验证对端证书的合法性。
由于 node-node-encryption.rst 中提到 ScyllaDB 的 TLS 实现基于 OpenSSL(其使用的 OpenSSL 库为 FIPS 140-2 认证),上述证书最终将由 OpenSSL 工具链生成并被 ScyllaDB 加载解析。
第一步:编写证书配置文件(.cfg)
构建证书链的第一步是创建一个 OpenSSL 配置文件,其中定义了密钥长度、证书主体信息(distinguished name)以及 X.509 扩展。模板如下:
[ req ] default_bits = 4096 default_keyfile = <hostname>.key distinguished_name = req_distinguished_name req_extensions = v3_req prompt = no [ req_distinguished_name ] C = <country code> ST = <state> L = <locality/city> O = <domain> OU = <organization, usually domain> CN= <hostname>.<domain> emailAddress = <email> [v3_ca] subjectKeyIdentifier=hash authorityKeyIdentifier=keyid:always,issuer:always basicConstraints = CA:true [v3_req] # Extensions to add to a certificate request basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment各字段含义:
[req]段控制证书请求(CSR)的生成行为。default_bits = 4096指定密钥长度;default_keyfile指定默认私钥文件名;prompt = no表示不进行交互式提问,直接使用配置中的值;[req_distinguished_name]段填写证书主体信息。CN(Common Name)必须设置为主机名.域名的形式,例如db.foo.bar;[v3_ca]段用于签发 CA 证书,其中basicConstraints = CA:true表明这是一把 CA 身份;[v3_req]段用于证书签名请求,basicConstraints = CA:FALSE表明被签发的证书是终端实体证书,keyUsage定义其允许的密钥用途。
将尖括号中的占位值替换为你组织的信息。官方示例中,主机名为db、域名为foo.bar,配置文件保存为db.cfg:
[ req ] default_bits = 4096 default_keyfile = db.key distinguished_name = req_distinguished_name req_extensions = v3_req prompt = no [ req_distinguished_name ] C = SE ST = Stockholm L = Stockholm O = foo.bar OU = foo.bar CN= db.foo.bar emailAddress = postmaster@foo.bar [v3_ca] subjectKeyIdentifier=hash authorityKeyIdentifier=keyid:always,issuer:always basicConstraints = CA:true [v3_req] # Extensions to add to a certificate request basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment重要注意事项:每一张新签发的证书,其
req_distinguished_name段中的CN值必须不同,否则将无法通过openssl verify校验。也就是说,如果你要为多台主机签发证书,需要为每台主机准备(或临时修改)各自的 CN。
第二步:生成 CA 私钥与自签名 CA 证书
先为内部 CA 生成一个 4096 位的 RSA 私钥:
openssl genrsa -out cadb.key 4096再用该私钥配合db.cfg配置,生成一张自签名(-x509)的 CA 证书,有效期 3650 天(约 10 年),-nodes表示私钥不加密:
openssl req -x509 -new -nodes -key cadb.key -days 3650 -config db.cfg -out cadb.pemcadb.pem即为整个集群的信任锚点(trust anchor),后续它将被放入所有节点和客户端的信任库中。
第三步:生成节点私钥与证书签名请求(CSR)
为数据库节点生成独立的私钥:
openssl genrsa -out db.key 4096从该私钥生成证书签名请求:
openssl req -new -key db.key -out db.csr -config db.cfgdb.csr是未签名的请求文件,其中包含节点的公钥与主体信息,等待 CA 签名。
第四步:签发节点证书
用 CA 私钥对 CSR 进行签名,生成最终可用的节点证书:
openssl x509 -req -in db.csr -CA cadb.pem -CAkey cadb.key -CAcreateserial -out db.crt -days 365 -sha256参数说明:
-CA cadb.pem -CAkey cadb.key:指定签发用的 CA 证书与私钥;-CAcreateserial:首次签发时自动创建序列号文件cadb.srl;-days 365:节点证书有效期 1 年;-sha256:使用 SHA-256 摘要算法签名。
第五步:核对产物并部署
签发完成后,你会得到以下文件:
| 文件 | 用途 |
|---|---|
db.key | PEM 格式私钥,由数据库节点使用(仅节点持有,注意保密) |
db.crt | 由cadb.pem签名、与db.key配对的 PEM 格式证书,由数据库节点使用 |
cadb.pem | PEM 格式 CA 身份,可作为信任库使用;同时用于签发将要连接数据库的客户端证书 |
将文件放到你选择的目录(官方配置示例中常放在/etc/scylla/下),并确保设置好文件权限,使 ScyllaDB 实例能够读取它们。然后更新服务端/客户端配置来引用这些文件路径。
第六步:在 ScyllaDB 中启用加密并验证
证书就绪后,需要将其配置到 ScyllaDB 主配置文件/etc/scylla/scylla.yaml中,然后重启节点。仓库中的 conf/scylla.yaml(第 504-522 行)给出了两组配置项的完整模板。
配置节点间加密(server_encryption_options)
启用节点间加密由server_encryption_options控制(详见 node-node-encryption.rst),其 yaml 结构如下:
server_encryption_options: internode_encryption: <none|rack|dc|all|transitional> certificate: <path to a PEM-encoded certificate file> keyfile: <path to a PEM-encoded key for certificate> truststore: <path to a PEM-encoded trust store> (optional) certficate_revocation_list: <path to a PEM-encoded CRL file> (optional)各参数含义与取值:
internode_encryption:控制节点间加密范围,可选值:none(默认):所有流量不加密;all:加密所有节点间流量;dc:仅加密跨数据中心(data center)之间的流量;rack:仅加密跨机架(rack)之间的流量;transitional:所有出站流量加密,但允许未加密的入站流量,用于集群零停机升级;
certificate:PEM 格式证书,可以是自签名证书,也可以是由 CA 签发的证书;keyfile:与证书对应的 PEM 格式私钥;truststore(可选):PEM 格式的受信任 CA 证书库路径;若未提供,ScyllaDB 会尝试使用系统信任库来认证证书;certficate_revocation_list(可选):PEM 编码的证书吊销列表(CRL)路径,用于列出在到期前已被吊销的证书;require_client_auth:设为True时要求对端提供客户端证书,默认False;priority_string:指定 TLS 握手的算法与选项(GnuTLS 优先级字符串语法),默认无。
修改后重启节点使配置生效(注意需要逐节点操作,避免集群中断)。
配置客户端到节点加密(client_encryption_options)
客户端与节点之间启用 TLS 后,所有客户端与节点的通信都通过 TLS/SSL 传输。参考 client-node-encryption.rst,配置示例:
client_encryption_options: enabled: true certificate: /etc/scylla/db.crt keyfile: /etc/scylla/db.key truststore: <path to a PEM-encoded trust store> (optional) certficate_revocation_list: <path to a PEM-encoded CRL file> (optional) require_client_auth: ... priority_string: SECURE128:-VERS-TLS1.0:-VERS-TLS1.1关键说明:
enabled默认false;- 若使用自签名证书,
truststore参数必须设置为包含 CA 私钥的 PEM 容器(即上文生成的cadb.pem); priority_string可精确控制 TLS 版本与安全强度。例如SECURE128:-VERS-TLS1.0:-VERS-TLS1.1表示最低 128 位安全强度并禁用 TLS 1.0/1.1;SECURE128:+SECURE192:-VERS-ALL:+VERS-TLS1.2:+VERS-TLS1.3表示启用 128/192 位安全密码套件且只允许 TLS 1.2 与 TLS 1.3;enable_session_tickets默认true(见 conf/scylla.yaml 第 522 行)。
配置客户端到节点加密时建议逐节点操作:先nodetool drain,停止 ScyllaDB,修改配置后启动(新集群可跳过前两步)。
在日志中验证加密生效
重启 ScyllaDB 后,根据启用的加密类型,日志中会出现对应的确认信息:
- 节点间加密生效时:
Starting Encrypted Messaging Service on SSL port 7001- 客户端到节点加密生效时:
Enabling encrypted CQL connections between client and server客户端到节点加密还可以通过journalctl _COMM=scylla查看,日志中出现storage_service - Enabling encrypted CQL connections between client and node即表示加密连接已启用。
客户端证书与 keystore 的配套使用
生成证书链的产物同样服务于客户端验证环节(client-node-encryption.rst 的 Validate the Clients 部分):
使用 cqlsh 连接启用 SSL 的集群时,需要先生成
~/.cassandra/cqlshrc配置文件(详见 gen-cqlsh-file.rst)。自签名证书场景下[ssl]段写法如下:[ssl] certfile = /etc/scylla/db.crt validate = true userkey = /etc/scylla/db.key usercert = /etc/scylla/db.crt注意:当
validate = true时,证书名称必须与机器主机名匹配;若启用了客户端认证(require_client_auth = true),还需指定userkey与usercert。保存后使用cqlsh --ssl连接验证。使用
cassandra-stress压测时,需要把db.key、db.crt、cadb.key、cadb.pem复制到客户端,并用openssl pkcs12与keytool生成 Java keystore/truststore(keystore.jks与truststore.jks),随后通过-transport keystore=... keystore-password=... truststore=... truststore-password=...参数指定。
证书热加载(Hot Reload)
一旦internode_encryption或client_encryption_options被启用(即设置值不为 none),ScyllaDB 会持续监控 scylla.yaml 中指定的 SSL/TLS 证书与密钥文件(详见 ssl-hot-reload.rst)。当文件在磁盘上被更新时,ScyllaDB 会自动重新加载它们,并用于后续的新连接——这意味着证书轮换(rotation)时无需重启节点即可生效,方便在证书到期前平滑更新。
零停机迁移已有集群到 TLS
对于已运行但未启用 TLS 的集群,node-node-encryption.rst 给出了三步渐进式迁移方案:
被动监听阶段:为每个节点加上
ssl_storage_port: 7001与一套server_encryption_options(internode_encryption仍为none),重启节点。此时节点在 7001 端口开启被动 TLS 监听,但出站流量仍不加密:ssl_storage_port: 7001 server_encryption_options: internode_encryption: none certificate: <path to a PEM-encoded certificate file> keyfile: <path to a PEM-encoded key for certificate> truststore: <path to a PEM-encoded trust store> (optional) certficate_revocation_list: <path to a PEM-encoded CRL file> (optional)过渡阶段:将每个节点的
internode_encryption改为transitional并重启,所有出站流量开始加密,同时仍接受未加密入站流量;强制执行阶段:将每个节点改为
all、rack或dc并重启,出站按目标类型加密,入站也按模式强制要求加密,完成全量加密。
源码侧实现印证
上述配置项并非文档虚构,而是由 ScyllaDB 配置系统直接解析。在 db/config.cc 中可以看到server_encryption_options的正式定义,其说明文字明确写道:internode_encryption默认值为none,用于控制节点间通信的加密(使用 TLS_RSA_WITH_AES_128_CBC_SHA 密码套件进行认证、密钥交换与数据传输)。在传输层,transport/controller.cc 负责处理client_encryption_options对应的加密 CQL 连接逻辑。当你按照本文步骤完成配置并重启后,ScyllaDB 会在启动阶段加载证书文件、初始化 TLS 上下文,并在日志中输出前文所述的确认信息。
相关文档
- 节点间传输加密(Node-to-Node)
- 客户端到节点传输加密(Client-to-Node)
- 生成 cqlshrc 文件
- 授权(Authorization)
【免费下载链接】scylladbNoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB项目地址: https://gitcode.com/GitHub_Trending/sc/scylladb
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考