본문으로 건너뛰기

9.5 SSL/TLS와 SCRAM

운영 클러스터의 네트워크 보안 두 축은 전송 암호화(SSL/TLS)와 비밀번호 해시 방식(SCRAM-SHA-256)입니다. 둘은 독립적으로 동작하지만 함께 켜야 안전한 접속이 됩니다. 인증서 발급·서버 설정·클라이언트 검증·SCRAM 동작을 정리합니다.

SCRAM-SHA-256

PostgreSQL의 비밀번호 인증은 두 가지가 표준이었습니다.

방식보안
md5 (PG 9.6 이전)MD5 challenge-response. 평문 노출은 안 되지만 rainbow table 위험
scram-sha-256 (PG 10+)SCRAM-SHA-256. 비밀번호를 서버가 저장 시점부터 모름

SCRAM의 핵심:

  • 서버는 비밀번호 자체가 아니라 salted hash만 저장
  • 인증 시 challenge-response — 비밀번호가 네트워크에 흐르지 않음
  • 평문·MD5보다 강력

pg_authid.rolpassword를 보면 시작 문자열로 어느 방식인지 압니다.

SELECT rolname, LEFT(rolpassword, 14) AS kind
  FROM pg_authid WHERE rolcanlogin;
-- kind = 'SCRAM-SHA-256' 또는 'md5...'

SCRAM으로 마이그레이션

ALTER SYSTEM SET password_encryption = 'scram-sha-256';
SELECT pg_reload_conf();

-- 각 사용자의 비밀번호를 다시 설정 (이때 SCRAM으로 저장됨)
ALTER ROLE alice PASSWORD 'new_secret';

password_encryption만 바꾸면 기존 비밀번호는 그대로 MD5. 새로 설정하는 비밀번호만 SCRAM. 모든 사용자가 갱신되면 pg_hba.confmd5scram-sha-256으로 교체.

channel binding

SCRAM-SHA-256-PLUS는 SCRAM에 TLS 채널 바인딩을 결합 — TLS MITM 공격 방어.

# pg_hba.conf
hostssl  app_main  all  10.0.0.0/8  scram-sha-256

PG 11+의 libpq는 channel_binding=require로 강제 가능합니다.

psql 'postgresql://user@host/db?sslmode=verify-full&channel_binding=require'

SSL/TLS

서버 측 — 인증서 생성

운영 환경에서는 PKI(사내 CA·Let’s Encrypt 등)를 씁니다. 개발용 자가 서명:

# 1. CA (조직의 root)
openssl req -new -x509 -days 3650 -nodes \
  -out ca.crt -keyout ca.key \
  -subj "/CN=My PG CA"

# 2. 서버 키·CSR
openssl req -new -nodes \
  -out server.csr -keyout server.key \
  -subj "/CN=db.example.com"

# 3. CA로 서버 인증서 서명
openssl x509 -req -in server.csr -days 365 \
  -CA ca.crt -CAkey ca.key -CAcreateserial \
  -out server.crt

# 4. 파일 권한 (0600 — 안 그러면 PG가 거부)
chmod 0600 server.key
chown postgres:postgres server.{crt,key} ca.crt

PGDATA 안 또는 별도 디렉토리에 두고 postgresql.conf에서 경로 지정.

postgresql.conf

ssl = on
ssl_cert_file     = '/etc/postgresql/ssl/server.crt'
ssl_key_file      = '/etc/postgresql/ssl/server.key'
ssl_ca_file       = '/etc/postgresql/ssl/ca.crt'           # 클라이언트 인증서 검증 시
ssl_min_protocol_version = 'TLSv1.2'                        # 또는 TLSv1.3
ssl_ciphers       = 'HIGH:!aNULL:!MD5:!RC4'                 # 안전한 cipher만

reload 또는 restart 후:

SHOW ssl;          -- on

클라이언트 측 — verify-full

psql 'postgresql://app@db.example.com/app?sslmode=verify-full&sslrootcert=/etc/ssl/ca.crt'

sslmode 단계:

