Redis容器内外TLS连接异常:外部可连内部失败排查
问题场景
我在Docker中部署了启用TLS的Redis服务,连接到名为site的外部Docker网络。Redis配置了bind * -::*、protected-mode no、tls-auth-clients no,主机通过redis-cli --tls -p 2999可以成功连接,但进入Redis容器内部执行redis-cli --tls -p 6379时,Redis日志报错:
1:M 28 Feb 2025 01:17:38.495 - Accepted 127.0.0.1:47094
1:M 28 Feb 2025 01:17:38.498 # Error accepting a client connection: error:0A000418:SSL routines::tlsv1 alert unknown ca (addr= laddr=127.0.0.1:6379)
1:M 28 Feb 2025 01:17:42.880 . 0 clients connected (0 replicas), 946440 bytes in use
相关配置
docker-compose.yml
services: redis: image: redis networks: - site ports: - "2999:6379" volumes: - ./redis.conf:/etc/redis.conf - ./redis.log:/etc/redis.log - /etc/privkey.pem:/etc/privkey.pem:ro - /etc/cert.pem:/etc/cert.pem:ro - /etc/fullchain.pem:/etc/fullchain.pem:ro - /etc/isrgrootx1.pem:/etc/ca.pem:ro networks: site: external: true
redis.conf核心配置片段
bind * -::* protected-mode no port 0 tls-port 6379 tls-cert-file /etc/fullchain.pem tls-key-file /etc/privkey.pem tls-ca-cert-file /etc/ca.pem tls-ca-cert-dir /etc/ tls-auth-clients no
两种连接的核心差异
- 主机端连接:通过Docker端口映射
2999:6379访问,主机上的redis-cli使用主机系统默认的根CA证书库验证Redis服务端证书。Let's Encrypt的根证书已被绝大多数操作系统信任,因此验证流程顺利通过。 - 容器内部连接:直接访问容器本地的
127.0.0.1:6379,容器内的redis-cli默认读取容器自身的CA证书信任目录(如/etc/ssl/certs/),但你仅将Let's Encrypt根证书挂载到了/etc/ca.pem,未告知redis-cli使用该文件,导致客户端无法识别服务端证书的签发CA,触发验证失败。
失败原因详解
Redis的tls-auth-clients no仅表示不要求客户端提供自身证书,但TLS协议的单向验证(客户端验证服务端证书合法性)仍会强制执行。容器内的redis-cli在未指定--cacert参数时,不会自动加载你挂载的/etc/ca.pem,因此无法确认服务端证书的签发机构是否可信,最终导致连接被拒绝。
解决方法
方法一:连接时指定CA证书
在容器内执行redis-cli时,显式指定CA证书路径:
redis-cli --tls -p 6379 --cacert /etc/ca.pem
方法二:将CA证书加入容器默认信任库
进入容器后,将挂载的CA证书复制到系统默认CA目录并更新信任列表:
cp /etc/ca.pem /etc/ssl/certs/ update-ca-certificates
之后再执行redis-cli --tls -p 6379即可正常连接。
内容的提问来源于stack exchange,提问作者Kelsey Williams

