Solr部署:SSL加密配置完整指南与安全实践

Solr部署:SSL加密配置完整指南与安全实践

Apache Solr可以通过安全套接字层(SSL)加密技术来保护客户端与服务器之间以及SolrCloud模式下节点之间的通信安全。本文将详细介绍如何配置Solr SSL加密,确保数据传输的机密性和完整性。

SSL配置概述

SSL(Secure Sockets Layer)是一种标准的网络安全协议,用于在网络连接中建立加密链接。在Solr环境中,SSL提供以下安全保障:

  • 数据加密:保护传输过程中的数据不被窃听
  • 身份认证:验证服务器和客户端的身份
  • 数据完整性:确保数据在传输过程中未被篡改

本指南主要介绍使用自签名证书启用SSL的方法。如需了解SSL证书和密钥的背景知识,请参考SSL证书HOWTO文档

为Solr配置SSL

生成自签名证书和密钥

首先,我们需要生成一个自签名证书和密钥,用于服务器和客户端的双向认证。我们将使用JDK的keytool命令创建一个独立的keystore,该keystore同时用作truststore。

在Solr二进制发行版的server/etc/目录中运行以下命令。确保JDK的keytool工具和openssl命令在您的系统PATH中。Windows和Solaris用户可以从OpenSSL官网获取OpenSSL二进制文件。

-ext SAN=...选项允许您指定在启用主机名验证时允许的所有DNS名称和/或IP地址。

以下示例除了包含localhost127.0.0.1外,还包含了运行Solr节点的机器的局域网IP地址192.168.1.3

1
2
3
4
5
keytool -genkeypair -alias solr-ssl -keyalg RSA -keysize 2048 \
-keypass secret -storepass secret -validity 9999 \
-keystore solr-ssl.keystore.p12 -storetype PKCS12 \
-ext SAN=DNS:localhost,IP:192.168.1.3,IP:127.0.0.1 \
-dname "CN=localhost, OU=Organizational Unit, O=Organization, L=Location, ST=State, C=Country"

上述命令将在当前目录中创建一个名为solr-ssl.keystore.p12的keystore文件。

将证书和密钥转换为PEM格式以便与curl配合使用

使用openssl命令将PKCS12格式的keystore(包括证书和密钥)转换为PEM格式:

1
openssl pkcs12 -in solr-ssl.keystore.p12 -out solr-ssl.pem

如果您想在OS X Yosemite (10.10)上使用curl,需要创建仅包含证书的PEM格式文件:

1
openssl pkcs12 -nokeys -in solr-ssl.keystore.p12 -out solr-ssl.cacert.pem

设置常见的SSL相关系统属性

Solr控制脚本已经设置好了向JVM传递SSL相关Java系统属性的功能。要激活SSL设置,需要在Unix系统的bin/solr.in.sh或Windows系统的bin\solr.in.cmd文件中取消注释并更新以SOLR_SSL_*开头的属性集合。

Unix系统配置

注意:如果您按照生产环境部署指南在Linux上将Solr设置为服务,则应在/var/solr/solr.in.sh中进行这些更改。

solr.in.sh配置示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 启用HTTPS。如果设置了SOLR_SSL_KEY_STORE,则隐式为true
# 使用此配置通过自定义jetty配置启用https模块
SOLR_SSL_ENABLED=true

# 取消注释以设置SSL相关系统属性
# 请确保更新路径为您环境中正确的keystore路径
SOLR_SSL_KEY_STORE=etc/solr-ssl.keystore.p12
SOLR_SSL_KEY_STORE_PASSWORD=secret
SOLR_SSL_TRUST_STORE=etc/solr-ssl.keystore.p12
SOLR_SSL_TRUST_STORE_PASSWORD=secret

# 要求客户端进行认证
SOLR_SSL_NEED_CLIENT_AUTH=false

# 允许客户端进行认证(但不强制要求)
SOLR_SSL_WANT_CLIENT_AUTH=false

# SSL证书包含默认验证的主机/IP"对等名称"信息
# 在多个主机上重用证书时,将此设置为false可以禁用这些检查
# 这也将用作是否启用SNI主机检查的默认值
SOLR_SSL_CHECK_PEER_NAME=true

Windows系统配置

solr.in.cmd配置示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
REM 启用HTTPS。如果设置了SOLR_SSL_KEY_STORE,则隐式为true
REM 使用此配置通过自定义jetty配置启用https模块
set SOLR_SSL_ENABLED=true

REM 取消注释以设置SSL相关系统属性
REM 请确保更新路径为您环境中正确的keystore路径
set SOLR_SSL_KEY_STORE=etc/solr-ssl.keystore.p12
set SOLR_SSL_KEY_STORE_PASSWORD=secret
set SOLR_SSL_TRUST_STORE=etc/solr-ssl.keystore.p12
set SOLR_SSL_TRUST_STORE_PASSWORD=secret

REM 要求客户端进行认证
set SOLR_SSL_NEED_CLIENT_AUTH=false

REM 允许客户端进行认证(但不强制要求)
set SOLR_SSL_WANT_CLIENT_AUTH=false

REM SSL证书包含默认验证的主机/IP"对等名称"信息
REM 在多个主机上重用证书时,将此设置为false可以禁用这些检查
REM 这也将用作是否启用SNI主机检查的默认值
set SOLR_SSL_CHECK_PEER_NAME=true

客户端认证设置

警告:启用SOLR_SSL_NEED_CLIENT_AUTHSOLR_SSL_WANT_CLIENT_AUTH中的任意一个,但不要同时启用两者。它们是互斥的,Jetty会选择其中一个,这可能不是您期望的结果。如果您想禁用客户端证书的主机名验证,应将SOLR_SSL_CLIENT_HOSTNAME_VERIFICATION设置为false。

当您启动Solr时,bin/solr脚本会包含这些设置并将它们作为系统属性传递给JVM。

如果您使用的是SolrCloud,在启动Solr之前需要配置ZooKeeper。

如果您运行的是用户管理的集群或单节点安装,可以直接跳到启动Solr的步骤。

通过Hadoop凭证存储分发密码

Solr支持从Hadoop凭证存储中读取keystore和truststore密码。如果密码轮换和分发已经由凭证存储处理,这种方法可能会很有用。

如果您不使用Hadoop凭证存储,可以跳过此步骤。

提供Hadoop凭证存储

创建Hadoop凭证存储文件,并使用实际的keystore密码定义以下条目:

1
2
3
4
solr.jetty.keystore.password
solr.jetty.truststore.password
javax.net.ssl.keyStorePassword
javax.net.ssl.trustStorePassword

注意,如果未设置javax.net.ssl.*配置,它们将回退到相应的solr.jetty.*配置。

配置Solr使用Hadoop凭证存储

Solr需要配置三个参数才能使用凭证存储文件获取keystore密码:

solr.ssl.credential.provider.chain

  • 必需参数,默认值:无
  • 凭证提供程序链,应设置为hadoop

SOLR_HADOOP_CREDENTIAL_PROVIDER_PATH

  • 必需参数,默认值:无
  • 凭证存储文件的路径

HADOOP_CREDSTORE_PASSWORD

  • 必需参数,默认值:无
  • 凭证存储的密码

Unix系统配置:

1
2
3
4
# solr.in.sh
SOLR_OPTS=" -Dsolr.ssl.credential.provider.chain=hadoop"
SOLR_HADOOP_CREDENTIAL_PROVIDER_PATH=localjceks://file/home/solr/hadoop-credential-provider.jceks
HADOOP_CREDSTORE_PASSWORD="credStorePass123"

Windows系统配置:

1
2
3
4
REM solr.in.cmd
set SOLR_OPTS=" -Dsolr.ssl.credential.provider.chain=hadoop"
set SOLR_HADOOP_CREDENTIAL_PROVIDER_PATH=localjceks://file/home/solr/hadoop-credential-provider.jceks
set HADOOP_CREDSTORE_PASSWORD="credStorePass123"

配置ZooKeeper

在创建上述keystore并启动任何SolrCloud节点之前,必须在ZooKeeper中配置Solr集群属性,以便Solr节点知道通过SSL进行通信。

本节假设您已经创建并启动了外部ZooKeeper。更多信息请参考ZooKeeper集群配置文档。

在任何Solr节点启动之前,需要将集群范围的urlScheme属性设置为https。以下示例使用Solr附带的bin/solr工具来完成此操作。

Unix系统:

1
bin/solr cluster --property urlScheme --value https --zk-host server1:2181,server2:2181,server3:2181

Windows系统:

1
bin/solr.cmd cluster --property urlScheme --value https --zk-host server1:2181,server2:2181,server3:2181

