安装
# 安装依赖软件
sudo apt update
sudo apt install make gcc libssl-dev pkg-config
# 下载redis 解压
wget https://download.redis.io/releases/redis-6.2.6.tar.gz
tar -xvf redis-6.2.6.tar.gz
# 编译
cd redis-6.2.6
make BUILD_TLS=yes
# 如果执行编译出错,提示 zmalloc.h:50:10: fatal error: jemalloc/jemalloc.h: No such file or directory 执行 MALLOC=libc
make BUILD_TLS=yes MALLOC=libc
make install
#拷贝命令到环境变量中
cd src
cp redis-sentinel redis-cli redis-server /usr/bin/
#overcommit_memory设置为1
echo "vm.overcommit_memory = 1" >>/etc/sysctl.conf
sysctl -p #生效
规划目录及证书
# 创建目录
mkdir -p /etc/redis/{conf,ssl,logs,pid,data}
# 创建集群存储目录(看情况实现)
for i in $(seq 1 6); do mkdir -p /etc/redis/data/698$i; done
# 创建证书
./utils/gen-test-certs.sh
# 拷贝证书都指定位置
cp tests/tls/redis.* /etc/redis/ssl/
cp tests/tls/ca.crt /etc/redis/ssl/
编写配置文件
##########################################基础参数配置############################################
bind 0.0.0.0
protected-mode no
#端口0代表完全禁用非TLS端口
port 0
# 单机集群端口不能一致
tls-port 6981
tcp-backlog 511
unixsocket /tmp/redis.sock
unixsocketperm 700
timeout 0
tcp-keepalive 300
daemonize yes
supervised no
pidfile /etc/redis/pid/redis_6981.pid
loglevel notice
logfile /etc/redis/logs/redis_6981.log
databases 16
always-show-logo yes
################################# 持久化配置 #################################
#RDB 快照持久化
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
# 设置对应的存储位置
dir /etc/redis/data/6981
#AOF 持久化
appendonly no
appendfilename appendonly.aof
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
aof-rewrite-incremental-fsync yes
################################# cluser配置 #################################
masterauth 123456
cluster-enabled yes
cluster-config-file nodes_6981.conf
cluster-node-timeout 15000
################################## 安全认证 ###################################
requirepass 123456
rename-command CONFIG b840fc02d524045429941cc43f59e41cb7be6c52
################################## TLS 配置 ###################################
tls-cert-file /etc/redis/ssl/redis.crt
tls-key-file /etc/redis/ssl/redis.key
tls-ca-cert-file /etc/redis/ssl/ca.crt
tls-dh-params-file /etc/redis/ssl/redis.dh
tls-auth-clients yes
tls-replication yes
#指定tls-replication yes才能将TLS用于到主服务器的对外连接,sentinel也需要同步设置。
tls-cluster yes
################################## 连接配置 ##################################
maxclients 10000
############################# 懒惰的释放 ####################################
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
################################ LUA时间限制 ###############################
lua-time-limit 5000
############################### 慢日志 ################################
slowlog-log-slower-than 10000
slowlog-max-len 128
######################### 高级设置 #########################
activerehashing yes
#缓存空间限制
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 1024mb 256mb 300
client-output-buffer-limit pubsub 32mb 8mb 60
client-query-buffer-limit 1gb
#加快写入rdb 和aof
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes
######################### 多线程设置 #########################
## 设置线程数,不超过CPU可用总核数
#io-threads 4
## 设置yes 开启多线程
#io-threads-do-reads yes
后续配置文件操作
# 复制配置文件
for i in $(seq 2 6); do cp /etc/redis/conf/redis_6981.conf /etc/redis/conf/redis_698$i.conf; done
# 修改配置文件
for i in $(seq 2 6); do sed -i "s/6981/698$i/g" redis_698$i.conf;done
创建cluster 集群
redis-cli --tls --cert /etc/redis/ssl/redis.crt \
--key /etc/redis/ssl/redis.key \
--cacert /etc/redis/ssl/ca.crt -a 123456 \
--cluster create --cluster-replicas 1 \
192.168.50.235:6981 192.168.50.235:6982 192.168.50.235:6983 \
192.168.50.235:6984 192.168.50.235:6985 192.168.50.235:6986
验证cluster 集群
# 登录
redis-cli --tls --cert /etc/redis/ssl/redis.crt --key /etc/redis/ssl/redis.key --cacert /etc/redis/ssl/ca.crt -c -p 6981
# 查看集群信息
cluster info
# 列出集群所有节点
cluster nodes
Jedis进行SSL连接redis操作
-
将上述中生成的ca.cert、redis.cert、redis.key文件提取出来放在我们java项目中的resource目录下(当然我只是测试所以没有规范存放): -
编写SSLSocketFactory生成类 此处参考相关博客链接:https://blog.csdn.net/weixin_43803007/article/details/105513034 引入项目Maven依赖: -
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.60</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.60</version>
</dependency> 生成SSLSocketFactory代码示例:
package com.weichai.config;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMDecryptorProvider;
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
import org.springframework.core.io.ClassPathResource;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.Security;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
/**
* SocketFactory
* @date 2021/12/20 16:43
* @Description socket工厂
*/
public class SocketFactory {
/**
* 创建 SSLSocketFactory 工厂
*
* @param caCrtFile 服务端 CA 证书
* @param crtFile 客户端 CRT 文件
* @param keyFile 客户端 Key 文件
* @param password SSL 密码,随机
* @return {@link SSLSocketFactory}
* @throws Exception 异常
*/
public static SSLSocketFactory getSocketFactory(final String caCrtFile, final String crtFile, final String keyFile, final String password) throws Exception {
InputStream caInputStream = null;
InputStream crtInputStream = null;
InputStream keyInputStream = null;
try {
Security.addProvider(new BouncyCastleProvider());
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// load CA certificate
caInputStream = new ClassPathResource(caCrtFile).getInputStream();
X509Certificate caCert = null;
while (caInputStream.available() > 0) {
caCert = (X509Certificate) cf.generateCertificate(caInputStream);
}
// load client certificate
crtInputStream = new ClassPathResource(crtFile).getInputStream();
X509Certificate cert = null;
while (crtInputStream.available() > 0) {
cert = (X509Certificate) cf.generateCertificate(crtInputStream);
}
// load client private key
keyInputStream = new ClassPathResource(keyFile).getInputStream();
PEMParser pemParser = new PEMParser(new InputStreamReader(keyInputStream));
Object object = pemParser.readObject();
PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(password.toCharArray());
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
KeyPair key;
if (object instanceof PEMEncryptedKeyPair) {
System.out.println("Encrypted key - we will use provided password");
key = converter.getKeyPair(((PEMEncryptedKeyPair) object).decryptKeyPair(decProv));
} else {
System.out.println("Unencrypted key - no password needed");
key = converter.getKeyPair((PEMKeyPair) object);
}
pemParser.close();
// CA certificate is used to authenticate server
KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType());
caKs.load(null, null);
caKs.setCertificateEntry("ca-certificate", caCert);
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init(caKs);
// client key and certificates are sent to server so it can authenticate
// us
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, null);
ks.setCertificateEntry("certificate", cert);
ks.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(), new java.security.cert.Certificate[]{cert});
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, password.toCharArray());
// finally, create SSL socket factory
SSLContext context = SSLContext.getInstance("TLSv1.2");
context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
return context.getSocketFactory();
}
finally {
if (null != caInputStream) {
caInputStream.close();
}
if (null != crtInputStream) {
crtInputStream.close();
}
if (null != keyInputStream) {
keyInputStream.close();
}
}
}
public static void main(String[] args) {
try {
SSLSocketFactory socketFactory = getSocketFactory("ca.crt", "redis.crt", "redis.key", "D8769D08908529D6");
System.out.println(666);
} catch (Exception e) {
e.printStackTrace();
}
}
}
-
jedis使用SSL调用redis服务示例
SSLSocketFactory socketFactory = SocketFactory.getSocketFactory("ca.crt", "redis.crt", "redis.key", "D8769D08908529D6");
JedisPool jedisPool = new JedisPool(new JedisPoolConfig(),
"127.0.0.1",
6380,
0,
"123456",
true,
socketFactory,null,null);
Jedis resource = jedisPool.getResource();
resource.set("test","123");
|