资讯动态

Elasticsearch集群安全配置:TLS/SSL与密钥库管理全解析

发布时间:2026/10/21 5:49:14 来源:尧图企业网站定制
给Elasticsearch集群做安全配置这件事远比想象中麻烦。很多人以为在elasticsearch.yml里加几行TLS/SSL配置就能收工结果往往是节点之间互相不认证书、Kibana连不上、客户端报handshake failed最后只能回滚。我这次把一套三节点ES集群从裸HTTP切换到全链路TLS加密顺便把密钥库管理的坑也踩了个遍。这篇就是第07篇针对Elasticsearch集群安全配置中最核心的TLS/SSL与密钥库管理把原理、实操和排障完整捋一遍。1. 为什么非做集群安全不可1.1 裸奔的HTTP和Transport端口等于把数据写在明信片上Elasticsearch安装完成后默认是“零安全”状态HTTP端口9200直接以明文对外服务节点之间的Transport端口9300也是明文通信。很多初学者觉得“内网环境不用加密”但现实往往是一旦有运维同事误开放了端口或者内网被攻破一台机器攻击者就能直接用HTTP请求把索引里的数据全部拉走连密码都不需要。更重要的是节点间通信。ES节点之间要同步分片、选举主节点这些数据通过9300端口传递。如果这个链路明文裸露抓包工具可以直接看到索引内容、文档内容甚至能伪造一个节点加入集群。这种风险用“明信片”来类比再合适不过你往信封里塞了重要资料结果邮局一路上都是透明玻璃谁路过都能瞄一眼。TLS/SSL要解决的就是把明信片换成加密邮件。1.2 安全配置三件事传输加密、节点可信、客户端可信真正把ES集群做安全不只是加个证书那么简单。拆开看需要解决三个独立问题传输加密HTTP层和Transport层的数据包必须加密防止被抓包后直接读明文。节点可信新节点加入集群时必须证明“我是自己人”而不是随便一个伪装进程连上9300端口就能混进来。客户端可信Kibana、Java程序、脚本调用ES时既要验证ES服务端证书是否可信也需要决定是否要求客户端出示自己的证书。这三个问题对应的技术方案就是TLS/SSL协议和PKI证书体系。HTTP层的TLS保护REST APITransport层的TLS保护节点间通信而证书体系解决“谁可信”的问题。1.3 基础版安全能力边界不同发行版和版本在安全功能上差异不小。这里说的是常用场景官方发行版的基础安全功能在6.8之后已经支持TLS加密、内置用户认证、基于角色的访问控制等并不需要额外购买商业插件。7.x、8.x的配置方式有细微差别8.x默认开启安全7.x默认关闭所以如果你还在维护7.x集群这一篇的配置方法仍然很通用。需要提醒的是开启安全后内置的elastic超级用户默认没有密码必须通过初始化脚本设置。这一步很多人会漏结果集群看似起来了实际上所有请求都被401拒绝。2. 证书体系与密钥库管理的核心概念2.1 CA、证书链和“信任”这件事HTTPS的信任模型用一个生活化例子理解最方便你去一家公司办事前台不认识你但你掏出身份证件身份证上有公安局的印章前台认这个印章于是认你。这里的“公安局”就是CA证书颁发机构身份证就是证书身份证上的印章就是CA的数字签名。自建ES集群时我们不需要找外面的公共CA买证书完全可以自己做“公安局”也就是自建CA。用这个CA给每个节点签发身份证节点证书然后让所有节点都信任这个CA。只要证书是由同一个CA签发的节点之间就天然互相认可。这也是为什么我强烈建议自建CA而不是直接生成自签名证书自签名证书相当于你自己给自己盖了个章别的节点不认识而统一CA签发的证书所有节点都认同一套信任链。2.2 PKCS12、JKS、PEM三者的选择和证书打交道时你一定会碰到三种文件格式别被它们绕晕格式后缀内容典型工具适用场景PEM.crt / .key / .pemBase64文本证书或私钥OpenSSLNginx、Kibana等大量中间件PKCS12.p12 / .pfx二进制容器可同时装证书和私钥keytool、certutilJava体系、ES最推荐JKS.jksJava专用密钥库keytool老版本Java应用Elasticsearch官方最推荐PKCS12原因很直接它可以把私钥、证书、信任的CA都放进一个文件里用密码保护配置路径也简单。PEM的好处是肉眼可读、方便调试但在ES里要分别配置证书路径、私钥路径、CA路径稍有遗漏就会握手失败。2.3 Keystore和Truststore到底谁管谁密钥库这个概念经常把新手搞糊涂。简单记住两句话Keystore密钥库存放“我自己的身份证明”包括私钥和配套证书。对外通信时我用它证明我是谁。Truststore信任库存放“我信任的CA证书”用于验证对方出示的证书是否合法。用一个场景串起来A节点连接B节点时A把自己的证书从Keystore里取出来发给BB收到后拿着Truststore里的CA证书去验证A的证书签名验过了才建立加密通道。所以每个节点既要有Keystore证明自己也要有Truststore验证别人。在ES里如果你使用单个PKCS12文件这个文件可以同时扮演Keystore和Truststore角色既存放自己的私钥证书也存放CA证书配置时通常把同一个路径写在两处或者只写Keystore路径并让ES复用其中包含的CA。PEM模式下则必须分别指定三个路径。3. 动手签发证书使用内置certutil搭建企业级CA3.1 集群规划节点、域名、IP怎么定假设现在有一套三节点集群规划如下节点名IP域名角色node1192.168.1.11es-node1.internal.examplemaster datanode2192.168.1.12es-node2.internal.examplemaster datanode3192.168.1.13es-node3.internal.examplemaster data证书里的IP和域名不是随便写的。TLS握手时客户端或另一个节点会检查访问地址是否和证书里的“使用者备用名称”匹配也就是SANSubject Alternative Name。如果你的证书只写了域名却用IP访问握手会直接失败。所以我建议只要IP会被直接访问就必须把IP写进证书SAN如果Kibana会通过域名访问也要把域名写进去。3.2 创建自建CA在node1上执行官方自带的证书工具cd /usr/share/elasticsearch bin/elasticsearch-certutil ca --pem --out ca.zip执行后输入CA密码这里建议设置一个强密码并妥善保存。命令会在当前目录生成ca.zip解压后得到ca/ca.crt和ca/ca.key前者是CA根证书后者是CA私钥。也有很多人图省事会直接跳过CA文件但我的习惯是把CA单独保存到安全目录后续签发新节点证书、轮换证书都能复用。没有这套CA以后想加节点要么全部重新签发要么就得再建一套信任体系非常痛苦。3.3 为每个节点签发证书拿到CA后为三个节点分别签发证书。以node1为例bin/elasticsearch-certutil cert --pem \ --ca-cert ca/ca.crt \ --ca-key ca/ca.key \ --ca-pass 你的CA密码 \ --name node1 \ --dns es-node1.internal.example,localhost \ --ip 192.168.1.11,127.0.0.1 \ --out node1.zipnode2、node3把--name、--dns、--ip换成对应值即可。解压后每个zip里包含node1.crt和node1.key分别是对应节点的证书和私钥。这里有两个容易踩的小坑。第一个是--dns里必须带localhost、--ip里带127.0.0.1否则本机使用curl https://localhost:9200做自检时也会报主机名不匹配。第二个是CA私钥如果设置了密码--ca-pass必须正确否则签不出来证书。3.4 密钥库分发与权限检查如果你更习惯PKCS12方式可以用certutil直接生成p12文件一个文件里同时包含证书、私钥和CAbin/elasticsearch-certutil cert \ --ca-cert ca/ca.crt \ --ca-key ca/ca.key \ --ca-pass 你的CA密码 \ --dns es-node1.internal.example,es-node2.internal.example,es-node3.internal.example,localhost \ --ip 192.168.1.11,192.168.1.12,192.168.1.13,127.0.0.1 \ --out elastic-certificates.p12这种方式生成的p12在所有节点上可以用同一个文件因为它包含所有节点的SAN。不过生产环境我仍建议每节点独立证书这样某台机器私钥泄露时只用吊销那一台不至于整个集群信任体系崩掉。证书文件复制到每个节点的config/certs目录后马上做两个检查chown -R elasticsearch:elasticsearch /usr/share/elasticsearch/config/certs chmod 600 /usr/share/elasticsearch/config/certs/*私钥和p12文件权限必须锁死否则ES启动时会因为“权限过于开放”直接拒绝加载密钥库。4. 配置TLS三节点集群加密落地4.1 elasticsearch.yml中的Transport层TLS配置把node1的config/elasticsearch.yml打开在末尾追加一段。使用PEM证书方式的Transport配置如下xpack.security.enabled: true xpack.security.transport.ssl.enabled: true xpack.security.transport.ssl.verification_mode: certificate xpack.security.transport.ssl.certificate: certs/node1.crt xpack.security.transport.ssl.key: certs/node1.key xpack.security.transport.ssl.certificate_authorities: certs/ca/ca.crt注意路径是相对于config目录的。verification_mode我建议先写成certificate它表示只验证证书是否由受信CA签发不做主机名严格匹配。写成full意味着还要校验对方证书里的域名/IP与访问地址一致在节点间通信时非常容易因为DNS解析问题翻车。如果是p12方式配置是这样xpack.security.transport.ssl.keystore.path: certs/elastic-certificates.p12 xpack.security.transport.ssl.truststore.path: certs/elastic-certificates.p124.2 HTTP层TLS配置HTTP层负责对外提供REST API这一步必须有否则你从客户端访问还是明文。继续追加xpack.security.http.ssl.enabled: true xpack.security.http.ssl.certificate: certs/node1.crt xpack.security.http.ssl.key: certs/node1.key xpack.security.http.ssl.certificate_authorities: certs/ca/ca.crt xpack.security.http.ssl.client_authentication: noneclient_authentication先保持none表示服务端只出示证书不强制要求客户端出示证书。等Kibana、Java客户端都跑通了再按需求升级成双向认证否则一开始就开双向认证排错难度会翻倍。三个节点都要把上面配置写上只是证书路径换成各自的节点证书。4.3 密钥库密码的安全存储如果你用了p12文件ES默认会要求你提供密钥库密码。这个密码不能直接写进elasticsearch.yml因为它是明文文件权限再严也有泄露风险。ES提供了专门的secure settings机制cd /usr/share/elasticsearch bin/elasticsearch-keystore add xpack.security.transport.ssl.keystore.secure_password bin/elasticsearch-keystore add xpack.security.transport.ssl.truststore.secure_password bin/elasticsearch-keystore add xpack.security.http.ssl.keystore.secure_password执行后会交互式输入密码密码被加密存储在config/elasticsearch.keystore中。PEM模式如果想给私钥单独设置密码对应设置项是xpack.security.transport.ssl.secure_key_passphrase。这一步很容易漏。我见过有人配置好了所有路径ES启动时仍然报keystore password was incorrect原因就是忘了把密码写进elasticsearch-keystore。4.4 初始化密码与启动集群所有节点配置完成后按顺序逐台启动。全部起来后执行内置密码初始化bin/elasticsearch-setup-passwords auto这个脚本会连接集群为elastic、kibana_system等内置用户生成随机密码在终端打印出来。建议立刻保存。如果你希望密码可控可以用bin/elasticsearch-setup-passwords interactive此时用curl验证HTTP层加密是否生效curl -u elastic:你的密码 \ --cacert /usr/share/elasticsearch/config/certs/ca/ca.crt \ https://192.168.1.11:9200正常会返回集群信息。如果去掉--cacert一定会报证书验证失败这恰恰说明TLS已经生效。5. 客户端接入TLScurl、Kibana、Java5.1 三种客户端信任姿势TLS加密只是第一步客户端要访问ES还必须“信任”集群的证书。不同客户端有不同做法curl用--cacert指定CA证书。Kibana在kibana.yml里配置elasticsearch.ssl.certificateAuthorities。Java程序在SSLContext里加载Truststore。以Kibana为例kibana.yml核心配置如下server.host: 0.0.0.0 server.ssl.enabled: true server.ssl.certificate: /etc/kibana/certs/kibana.crt server.ssl.key: /etc/kibana/certs/kibana.key elasticsearch.hosts: [https://es-node1.internal.example:9200] elasticsearch.ssl.certificateAuthorities: [/etc/kibana/certs/ca/ca.crt]这里Kibana自身也开启了SSL浏览器访问Kibana时用的就是Kibana的证书。如果浏览器不想装CA证书可以暂时跳过验证但生产环境一定要把CA导入受信列表。5.2 单向认证与双向认证怎么选默认client_authentication: none是单向认证客户端验证服务端证书服务端不验证客户端。这种模式适合Web应用、数据分析工具配置简单绝大多数场景够用。如果你们安全规范要求“只有持证客户端才能访问ES”就把HTTP层改成双向xpack.security.http.ssl.client_authentication: required改成required之后curl命令也必须带上客户端证书和私钥curl -u elastic:密码 \ --cacert /path/ca.crt \ --cert /path/client.crt \ --key /path/client.key \ https://192.168.1.11:9200Kibana也要配客户端证书否则连不上ES。我的建议是如果只是内部工具使用单向足够如果ES直接暴露给第三方系统双向更稳而且一定要配合用户认证一起用。5.3 Java客户端里的SSLContext配置Java里的ES客户端最常用RestClient通过Apache HttpClient发送请求。连接HTTPS集群时需要手动构建SSLContextKeyStore trustStore KeyStore.getInstance(PKCS12); try (InputStream in new FileInputStream(/path/truststore.p12)) { trustStore.load(in, 密码.toCharArray()); } SSLContext sslContext SSLContexts.custom() .loadTrustMaterial(trustStore, null) .build(); RestClient client RestClient.builder( new HttpHost(es-node1.internal.example, 9200, https)) .setHttpClientConfigCallback(httpClientBuilder - httpClientBuilder.setSSLContext(sslContext)) .build();这里最关键的是Truststore里必须包含ES集群的CA证书。很多Java程序启动时报PKIX path building failed十有八九就是没有正确加载Truststore。Hostname验证方面如果证书SAN里有对应域名不需要额外关闭验证如果一定要用IP访问但证书里没有IP那才需要自己写HostnameVerifier不推荐为了省事直接NoopHostnameVerifier。6. 常见问题、坑位与排查实录6.1 节点之间互相不认握手失败最典型的报错是javax.net.ssl.SSLHandshakeException日志里能看到PKIX path building failed或者No trusted certificate found。原因基本是节点证书不是由同一CA签发或者certificate_authorities路径写错。排查思路很简单在所有节点上分别执行openssl verify用CA证书验证节点证书openssl verify -CAfile /usr/share/elasticsearch/config/certs/ca/ca.crt \ /usr/share/elasticsearch/config/certs/node1.crt如果验证失败说明证书签发关系有问题需要重新用同一CA签一份。如果验证通过就去检查各节点certificate_authorities是否都指向同一个ca.crt。6.2 验证模式坑verification_mode到底是certificate还是full我在排障时遇到过这样一个案例A节点和B节点连接时A一直报peer not authenticated但证书明明是好的。最后发现是verification_mode设成了full而A访问B时用的地址是IP 192.168.1.12B的证书里也写了这个IP按理说应该能通过。问题出在ES的Transport模式是双向连接节点名解析和连接地址可能不一致导致主机名校验失败。我的经验是在节点间Transport层certificate模式已经足够安全它确保对方证书受信且私钥匹配只是不校验主机名。把full留给对公网的HTTPS场景更合理。6.3 启动时找不到证书或权限损坏ES启动失败日志提示Private key is encrypted but no key passphrase is configured或Permission denied这类问题多半不在证书本身而在文件路径和权限。检查项如下配置文件里的路径是否相对于config目录写对。证书目录的属主是否为启动ES的系统用户。私钥或p12文件权限是否为600。路径末尾是否误写了空格。另外配置文件路径里不要用/etc/elasticsearch之类的绝对路径除非你确认目录属主和权限没问题。保持默认的config/certs相对路径最省心。6.4 忘记密码、证书过期、滚动替换密码遗忘这种事真发生了也别慌。如果只是密钥库密码丢了可以重新生成elasticsearch.keystore再执行elasticsearch-keystore add重新输入。如果elastic用户密码忘了在任意节点执行elasticsearch-setup-passwords interactive重新设置一遍即可但要注意这个操作会覆盖所有内置用户密码。证书过期是另一个高频问题。生产集群证书到期前一个月最好做一次滚动替换。流程是用原有CA重新签发新节点证书把新文件放到对应位置逐台重启节点。因为CA没变其他节点的Truststore不用改替换成本很低。这再次印证了自建CA的价值只要CA私钥还在换节点证书是几分钟的事。6.5 问题排查速查表现象可能原因处理方式握手失败PKIX path building failed客户端Truststore缺少CA用--cacert或把CA加入Truststore握手失败hostname in certificate didnt match访问地址不在证书SAN中用证书里的域名访问或重签证书加IP节点无法加入集群各节点Truststore不一致统一所有节点使用同一CA及证书启动报keystore password was incorrect密钥库密码未写进elasticsearch-keystore执行elasticsearch-keystore add设置密码日志提示Permission denied证书文件或目录权限不对设置属主为es用户权限600访问9200被拒绝安全已开启但未初始化密码执行elasticsearch-setup-passwords auto证书过期未做到期维护用原有CA重签并逐节点滚动重启最后分享一个我在实际运维中养成的习惯每次配置集群安全前先把整套步骤在本地一台临时节点上跑一遍确认证书路径、密码、验证模式都没问题再批量同步到生产节点。TLS配置的报错信息有时很绕但只要掌握“CA统一、路径正确、权限严密、密码进keystore”这四条主线大多数问题都能快速定位。ES集群安全没有想象中那么高不可攀认真做一次后面就是长期稳定运行。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