请确保为您的系统使用正确的zkhost值。如果您已设置ZooKeeper集群为Solr使用chroot,请确保在zkHost字符串中包含它,例如:--zk-host server1:2181,server2:2181,server3:2181/solr

更新现有集合的集群属性

如果您使用的是SolrCloud并且在启用SSL之前已创建了集合,则需要更新集群属性以使用HTTPS。

如果您没有现有集合或不使用SolrCloud,可以直接跳到启动Solr的步骤。

可以使用Collections API的CLUSTERPROP命令更新集群属性,如以下示例所示(根据您的系统更新主机名和端口):

1
curl "http://localhost:8983/solr/admin/collections?action=CLUSTERPROP&name=urlScheme&val=https"

此命令只需在集群的一个节点上运行,更改将应用于所有节点。

完成此步骤和所有其他步骤后,您就可以启动Solr了。

启用SSL后启动Solr

启动SolrCloud

注意:如果您在solr.in.sh/solr.in.cmd中定义了ZK_HOST(参见更新Solr包含文件),可以从以下所有bin/solr/bin\solr.cmd命令中省略-z <zk host string>

使用Solr控制脚本启动每个Solr节点,如以下示例所示。根据需要自定义显示参数的值,并添加系统中使用的任何参数。

如果您创建SSL密钥时没有包含运行Solr节点的所有DNS名称或IP地址,可以通过设置-Dsolr.ssl.checkPeerName=false系统属性来告诉Solr跳过节点间通信的主机名验证。

Unix系统:

1
bin/solr start --cloud --solr-home cloud/node1 -z server1:2181,server2:2181,server3:2181 -p 8984

Windows系统:

1
bin\solr.cmd --cloud --solr-home cloud\node1 -z server1:2181,server2:2181,server3:2181 -p 8984

启动用户管理的集群或单节点Solr

使用Solr控制脚本启动Solr,如以下示例所示。根据需要自定义显示参数的值,并添加系统中使用的任何参数。

Unix系统:

1
bin/solr start -p 8984

Windows系统:

1
bin\solr.cmd -p 8984

KeyStore/TrustStore自动重新加载

Solr服务器

Solr可以在证书更新时自动重新加载KeyStore/TrustStore而无需重启。使用SSL时此功能默认启用,但可以通过将环境变量SOLR_SSL_RELOAD_ENABLED设置为false来禁用。

默认情况下,Solr每30秒检查一次KeyStore更新,但可以通过在启动时传递系统属性solr.jetty.sslContext.reload.scanInterval(以秒为单位)来更新此间隔。

注意,truststore文件不会被主动监控,因此如果需要应用truststore更改,需要更新它并随后touch keystore文件以触发重新加载。

SolrJ客户端

Http2SolrClient构建器有一个withKeyStoreReloadInterval(long interval, TimeUnit unit)方法来初始化一个扫描器,该扫描器将监视和更新keystore和truststore的更改。如果您使用CloudHttp2SolrClient,可以使用withInternalClientBuilder(Http2SolrClient.Builder internalClientBuilder)配置内部http客户端的keystore重新加载间隔。

最小重新加载间隔为1秒。如果未设置(或设置为0或负值),客户端将不会更新keystore/truststore。

客户端操作示例

重要提示:OS X Mavericks (10.9)上的curl SSL支持有所降级。有关更多信息和允许单向SSL的解决方法,请参见相关文档。OS X Yosemite (10.10)上的curl得到了改进 - 支持双向SSL - 请参见相关文档

以下部分中的curl命令在OS X Yosemite (10.10)的系统curl中无法工作。相反,使用-E参数提供的证书必须是PKCS12格式,使用--cacert参数提供的文件必须仅包含CA证书,不包含密钥:

1
curl -E solr-ssl.keystore.p12:secret --cacert solr-ssl.cacert.pem ...

注意:如果您的操作系统不包含curl,可以从这里下载二进制文件:https://curl.se/download.html

使用bin/solr创建SolrCloud集合

使用_default配置集创建一个2分片、replicationFactor=1的名为mycollection的集合:

Unix系统:

1
bin/solr create -c mycollection --shards 2

Windows系统:

1
bin\solr.cmd create -c mycollection --shards 2

create操作将把包含文件中设置的SOLR_SSL_*属性传递给用于创建集合的SolrJ代码。

使用curl获取SolrCloud集群状态

要获取结果集群状态(如果您没有启用客户端认证,请移除-E solr-ssl.pem:secret选项):

1
2
curl -E solr-ssl.pem:secret --cacert solr-ssl.pem \
"https://localhost:8984/solr/admin/collections?action=CLUSTERSTATUS&indent=on"

您应该得到类似以下的响应:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
{
"responseHeader":{
"status":0,
"QTime":2041
},
"cluster":{
"collections":{
"mycollection":{
"shards":{
"shard1":{
"range":"80000000-ffffffff",
"state":"active",
"replicas":{"core_node1":{
"state":"active",
"base_url":"https://127.0.0.1:8984/solr",
"core":"mycollection_shard1_replica1",
"node_name":"127.0.0.1:8984_solr",
"leader":"true"
}}
},
"shard2":{
"range":"0-7fffffff",
"state":"active",
"replicas":{"core_node2":{
"state":"active",
"base_url":"https://127.0.0.1:7574/solr",
"core":"mycollection_shard2_replica1",
"node_name":"127.0.0.1:7574_solr",
"leader":"true"
}}
}
},
"router":{"name":"compositeId"},
"replicationFactor":"1"
}
},
"properties":{"urlScheme":"https"}
}
}

使用bin/solr post索引文档

使用bin/solr post将一些示例文档索引到上面创建的SolrCloud集合:

1
bin/solr post --solr-url https://localhost:8984 --name mycollection example/exampledocs/*.xml

使用curl查询

使用curl查询上面创建的SolrCloud集合,从包含上面创建的PEM格式证书和密钥的目录(例如,example/etc/)执行。如果您没有启用客户端认证(系统属性-Djetty.ssl.clientAuth=true),则可以移除-E solr-ssl.pem:secret选项:

1
2
curl -E solr-ssl.pem:secret --cacert solr-ssl.pem \
"https://localhost:8984/solr/mycollection/select?q=*:*"

使用CloudSolrClient索引文档

使用SolrJ的Java客户端索引文档。在下面的代码中,javax.net.ssl.*系统属性是通过编程方式设置的,但您也可以在java命令行中指定它们:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
System.setProperty("javax.net.ssl.keyStore", "/path/to/solr-ssl.keystore.p12");
System.setProperty("javax.net.ssl.keyStorePassword", "secret");
System.setProperty("javax.net.ssl.keyStoreType", "pkcs12");
System.setProperty("javax.net.ssl.trustStore", "/path/to/solr-ssl.keystore.p12");
System.setProperty("javax.net.ssl.trustStorePassword", "secret");
System.setProperty("javax.net.ssl.trustStoreType", "pkcs12");

String zkHost = "127.0.0.1:2181";
CloudSolrClient client = new CloudSolrClient.Builder(
Collections.singletonList(zkHost), Optional.empty())
.withDefaultCollection("mycollection")
.build();

SolrInputDocument doc = new SolrInputDocument();
doc.addField("id", "1234");
doc.addField("name", "A lovely summer holiday");
client.add(doc);
client.commit();

生产环境最佳实践

证书管理建议

  1. 使用CA签发的证书:在生产环境中,强烈建议使用由受信任的证书颁发机构(CA)签发的证书,而不是自签名证书。

  2. 证书轮换策略:建立定期更新SSL证书的流程,并利用Solr的自动重新加载功能实现无缝更新。

  3. 密钥长度:使用至少2048位的RSA密钥或256位的ECC密钥以确保足够的安全性。

安全配置建议

  1. 禁用弱加密套件:配置Jetty以禁用弱加密算法和协议。

  2. 启用HSTS:在生产环境中启用HTTP严格传输安全(HSTS)以防止降级攻击。

  3. 网络隔离:将Solr部署在安全的网络环境中,使用防火墙限制访问。

性能优化

  1. 硬件加速:在支持的平台上启用SSL硬件加速以提高性能。

  2. 连接池:适当配置SSL连接池以减少握手开销。

  3. 监控指标:定期监控SSL相关的性能指标,及时发现和解决性能问题。

通过本指南的详细配置,您可以为Apache Solr成功启用SSL加密,确保数据传输的安全性。记住在生产环境中遵循最佳安全实践,定期更新证书和审查安全配置。

© 2025 Solr Community of China All Rights Reserved. 本站访客数人次 本站总访问量
Theme by hiero