안전하게 연결하기

안전하게 연결하기 (Connect Securely)

Redis에 연결할 때 "그냥 연결하면 되지 않나?" 싶을 수 있는데, 실제 배포 환경에서는 연결을 암호화하고 인증을 제대로 설정하는 게 꽤 중요해요. 이 문서에서는 Redis 서버에 안전하게(securely) 연결하는 방법, 즉 TLS로 암호화된 채널을 만들고 인증(AUTH)과 사용자 권한(ACL)을 활용하는 방법을 차례대로 다룰게요.

출처: 공식문서

⚠️ 확인 필요: 원문이 위치했던 URL(/docs/latest/develop/connect/securely/)이 현재 Redis 공식 문서 사이트에서 더 이상 응답하지 않아요(404). 아래 내용은 Redis 공식 문서의 클라이언트 연결 가이드와 redis-cli 문서에 실제로 존재하는 보안 연결(TLS) 지침을 바탕으로 정리했어요. 번역하기 전에 최신 URL을 한 번 확인해 보시길 권합니다.

왜 안전하게 연결해야 하나요?

기본적으로 redis-cli는 평문 TCP 연결로 Redis에 접속합니다. 즉 네트워크에서 엿볼 수 있는 사람이면 누구든 주고받는 데이터를 읽을 수 있다는 뜻이에요. 로컬 개발 서버에서는 그냥 써도 무방하지만, 원격 서버나 운영 환경에서는 이러면 안 됩니다. 두 가지를 함께 챙기면 됩니다:

  1. TLS로 암호화 — 주고받는 데이터가 네트워크에서 노출되지 않게 해요.
  2. 인증(AUTH)·권한(ACL) — 누가 연결하는지 확인하고, 할 수 있는 일을 제한해요.

실제로 Redis 공식 가이드는 "애플리케이션을 배포할 때는 TLS를 사용하고 Redis 보안 가이드라인을 따르세요"라고 명확히 권장합니다.

redis-cli로 TLS 연결하기

redis-cli는 기본적으로 평문 TCP 연결을 사용해요. SSL/TLS를 활성화하려면 --tls 옵션을 쓰고, 신뢰할 루트 인증서 번들(bundle)이나 디렉터리를 구성하기 위해 --cacert 또는 --cacertdir을 함께 지정합니다:

$ redis-cli --tls --cacert /path/to/ca.pem -h my-redis.example.com -p 6379 PING
PONG

-h(호스트)와 -p(포트)는 평문 연결 때와 똑같이 동작해요. 인증서 경로는 사용자 환경에 맞게 바꿔 쓰시면 됩니다.

URI 패턴으로 비밀번호·TLS 지정하기

연결 정보를 한 번에 담고 싶다면 URI 스킴을 쓰는 게 편리해요. redis://user:password@host:port/dbnum 패턴을 기본으로 쓰고, TLS 연결은 스킴을 rediss://로 바꿉니다:

$ redis-cli -u rediss://LJenkins:p%[email protected]:6379/0 PING
PONG

여기서 몇 가지 짚고 넘어갈게요:

  • redis://는 평문, rediss://는 TLS. 개발 서버를 제외하면 rediss를 쓰는 게 원칙이에요.
  • user와 password, dbnum은 모두 선택 사항입니다.
  • 사용자명 없이 인증하려면 사용자명을 default로 씁니다.
  • 비밀번호에 특수 문자가 있으면 URL 인코딩해야 해요. 위 예시에서 p%40ssw0rd가 비밀번호 p@ssw0rd를 인코딩한 것이에요.

비밀번호 인증과 환경 변수

비밀번호로 보호된 인스턴스라면, -a <password> 옵션으로 인증을 수행할 수 있어요. 이러면 AUTH 명령을 직접 보낼 필요가 없어집니다:

$ redis-cli -a myUnguessablePazzzzzword123 PING
PONG

다만 보안 관점에서 -a로 커맨드라인에 비밀번호를 바로 적는 것은 좋지 않아요. 프로세스 목록(예: ps)에 그대로 노출될 수 있기 때문이죠. Redis 공식 문서는 비밀번호를 REDISCLI_AUTH 환경 변수로 redis-cli에 자동으로 제공하도록 권장합니다. 셸에서 이렇게 쓸 수 있어요:

$ export REDISCLI_AUTH=myUnguessablePazzzzzword123
$ redis-cli PING
PONG

클라이언트 라이브러리에서의 TLS 연결

애플리케이션 코드에서는 언어별 공식 클라이언트에 TLS 옵션을 켜서 연결합니다. 어느 언어든 공통적으로 준비할 것이 세 가지 있어요: 사용자 인증서(redis_user.crt), 사용자 개인 키(redis_user_private.key), 그리고 CA 인증서(redis_ca.pem)입니다.

예를 들어 Go(go-redis)에서는 다음과 같이 TLS 구성을 세팅합니다:

// 사용자 인증서 로드
cert, err := tls.LoadX509KeyPair("redis_user.crt", "redis_user_private.key")
if err != nil {
    log.Fatal(err)
}
// CA 인증서 로드
caCert, err := os.ReadFile("redis_ca.pem")
if err != nil {
    log.Fatal(err)
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)

client := redis.NewClient(&redis.Options{
    Addr:     "my-redis.cloud.redislabs.com:6379",
    Username: "default", // 사용자 자신의 Redis 사용자, 상세: ACL 문서 참고
    Password: "secret",  // 사용자 자신의 Redis 비밀번호
    TLSConfig: &tls.Config{
        MinVersion:   tls.VersionTLS12,
        Certificates: []tls.Certificate{cert},
        RootCAs:      caCertPool,
    },
})

핵심 포인트는 TLSConfig에 최소 TLS 버전(tls.VersionTLS12), 클라이언트 인증서, 루트 CA 풀을 함께 넣고, Addr에는 rediss://가 아닌 TLS 포트(보통 6379)를 지정한다는 거예요. 언어별(Java/Jedis, Node.js/ioredis 등)로 문법은 다르지만 준비물과 개념은 동일합니다.

Java(Jedis)에서는 인증서를 PEM 형식에서 PKCS12 형식으로 먼저 변환하는 경우가 흔해요:

openssl pkcs12 -export -in ./redis_user.crt -inkey ./redis_user_private.key -out redis-user-keystore.p12 -name "redis"

ACL 사용자와 권한

Redis의 ACL(Access Control List)을 쓰면 "이 사용자는 이 명령만, 이 키들에만 가능"처럼 세밀하게 권한을 나눌 수 있어요. 보안 연결과 함께 ACL을 쓰면, 설령 자격 증명이 유출돼도 피해 범위를 제한할 수 있습니다.

연결할 때 사용자명과 비밀번호는 클라이언트 옵션에 지정합니다. 위 Go 예시에서 Username: "default"Password: "secret"이 바로 그 부분이에요. Redis에 정의된 사용자명과 해당 사용자의 비밀번호, 그리고 그 사용자가 허용된 명령·키 범위를 서로 맞춰야 연결이 성공합니다.

더 알아보기 (Learn more)