백엔드 데이터 인프라 71편. Redis TLS — 클라이언트·replication·cluster bus 전송 암호화. tls-cert-file·tls-key-file·tls-ca-cert-file 설정, mTLS (client cert 인증), Spring Boot 통합, 성능 부담과 절충까지 풀어쓴 학습 노트.
이 글은 백엔드 데이터 인프라 시리즈 130편 중 71편이에요. 70편 에서 인증·권한 관리 를 풀었다면, 보안의 두 번째 — TLS (전송 암호화). Part 4-5 운영의 마지막 글이고, 보안의 두 번째 축.
Redis TLS가 어렵게 느껴지는 이유
TLS 자체는 HTTPS 와 동일 한 개념인데, Redis 특유의 자리가 두 가지예요.
첫째로 여러 통신 경로가 있어요. 클라이언트-Redis 외에 Redis 끼리 (replication), Sentinel 끼리, Cluster bus 등 모두 별도로 TLS 활성화가 필요한데, 한 가지만 켜면 나머지 통신은 평문 그대로예요.
둘째는 Build-time 옵션이에요. Redis 가 기본 빌드에 TLS 미포함이라 make BUILD_TLS=yes 로 컴파일하거나 TLS 포함 빌드된 패키지 를 써야 해요. 기본 docker 이미지·apt 패키지 중에 TLS 빠진 것이 있어요.
이 글에서 TLS 빌드·기본 설정·mTLS (상호 TLS 인증)·각 통신 경로별 설정·성능 부담·운영 가이드 정리.
TLS 빌드 + 기본 설정
빌드
make BUILD_TLS=yes
OpenSSL 개발 라이브러리 (libssl-dev 등) 필요. 공식 docker 이미지 의 TLS 포함 변형 도 있음 (redis:7-alpine-tls 같은).
인증서 준비
자체 CA (인증 기관) 또는 외부 CA (Let's Encrypt 등):
# 자체 CA
openssl genrsa -out ca.key 4096
openssl req -x509 -new -nodes -sha256 -key ca.key -days 3650 -out ca.crt
# Redis 서버 키·인증서
openssl genrsa -out redis.key 2048
openssl req -new -sha256 -key redis.key -out redis.csr
openssl x509 -req -sha256 -in redis.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 365 -out redis.crt
# DH params (Diffie-Hellman 키 교환 파라미터, 선택)
openssl dhparam -out redis.dh 2048
redis.conf
tls-cert-file /etc/redis/tls/redis.crt
tls-key-file /etc/redis/tls/redis.key
tls-ca-cert-file /etc/redis/tls/ca.crt
tls-dh-params-file /etc/redis/tls/redis.dh
# TLS 전용 포트
tls-port 6379
# 평문 비활성
port 0
port 0 으로 평문 비활성. 평문·TLS 둘 다 듣게 하려면 두 포트 모두 박음:
port 6379 # 평문 (개발용, 같은 머신만)
tls-port 6380 # TLS (외부)
클라이언트 - Redis 통신 TLS
Python (redis-py)
import redis
r = redis.Redis(
host="redis-host",
port=6379,
ssl=True,
ssl_ca_certs="/path/to/ca.crt",
)
r.set("key", "value")
Java (Lettuce / Spring Data Redis)
spring:
data:
redis:
host: redis-host
port: 6379
ssl:
enabled: true
bundle: redis-tls
spring.ssl.bundle.jks.redis-tls:
truststore:
location: classpath:redis-ca.jks
password: trust-pass
mTLS — Client Certificate 인증
기본 = Redis 가 클라이언트의 인증서를 요구. 클라이언트도 키·인증서 필요.
서버 측 설정
tls-auth-clients yes # 기본값, mTLS 활성
# 또는
tls-auth-clients optional # 인증서 있으면 검증, 없어도 OK
# 또는
tls-auth-clients no # 클라이언트 인증서 요구 안 함
클라이언트 측 — Python
r = redis.Redis(
host="redis-host",
port=6379,
ssl=True,
ssl_ca_certs="/path/to/ca.crt",
ssl_certfile="/path/to/client.crt",
ssl_keyfile="/path/to/client.key",
)
mTLS 장점 — 비밀번호 + 인증서 이중 인증. 비밀번호만보다 훨씬 강한 보안. 단점 — 클라이언트 인증서 배포·관리 복잡.
Replication TLS
여기서 시험 함정이 하나 있어요 — Replication 통신은 별도 설정 필요.
# replica 측
tls-replication yes
이 옵션 없으면 master-replica 사이 가 평문 → 복제 데이터 도청 위험. 공용 클라우드의 다른 AZ (가용 영역)·리전 환경에서 특히 중요.
Cluster Bus TLS
Cluster 환경에서 노드 간 gossip (노드끼리 상태 교환) 통신 도 별도:
tls-cluster yes
활성 시 cluster bus 포트 (master port + 10000) 도 TLS.
Sentinel TLS
Sentinel ↔ Sentinel, Sentinel ↔ Redis 모두 TLS:
# sentinel.conf
tls-port 26379
tls-cert-file ...
tls-key-file ...
tls-ca-cert-file ...
tls-replication yes
tls-cluster yes # Sentinel 이 cluster 환경 모니터링 시
TLS 프로토콜·암호 슈트 설정
tls-protocols "TLSv1.2 TLSv1.3"
tls-ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:..."
tls-ciphersuites "TLS_AES_128_GCM_SHA256:..."
권장:
- TLSv1.2 + TLSv1.3 (이전 버전 차단)
- 현대적 AEAD (인증 + 암호화 결합 모드) 암호 슈트만
운영 환경에서는 조직 보안 정책 따라.
성능 부담
TLS 핸드셰이크 + 암호화 = CPU 부담 증가. 측정:
- 단순 GET 처리량: 평문 100,000 req/sec → TLS 70,000~85,000 req/sec
- 한 번 연결 후 재사용 (connection pool) 하면 핸드셰이크 부담 한 번만
권장:
- Connection pool 필수
- AES-NI hardware acceleration (CPU 내장 암호 가속) 활용
- 매우 트래픽 큰 환경 = TLS termination proxy (HAProxy 등) 로 분리 검토
운영 환경 권장 설정
| 환경 | TLS | mTLS |
|---|---|---|
| 로컬 개발 | X | X |
| 같은 머신 (Unix socket) | X | X |
| 같은 VPC (가상 사설망) + 같은 AZ | △ (선택) | X |
| 다른 AZ·리전 (공용 네트워크) | ◯ | △ (선택) |
| 인터넷 노출 | ◯ | ◯ |
| 금융·법적 보장 | ◯ | ◯ |
여기서 정말 중요한 자리 — VPC 안이라고 안전한 게 아님. 다른 사용자의 워크로드와 같은 물리 호스트 또는 클라우드 백본 네트워크 도청 가능성 — 완전 안전한 망은 없음. 의심스러우면 TLS 활성.
한계·실무 함정
1. 빌드에 TLS 미포함
위에서 언급. 반드시 TLS 포함 빌드 확인.
> redis-cli INFO server | grep tls
tls_enabled:1
2. 인증서 만료
Let's Encrypt 같은 90일 인증서 사용 시 자동 갱신 + Redis reload. 만료 후 클라이언트 연결 거부.
3. CA 인증서 분리·관리
서버 CA + 클라이언트 CA 분리하면 권한 분리 유리. 단순 환경은 한 CA.
4. 비TLS 포트 남겨 두면 우회 가능
port 6379 평문 + tls-port 6380 TLS 동시 운영 시 방화벽으로 6379 차단 안 하면 평문 우회 접근. 운영 환경 = port 0 으로 평문 완전 비활성.
5. 클라이언트 라이브러리 TLS 지원 확인
오래된 클라이언트는 TLS 미지원 또는 mTLS 미지원. 도입 전 라이브러리 버전 확인.
6. Replication TLS 안 켜면 평문 복제
위에서 강조. tls-replication yes 필수.
시험 직전 한 번 더 — Redis TLS 함정 압축 노트
- Redis TLS = Redis 6+ 부터 옵션
- 빌드 =
make BUILD_TLS=yes(기본 빌드에 미포함) - 포함 빌드 확인 =
INFO server | grep tls_enabled - 설정 =
tls-cert-file·tls-key-file·tls-ca-cert-file(+ 선택tls-dh-params-file) tls-port 6379= TLS 전용 포트port 0= 평문 완전 비활성 (운영 환경 표준)- mTLS =
tls-auth-clients yes(기본값) → 클라이언트 인증서 요구 - mTLS = 비밀번호 + 인증서 이중 인증
tls-replication yes= master-replica 통신 TLS (별도 옵션)tls-cluster yes= cluster bus 통신 TLS- 클라이언트 - Sentinel TLS = sentinel.conf 별도 설정
- 클라이언트 — Python
ssl=True + ssl_ca_certs/ Javaspring.data.redis.ssl.enabled=true - mTLS 클라이언트 =
ssl_certfile + ssl_keyfile - 프로토콜 권장 = TLSv1.2 + TLSv1.3 (이전 차단)
- 암호 슈트 = 현대 AEAD (
ECDHE-*-GCM-SHA256등) - 성능 부담 = 평문 대비 ~15~30% 감소
- 완화 = Connection pool 필수 + AES-NI 활용 + TLS termination proxy
- 환경별 — 로컬/같은 머신 X / 같은 VPC △ / 다른 AZ ◯ / 인터넷 ◯ / 금융 ◯
- VPC 안도 안전 X — 의심스러우면 TLS 활성
- 함정 — 빌드에 TLS 미포함 → 첫 도입 시 확인
- 함정 — 인증서 만료 → 자동 갱신 + reload
- 함정 — 평문 포트 남겨 두면 우회 →
port 0 - 함정 — Replication TLS 별도 옵션 → 안 켜면 평문 복제
- 함정 — 오래된 클라이언트 mTLS 미지원
공식 문서: Redis TLS 에서 자세한 설정·운영 가이드를 확인할 수 있어요.
시리즈 다른 편 (앞뒤 글 모음)
이전 글:
- 66편 — Redis Persistence (RDB · AOF · Hybrid)
- 67편 — Redis Replication (Master-Replica)
- 68편 — Redis Cluster (Sharding · 16384 슬롯 · Hash Tag)
- 69편 — Redis Sentinel (자동 Failover · Quorum)
- 70편 — Redis ACL (사용자·권한 관리)
다음 글: