tar -zxvf redis-6.2.6.tar.gz -C /opt
cd /opt/redis-6.2.6/ # 要建立TLS通信,则必须要使用TLS支持进行构建,需要OpenSSL开发库 make MALLOC=libc BUILD_TLS=yes # 构建编译执行完成后,进行指定目录安装,将启动bin目录指定安装到/opt/redis 目录 make PREFIX=/opt/redis install # 添加环境变量 echo 'PATH=/opt/redis/bin:$PATH' >> /etc/profile source /etc/profile # 添加配置redis文件 mkdir -p /opt/redis/conf #将自定义的配置文件上传到 /opt/redis/conf目录下,下方可参考个人使用的配置文件 # 为防止redis启动存在警告添加系统配置参数 echo vm.overcommit_memory = 1 >> /etc/sysctl.conf; sysctl -p # 分别创建日志存放目录及数据目录 mkdir -p /opt/redis/logs mkdir -p /opt/redis/data
创建证书存放目录
mkdir -p /opt/redis/ssl
分别生成CA证书及客户端证书,key等文件
# 进入上诉新建的证书存放目录 cd /opt/redis/ssl # 依次执行以下命令生成证书 openssl genrsa -out ca.key 4096 openssl req -x509 -new -nodes -sha256 -key ca.key -days 3650 -subj '/O=Redis Test/CN=Certificate Authority' -out ca.crt openssl genrsa -out redis.key 2048 openssl req -new -sha256 -key redis.key -subj '/O=Redis Test/CN=Server' | openssl x509 -req -sha256 -CA ca.crt -CAkey ca.key -CAserial ca.txt -CAcreateserial -days 365 -out redis.crt openssl dhparam -out redis.dh 2048
证书生成截图如下:
##########################################基础参数配置############################################ bind 0.0.0.0 protected-mode no #端口0代表完全禁用非TLS端口 port 0 tls-port 6380 tcp-backlog 511 unixsocket /tmp/redis.sock unixsocketperm 700 timeout 0 tcp-keepalive 300 daemonize yes supervised no pidfile /etc/redis/pid/redis.pid loglevel notice logfile /opt/redis/logs/redis.log databases 0 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 /opt/redis/data #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 ################################## 安全认证 ################################### requirepass 123456 rename-command CONFIG b840fc02d524045429941cc43f59e41cb7be6c52 ################################## TLS 配置 ################################### tls-cert-file /opt/redis/ssl/redis.crt tls-key-file /opt/redis/ssl/redis.key tls-ca-cert-file /opt/redis/ssl/ca.crt tls-dh-params-file /opt/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 #rejson.so #loadmodule /usr/local/redis-6.2.0/module/rejson.soo ######################### 高级设置 ######################### 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
cd /opt/redis/ ./bin/redis-server ./conf/redis.conf
redis-cli --tls --cert /opt/redis/ssl/redis.crt --key /opt/redis/ssl/redis.key --cacert /opt/redis/ssl/ca.crt -p 6380
验证截图:
以上即完成Redis6.x的TLS安全通道配置部署。
将上述中生成的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(); } } }
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");
由上,我们可以发现key为test的数据已存入redis中。