의미
disable평문 (절대 금지)
prefer (기본)가능하면 SSL, 안 되면 평문
requireSSL 강제, 인증서 검증 안 함
verify-caCA 검증
verify-fullCA + 호스트명 검증. 표준

verify-full이 운영 표준입니다. 자가 서명 CA의 경우 sslrootcert에 CA 인증서 경로 지정.

클라이언트 인증서 (mutual TLS)

비밀번호 대신 클라이언트 인증서로 인증.

# 클라이언트 인증서 발급 (CN = DB 사용자명)
openssl req -new -nodes -out alice.csr -keyout alice.key \
  -subj "/CN=alice"
openssl x509 -req -in alice.csr -days 365 \
  -CA ca.crt -CAkey ca.key -CAcreateserial \
  -out alice.crt

서버 pg_hba.conf:

hostssl  all  all  10.0.0.0/8  cert  clientcert=verify-full

클라이언트 접속:

psql 'postgresql://alice@db.example.com/app?sslmode=verify-full&sslcert=/etc/ssl/alice.crt&sslkey=/etc/ssl/alice.key&sslrootcert=/etc/ssl/ca.crt'

pg_hba.confcert 메서드는 클라이언트 인증서의 CN이 user 컬럼과 일치해야 통과.

인증서 갱신 — pg_reload_conf()

PG 13+에서 SSL 설정 reload 시 기존 연결은 옛 인증서 유지, 새 연결은 새 인증서 사용합니다. 무중단 갱신 가능합니다.

# 인증서 파일 교체
sudo cp /tmp/new_server.crt /etc/postgresql/ssl/server.crt
sudo systemctl reload postgresql-17

# 새 연결로 검증
psql ... # 새 인증서로 접속됨

PG 12 이전은 restart 필요합니다.

TLS 정책 — postgresql.conf

파라미터권장
ssl_min_protocol_versionTLSv1.2 또는 TLSv1.3
ssl_max_protocol_version비워 둠 (최신)
ssl_prefer_server_cipherson
ssl_passphrase_command키가 암호화된 경우 — 자동화 어려움, 보통 평문 키 + 권한 0600

로깅 확인

SHOW ssl;
-- 현재 세션의 SSL 사용 여부
SELECT * FROM pg_stat_ssl WHERE pid = pg_backend_pid();
컬럼의미
ssltrue/false
versionTLSv1.2 / TLSv1.3
cipher사용된 cipher suite
client_dn클라이언트 인증서 DN (mutual TLS)

모니터링: pg_stat_ssl을 주기 점검해 평문 접속이 있는지 확인합니다.

-- 비-SSL 접속 추적
SELECT count(*) FROM pg_stat_ssl WHERE ssl IS NOT true;

안티패턴

안티패턴위험
ssl = off (운영)평문 전송
sslmode = require만 (인증서 검증 안 함)MITM 가능
자가 서명 인증서를 신뢰 chain 없이 클라이언트 배포검증 우회
MD5 비밀번호 유지rainbow table 위험
인증서 만료 알람 없음어느 날 모든 클라이언트 접속 실패
인증서 만료 모니터링 필수. 운영 사고 중 흔한 사례 — 인증서 1년 만료가 지나 어느 날 새벽에 모든 클라이언트가 접속 실패. Let’s Encrypt 같은 자동 갱신 또는 Vault·cert-manager 통합 권장합니다.

정리

  • SCRAM-SHA-256 = 비밀번호 인증의 현대 표준입니다. PG 10+ 이후 권장
  • md5 → SCRAM 마이그레이션은 password_encryption + 비밀번호 재설정
  • SSL/TLS는 서버 인증서 + 클라이언트 sslmode=verify-full
  • mutual TLS는 cert 메서드 + 클라이언트 인증서
  • PG 13+ SSL reload 무중단 갱신 가능
  • pg_stat_ssl로 접속 보안 상태 모니터링
  • 인증서 만료 알람·자동 갱신 자동화 필수

다음 절(9.6)에서는 누가 무엇을 했는지 기록하는 감사 — pgaudit을 봅니다.