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.conf의 md5를 scram-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-256PG 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.crtPGDATA 안 또는 별도 디렉토리에 두고 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, 안 되면 평문 |
require | SSL 강제, 인증서 검증 안 함 |
verify-ca | CA 검증 |
verify-full | CA + 호스트명 검증. 표준 |
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.conf의 cert 메서드는 클라이언트 인증서의 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_version | TLSv1.2 또는 TLSv1.3 |
ssl_max_protocol_version | 비워 둠 (최신) |
ssl_prefer_server_ciphers | on |
ssl_passphrase_command | 키가 암호화된 경우 — 자동화 어려움, 보통 평문 키 + 권한 0600 |
로깅 확인
SHOW ssl;
-- 현재 세션의 SSL 사용 여부
SELECT * FROM pg_stat_ssl WHERE pid = pg_backend_pid();| 컬럼 | 의미 |
|---|---|
ssl | true/false |
version | TLSv1.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 위험 |
| 인증서 만료 알람 없음 | 어느 날 모든 클라이언트 접속 실패 |
정리
- 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을 봅니다.