Elasticsearch集群TLS/SSL配置实战:从证书生成到安全通信全流程

📅 2026/6/19 9:01:56
Elasticsearch集群TLS/SSL配置实战:从证书生成到安全通信全流程
1. 项目概述在Elasticsearch的日常运维中集群安全配置是每个工程师从“能用”到“敢用”必须跨越的一道坎。尤其是在生产环境一个没有启用TLS/SSL加密的Elasticsearch集群就好比把公司核心数据仓库的大门敞开任何人都可以大摇大摆地走进来查看、修改甚至删除数据。我见过太多团队在测试环境玩得风生水起一到上生产就卡在安全配置这一步被各种证书、密钥库、双向认证搞得焦头烂额。今天我们就来彻底拆解Elasticsearch集群的TLS/SSL配置与密钥库管理这不仅仅是打开几个开关而是理解一套完整的安全通信体系。无论你是要为现有集群“补票上车”还是从零搭建一个安全的新集群这篇文章都会手把手带你走通全流程并分享那些官方文档里不会写的“踩坑”实录。2. 集群安全的核心为什么必须启用TLS/SSL在深入实操之前我们必须先搞清楚一个根本问题为什么Elasticsearch集群必须启用TLS/SSL很多新手会觉得我的集群部署在内网有防火墙是不是就可以省掉这个“麻烦”的步骤答案是绝对不行。首先传输层安全TLS及其前身安全套接字层SSL解决的是通信过程中的三大核心安全问题机密性、完整性和身份验证。在Elasticsearch集群中节点之间Transport层以及客户端与集群之间HTTP层的通信默认都是明文的。这意味着任何一个能够接入网络的设备都可以通过抓包工具如Wireshark轻易地看到你索引的文档内容、执行的查询语句甚至是修改数据的请求。这对于包含用户隐私、商业机密或系统日志的数据来说是灾难性的。其次Elasticsearch的节点发现和集群组建依赖于节点间的相互通信。如果没有TLS和身份验证任何一个知道集群地址和端口的进程都可以伪装成一个Elasticsearch节点加入集群这就是所谓的“欺诈节点”攻击。攻击者加入后可以窃取分片数据、破坏集群状态甚至发起拒绝服务攻击。因此启用TLS/SSL不仅仅是“加密数据流”它更构建了集群内部的信任边界。通过证书每个节点都能向其他节点证明“我是我”并且确保我们之间的对话没有被窃听或篡改。从Elasticsearch 8.0开始安全功能包括TLS和基础身份认证在安装时默认就是启用的这足以说明其重要性。对于7.x版本虽然默认不开启但任何计划用于生产的部署启用安全配置都是第一步。3. 证书体系与密钥库管理深度解析配置Elasticsearch TLS核心就是管理好两样东西证书和密钥库。很多人在这里容易混淆我们先把概念理清。X.509证书可以理解为一个节点的“数字身份证”。它包含了该节点的身份信息如通用名CN、组织O等、公钥以及签发机构CA的签名。其他节点或客户端通过验证这张“身份证”是否由可信的CA签发以及身份证上的信息是否匹配当前连接的主机来决定是否信任它。而密钥库Keystore和信任库Truststore则是用来存放和管理这些“身份证”及对应“私钥”的保险箱。在Java生态Elasticsearch基于Java中常见的格式有JKS和PKCS#12。Elasticsearch主要使用PKCS#12格式文件扩展名通常为.p12或.pfx。密钥库Keystore存放自己的“身份证”证书和绝不能外泄的“私钥”。私钥用于在TLS握手过程中解密数据或生成数字签名证明你确实持有这张身份证。信任库Truststore存放你信任的“签发机构”CA的证书。当对方节点出示它的“身份证”时你会用信任库里的CA证书去验证这张身份证的真伪。在Elasticsearch配置中xpack.security.transport.ssl.keystore.path指向的就是节点自己的密钥库包含节点证书和私钥而xpack.security.transport.ssl.truststore.path指向的是信任库包含CA证书。在简单配置中我们常常让一个.p12文件同时充当这两个角色即它既包含节点证书/私钥也包含CA证书。Elasticsearch提供了一个非常方便的工具elasticsearch-certutil来生成这一切。它的设计哲学是“开箱即用”能够引导你生成一个自签名的CA然后用这个CA为你的集群签发所有需要的证书。对于大多数内部集群和开发测试环境这已经完全足够。对于严格的生产环境你可能会考虑使用公司现有的、受全局信任的CA来签发证书流程类似只是CA的来源不同。4. 实战生成与配置节点间传输层TransportTLS证书这是保障集群内部通信安全的第一步。我们将使用elasticsearch-certutil工具完成从创建CA到为所有节点分发证书的全过程。4.1 生成证书颁发机构CACA是整个证书信任链的根。集群内所有节点的证书都必须由同一个CA签发它们之间才会相互信任。操作需要在集群中的任意一个节点上进行通常是在第一个准备启动的节点。进入Elasticsearch的安装目录$ES_HOME执行以下命令./bin/elasticsearch-certutil ca执行后工具会进入交互式命令行界面。你会看到一些说明文字然后被询问输出文件名和密码。输出文件默认是elastic-stack-ca.p12直接回车即可。这个文件将包含CA的证书和私钥。密码为CA密钥库设置一个强密码。这里有一个关键选择你可以设置密码也可以留空直接回车。如果留空后续使用该CA文件时就不需要输入密码方便自动化脚本但安全性稍低。对于生产环境建议设置强密码并妥善保管。命令执行成功后会在当前目录下生成elastic-stack-ca.p12文件。请务必安全备份这个文件它是你整个集群安全体系的根。如果丢失你将无法用同一个CA签发新的节点证书未来扩容会非常麻烦。4.2 为集群所有节点生成证书接下来我们用刚创建的CA为集群中的每一个节点签发证书。假设你的集群有三个节点IP地址分别是192.168.1.101, 192.168.1.102, 192.168.1.103。./bin/elasticsearch-certutil cert \ --ca elastic-stack-ca.p12 \ --days 3650 \ --ip 192.168.1.101,192.168.1.102,192.168.1.103 \ --dns node-1,node-2,node-3,localhost让我们拆解一下这个命令的参数--ca: 指定上一步生成的CA文件路径。--days: 证书的有效期这里设为3650天约10年。对于生产环境建议遵循“短有效期”原则如90天并配合自动化证书轮换但这需要更复杂的运维体系。对于初期部署可以设置一个较长的有效期以减少维护频率。--ip:这是最关键的一步。你必须列出集群中所有节点可能用于通信的IP地址。当节点间建立TLS连接时会校验对方证书中是否包含连接所使用的IP地址。如果这里漏掉了某个节点的IP该节点将无法加入集群或与其他节点通信。--dns: 列出所有节点的主机名。同样如果客户端或节点通过主机名连接证书中必须包含该主机名。localhost通常也需要加上因为某些本地回环通信可能会用到。执行命令后会提示你输入CA密钥库的密码如果你之前设置了的话然后让你指定输出文件名默认elastic-certificates.p12并为新生成的节点证书密钥库设置密码。同样密码可以为空。实操心得一关于IP和DNS的坑我遇到过最典型的问题就是节点启动后日志里疯狂报错“SSL handshake failed”或“certificate verify failed”。十有八九是--ip参数没写全。特别是当你使用云服务器时除了内网IP可能还有公网IP或弹性网卡IP。一个稳妥的做法是在每个节点上执行hostname -I命令把所有列出的非回环IP地址都加入到--ip列表中。对于DNS如果你内部有DNS服务最好使用完整域名FQDN例如es-node-1.prod.cluster.local。4.3 分发证书并配置Elasticsearch生成的elastic-certificates.p12文件包含了所有节点的证书和私钥默认情况下它是一份多主机证书。你需要将这个文件复制到集群中每一个节点的相同位置例如$ES_HOME/config/certs/目录下。确保目录存在。# 在每个节点上创建证书目录 mkdir -p config/certs # 将生成的p12文件复制到该目录假设从第一个节点scp过去 cp elastic-certificates.p12 config/certs/接下来修改每个节点的elasticsearch.yml配置文件启用安全配置# 启用X-Pack安全功能包括认证和TLS xpack.security.enabled: true # 启用传输层节点间TLS xpack.security.transport.ssl.enabled: true # 验证模式certificate表示验证对方证书的有效性和签发者不验证主机名。 # 对于内部集群使用certificate通常足够因为我们已经将IP地址包含在证书中。 # 如果设置为full则会额外验证连接使用的主机名/IP是否与证书中的Subject Alternative Name (SAN)匹配更为严格。 xpack.security.transport.ssl.verification_mode: certificate # 要求客户端其他节点提供证书即启用双向认证 xpack.security.transport.ssl.client_authentication: required # 指定本节点的密钥库和信任库路径相对路径基于ES_HOME xpack.security.transport.ssl.keystore.path: certs/elastic-certificates.p12 xpack.security.transport.ssl.truststore.path: certs/elastic-certificates.p12如果你的证书密钥库设置了密码还需要将密码添加到Elasticsearch的密钥库中这是一个独立的、用于存储敏感信息的系统。在每个节点上执行# 这会提示你输入证书密钥库的密码 ./bin/elasticsearch-keystore add xpack.security.transport.ssl.keystore.secure_password ./bin/elasticsearch-keystore add xpack.security.transport.ssl.truststore.secure_password为什么要有这个步骤因为把密码明文写在elasticsearch.yml里是极不安全的。Elasticsearch的密钥库elasticsearch.keystore会对这些密码进行加密存储。配置中只需引用密钥库中的条目名即可。4.4 启动集群并验证配置完成后按顺序启动所有节点。首先启动第一个节点持有初始主节点资格的节点观察其日志。你应该能看到与安全相关的日志行例如[INFO ][o.e.x.s.t.n.SecurityNetty4Transport] [node-1] SSL driver is configured with provider [SunJSSE], protocol [TLSv1.3], ciphers [TLS_AES_256_GCM_SHA384, TLS_AES_128_GCM_SHA256...] [INFO ][o.e.x.s.t.n.SecurityNetty4Transport] [node-1] SSL driver is configured with trust configuration [Composite: PKCS#12: /path/to/elastic-certificates.p12] and key configuration [Composite: PKCS#12: /path/to/elastic-certificates.p12] [INFO ][o.e.t.TransportService ] [node-1] publish_address {192.168.1.101:9300}, bound_addresses {[::]:9300}关键点是看到SSL driver is configured和publish_address。然后启动其他节点。其他节点启动后应该能在第一个节点的日志中看到类似added {{node-2}{xxxxx}{xxx}}{192.168.1.102:9300}{...}的连接成功信息。你可以使用curl命令验证集群状态和TLS是否生效# 注意此时HTTP层还未加密我们先用HTTP检查集群健康状态假设HTTP端口9200开放 curl -X GET localhost:9200/_cluster/health?pretty如果看到status : green或yellow并且节点数正确说明传输层TLS配置成功节点间已建立安全连接。5. 实战配置HTTPS访问HTTP层TLS节点间的通信安全了但用户或应用程序通过9200端口访问Elasticsearch的HTTP API还是明文的。我们需要为HTTP层也配置TLS。5.1 为HTTP层生成证书我们继续使用之前创建的同一个CA为Elasticsearch的HTTP服务生成证书。这确保了整个体系使用统一的信任根。./bin/elasticsearch-certutil http这个命令会启动一个更复杂的交互式向导。下面我解释几个关键的选择生成CSR选择n。CSR证书签名请求是用于向公共CA或企业CA申请证书的。我们使用自己的CA所以不需要。使用现有CA选择y然后输入之前生成的elastic-stack-ca.p12的路径。证书有效期根据你的安全策略设置例如5y5年。是否为每个节点生成单独证书选择n。我们生成一个通配证书用于所有节点的HTTP服务。主机名如果你有统一的DNS域名如es.example.com可以输入。如果客户端主要通过IP访问这里可以直接回车跳过。IP地址务必输入所有节点对外的HTTP服务IP地址以及127.0.0.1和::1本地回环。例如192.168.1.101,192.168.1.102,192.168.1.103,127.0.0.1,::1。私钥密码可以为HTTP证书密钥库设置密码同样生产环境建议设置。输出文件指定生成的zip文件路径和名称例如elasticsearch-http.zip。命令执行后会生成一个zip文件。解压后你会看到类似这样的结构elasticsearch-http.zip ├── elasticsearch/ │ ├── http.p12 # Elasticsearch使用的PKCS#12密钥库 │ ├── sample-elasticsearch.yml # 示例配置 │ └── README.txt └── kibana/ ├── elasticsearch-ca.pem # Kibana信任的CA证书PEM格式 ├── sample-kibana.yml └── README.txt5.2 配置Elasticsearch启用HTTPS将elasticsearch目录下的http.p12文件复制到每个Elasticsearch节点的config/certs/目录下。然后在每个节点的elasticsearch.yml中添加HTTP SSL配置# 启用HTTP层SSL xpack.security.http.ssl.enabled: true # 指定HTTP SSL密钥库路径 xpack.security.http.ssl.keystore.path: certs/http.p12 # 可选设置验证模式对于来自客户端的连接通常需要更严格的验证 # xpack.security.http.ssl.client_authentication: none # none是默认值表示不要求客户端提供证书。如果要求双向认证更安全可设置为required。如果http.p12有密码同样需要将其添加到Elasticsearch密钥库./bin/elasticsearch-keystore add xpack.security.http.ssl.keystore.secure_password重启Elasticsearch节点。现在HTTP API就只能在HTTPS上访问了。尝试用HTTP访问会失败用HTTPS则可以# 使用HTTPS和-k参数暂时忽略证书验证因为我们用的是自签名CA curl -k -X GET https://localhost:9200/_cluster/health?pretty # 或者使用正确的CA证书进行验证 curl --cacert config/certs/elasticsearch/ca.pem -X GET https://localhost:9200/_cluster/health?pretty实操心得二证书验证与curl使用-k或--insecure参数只是临时测试手段它会跳过证书验证不安全。在生产中你的客户端如Logstash、Beats、自定义应用必须配置为信任你的CA证书即上面生成的elastic-stack-ca.p12或从中导出的.pem文件。否则客户端会因证书不受信而拒绝连接。这是TLS配置好后最常见的客户端连接问题。6. 集成Kibana完成安全链路最后一环Kibana作为Elasticsearch的主要可视化工具也需要接入这个安全体系。这涉及两个方向的加密出站Kibana作为客户端连接到Elasticsearch。入站用户浏览器作为客户端连接到Kibana。6.1 配置Kibana连接安全的Elasticsearch这一步是让Kibana信任我们的Elasticsearch CA。使用上一步解压出的kibana/elasticsearch-ca.pem文件。将elasticsearch-ca.pem文件复制到Kibana服务器的某个目录例如$KIBANA_HOME/config/certs/。修改kibana.yml配置文件# 指定Elasticsearch的HTTPS地址 elasticsearch.hosts: [https://192.168.1.101:9200, https://192.168.1.102:9200] # 指定信任的CA证书路径PEM格式 elasticsearch.ssl.certificateAuthorities: [ config/certs/elasticsearch-ca.pem ] # 如果Elasticsearch配置了HTTP层客户端认证双向TLS则需要提供Kibana自己的证书和私钥 # elasticsearch.ssl.certificate: config/certs/kibana.crt # elasticsearch.ssl.key: config/certs/kibana.key # 通常不需要除非你在Elasticsearch中将xpack.security.http.ssl.client_authentication设为了required。6.2 为Kibana自身启用HTTPS为了让用户通过HTTPS访问Kibana默认端口5601我们需要为Kibana服务器本身生成一个TLS证书。你可以使用之前为Elasticsearch HTTP生成的同一个CA也可以使用像Let‘s Encrypt这样的公共CA或者生成一个自签名证书。这里演示使用OpenSSL生成一个简单的自签名证书适用于测试或内部环境# 在Kibana服务器上执行 openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout $KIBANA_HOME/config/certs/kibana.key \ -out $KIBANA_HOME/config/certs/kibana.crt \ -subj /CCN/STBeijing/LBeijing/OYourOrg/CNyour-kibana-hostname-or-ip将生成的kibana.key和kibana.crt文件放到Kibana的config/certs/目录。然后在kibana.yml中启用SSL# 启用Kibana服务器的SSL server.ssl.enabled: true # 指定服务器证书和私钥 server.ssl.certificate: config/certs/kibana.crt server.ssl.key: config/certs/kibana.key重启Kibana。现在你只能通过https://your-kibana-host:5601来访问Kibana了。浏览器会警告证书不受信任因为是自签名的你需要手动接受风险或将该CA证书导入到系统的信任库中。7. 常见问题、故障排查与进阶技巧配置过程中你几乎一定会遇到各种问题。下面是我总结的常见“坑点”和解决方法。7.1 节点无法加入集群Transport层问题症状后续启动的节点日志中持续出现SSLHandshakeException、Not authorized to join the cluster或一直停留在discovering master node状态。排查步骤检查IP/DNS列表这是最常见的原因。确保生成证书时--ip参数包含了所有节点用于集群通信的IP地址。在每个节点上运行hostname -I和ip addr核对所有非回环地址。检查证书一致性确保所有节点的config/certs/目录下的.p12文件完全一样来自同一生成命令。用md5sum或sha256sum命令对比文件哈希值。检查配置文件核对每个节点的elasticsearch.yml确保keystore.path和truststore.path指向正确且没有拼写错误。特别注意YAML的缩进。检查密钥库密码如果你设置了密码确认已通过elasticsearch-keystore add ...正确添加并且添加到了每个节点。可以运行./bin/elasticsearch-keystore list查看已存储的密钥。验证证书内容使用openssl工具检查证书内容确认SAN主题备用名称字段包含正确的IP和DNS。# 查看证书信息需要输入密钥库密码 keytool -list -v -keystore config/certs/elastic-certificates.p12 -storetype pkcs12 # 或者导出证书后用openssl查看 openssl pkcs12 -in config/certs/elastic-certificates.p12 -clcerts -nokeys | openssl x509 -text -noout | grep -A 1 Subject Alternative Name检查防火墙和网络确保所有节点之间的9300端口传输端口是互通的。使用telnet或nc命令测试。查看详细日志在启动命令中加入-E log_leveltrace可以获取最详细的SSL握手日志但信息量巨大建议在明确问题范围后使用。7.2 客户端无法连接HTTP层问题症状应用程序、curl或Kibana无法连接到Elasticsearch的9200端口报错“证书验证失败”、“不受信的证书”等。排查步骤确认HTTPS已启用首先确认Elasticsearch的HTTP SSL配置已正确添加并重启。客户端信任CA客户端必须信任签发Elasticsearch HTTP证书的CA。对于自签名CA你需要将CA证书elastic-stack-ca.p12或导出的.pem文件分发给所有客户端并配置客户端信任它。对于curl使用--cacert参数指定CA证书。对于Java应用将CA证书导入到JVM的信任库cacerts或应用指定的信任库。对于Logstash/Beats在输出插件的配置中设置ssl.certificate_authorities路径。检查主机名验证如果客户端使用主机名连接而证书的SAN字段中没有该主机名验证会失败。确保生成HTTP证书时在--dns参数中包含了客户端使用的主机名。或者在客户端配置中临时禁用主机名验证不推荐生产环境。检查Kibana配置确保kibana.yml中的elasticsearch.hosts是https://开头并且elasticsearch.ssl.certificateAuthorities路径指向正确的CA证书文件。7.3 密钥库管理与密码轮换问题证书快过期了或者密码泄露了怎么办最佳实践证书轮换在证书过期前使用相同的CA生成新的证书使用新的有效期。然后采用“滚动重启”的方式逐个节点更新config/certs/下的证书文件并重启确保集群服务不中断。密码管理永远不要将密码硬编码在配置文件或脚本中。使用elasticsearch-keystore工具管理所有密码。对于自动化部署可以通过echo “password” | ./bin/elasticsearch-keystore add --stdin xpack.security.transport.ssl.keystore.secure_password非交互式地添加密码。CA安全将根CAelastic-stack-ca.p12的私钥离线保存放在一个极其安全的地方。在日常运维中使用由该根CA签发的中间CA来签发节点和服务证书。这样即使中间CA泄露可以快速吊销而不影响根CA。7.4 性能考量与调试启用TLS会带来一定的性能开销主要在于SSL握手时的非对称加密计算。但对于现代CPU和Elasticsearch通常的I/O密集型负载来说这个开销通常是可接受的。如果怀疑TLS导致性能问题可以使用jstat或类似工具监控JVM确认CPU是否大量消耗在加密计算上。考虑使用更高效的密码套件。在elasticsearch.yml中可以通过xpack.security.transport.ssl.cipher_suites和xpack.security.http.ssl.cipher_suites来指定。例如优先使用AES-GCM和TLSv1.3的套件它们通常有硬件加速。确保使用最新的Java版本和Elasticsearch版本它们往往包含最新的性能优化和安全补丁。配置Elasticsearch集群的TLS/SSL初看步骤繁多但本质上是一个标准化流程生成CA - 用CA签发证书 - 分发证书 - 配置启用。最难的部分往往不是执行命令而是理解证书、密钥库、信任链这些概念以及在复杂的网络环境中确保IP/DNS配置的完整性。一旦你成功配置过一次并理解了背后的逻辑后续的维护和问题排查就会变得有章可循。记住安全配置不是一次性的任务而是一个需要持续维护如证书轮换、密码更新的运维过程。把它纳入你的常规运维清单你的Elasticsearch集群才能真正在稳固的基础上提供服务。