PostgreSQL 연결을 SSL/TLS 구성으로 보호하는 완벽 가이드
SSL/TLS 암호화로 PostgreSQL 연결을 보호하는 방법을 알아보세요. 이 포괄적인 가이드는 인증서 생성, `postgresql.conf` 및 `pg_hba.conf` 수정, 안전한 암호화 통신을 위한 클라이언트 설정 등 서버 및 클라이언트 측 구성을 다룹니다. 전송 중인 중요한 데이터를 보호하고 최신 보안 표준을 준수하세요.
PostgreSQL 연결을 SSL/TLS 구성으로 보호하는 완벽 가이드
PostgreSQL SSL/TLS 구성에는 두 가지 별개의 작업이 있습니다. 첫 번째는 암호화로, 네트워크 상의 누군가가 전송 중인 자격 증명이나 쿼리 결과를 읽을 수 없도록 하는 것입니다. 두 번째는 신원 확인으로, 클라이언트가 실제 데이터베이스 서버와 통신하고 있음을 확인하고 가짜 서버가 아닌지 확인하는 것입니다. 많은 설정이 첫 번째 작업을 수행하고 실수로 두 번째 작업을 건너뜁니다.
이러한 구분은 실제 배포에서 중요합니다. sslmode=require는 연결을 암호화하지만, 그 자체로는 서버 호스트 이름을 완전히 확인하지 않습니다. sslmode=verify-full이 이를 수행합니다. 애플리케이션이 공용 네트워크, 공유 회사 네트워크, 완전히 제어할 수 없는 Kubernetes 오버레이, 또는 트래픽이 가로채질 수 있는 환경을 통해 연결되는 경우 verify-full이 목표가 되어야 합니다.
PostgreSQL에서 SSL/TLS 이해하기
SSL/TLS(Secure Sockets Layer/Transport Layer Security)는 컴퓨터 네트워크를 통한 통신 보안을 제공하도록 설계된 암호화 프로토콜입니다. PostgreSQL에 적용하면 데이터베이스 서버와 클라이언트 간에 교환되는 데이터를 암호화합니다. 이는 승인되지 않은 당사자가 자격 증명, 금융 데이터 또는 개인 정보와 같은 중요한 정보를 가로채고 읽는 것을 방지합니다.
PostgreSQL 클라이언트는 여러 SSL 모드를 지원합니다.
sslmode=disable: 암호화되지 않은 일반 연결만 사용합니다.sslmode=prefer: 먼저 TLS를 시도하고, TLS를 사용할 수 없으면 일반 TCP로 대체합니다. 편리하지만 잘못된 구성을 숨길 수 있습니다.sslmode=require: TLS 암호화를 요구하지만 서버 호스트 이름을 반드시 확인하지는 않습니다.sslmode=verify-ca: TLS를 요구하고 인증서가 신뢰할 수 있는 CA에 연결되어 있는지 확인합니다.sslmode=verify-full: TLS를 요구하고, CA를 확인하며, 호스트 이름이 인증서와 일치하는지 확인합니다.
서버 측에서 ssl = on은 PostgreSQL이 TLS 연결을 수락할 수 있다는 의미일 뿐입니다. 모든 클라이언트가 TLS를 사용하도록 강제하지는 않습니다. 적용은 pg_hba.conf에서 hostssl 규칙을 사용하고 동일한 사용자와 네트워크가 TLS 없이 연결할 수 있는 더 넓은 host 규칙을 피함으로써 이루어집니다.
SSL/TLS 구성 사전 요구 사항
PostgreSQL용 SSL/TLS 구성을 시작하기 전에 다음 사항이 있는지 확인하세요.
- OpenSSL 설치: OpenSSL 툴킷은 SSL 인증서를 생성하고 관리하는 데 필수적입니다. 일반적으로 Linux 및 macOS 시스템에 사전 설치되어 있습니다. Windows의 경우 별도로 다운로드하여 설치해야 할 수 있습니다.
- PostgreSQL 구성 파일에 대한 액세스:
postgresql.conf및pg_hba.conf파일을 수정하려면 관리 권한이 필요합니다. - 인증 기관(CA) 이해: 테스트용으로 자체 서명된 인증서를 만들 수 있지만, 프로덕션 환경에서는 신뢰할 수 있는 인증 기관(CA) 또는 내부 엔터프라이즈 CA에서 서명한 인증서를 사용하는 것이 이상적입니다.
서버 측 SSL/TLS 구성
서버 측 구성에는 SSL 활성화, SSL 인증서 및 키 위치 지정, 클라이언트 인증 구성이 포함됩니다.
1. SSL 인증서 및 키 생성 또는 획득
PostgreSQL 서버용 SSL 인증서를 얻는 두 가지 주요 방법이 있습니다.
- 자체 서명된 인증서(테스트/개발용): OpenSSL을 사용하여 생성되며 외부 클라이언트가 기본적으로 신뢰하지 않습니다. 초기 설정 및 내부 테스트에 유용합니다.
- 인증 기관(CA)의 인증서(프로덕션용): 신뢰할 수 있는 공용 CA(예: Let's Encrypt, DigiCert) 또는 내부 엔터프라이즈 CA에서 인증서를 얻습니다. 이렇게 하면 클라이언트가 서버의 신원을 확인할 수 있습니다.
OpenSSL을 사용하여 자체 서명된 인증서 만들기:
이는 개발 및 내부 환경에서 일반적인 접근 방식입니다. PostgreSQL 서버 또는 OpenSSL이 설치된 머신에서 다음 명령을 실행하세요.
인증서 디렉토리 생성: 인증서를 체계적으로 유지 관리하는 것이 좋습니다.
sudo mkdir -p /etc/postgresql/ssl sudo chown postgres:postgres /etc/postgresql/ssl cd /etc/postgresql/ssl서버 개인 키 생성: 이 키는 비밀로 유지되어야 합니다.
sudo openssl genrsa -out server.key 2048서버 인증서 서명 요청(CSR) 생성: 서버에 대한 정보가 포함됩니다.
sudo openssl req -new -key server.key -out server.csr클라이언트가 연결할 호스트 이름(예:
db01.internal.example.com)을 사용하세요. 최신 클라이언트는 일반적으로 SAN(Subject Alternative Name)을 확인하므로, CA 프로세스가 지원하는 경우 인증서 요청에 DNS 이름을 포함하세요.자체 CA로 인증서 서명(내부용):
- 루트 CA 개인 키 및 인증서 생성(없는 경우):
# CA 개인 키 생성 sudo openssl genrsa -des3 -out root.key 2048 # CA 인증서 생성(3650일 동안 유효) sudo openssl req -new -x509 -days 3650 -key root.key -out root.crt - CA로 서버 CSR 서명: 신뢰할 수 있는 서버 인증서를 만듭니다.
sudo openssl x509 -req -days 365 -in server.csr -CA root.crt -CAkey root.key -set_serial 01 -out server.crt
- 루트 CA 개인 키 및 인증서 생성(없는 경우):
권한 설정: PostgreSQL 사용자가 이러한 파일을 읽을 수 있는지 확인하세요.
sudo chown postgres:postgres server.key server.crt root.crt sudo chmod 600 server.key sudo chmod 644 server.crt root.crt
공용/엔터프라이즈 CA의 인증서 사용:
CA에서 인증서를 받으면 일반적으로 다음을 받게 됩니다.
server.crt: 서버의 공개 인증서.server.key: 서버의 개인 키.root.crt(또는 유사): CA의 루트 인증서(및 잠재적으로 중간 인증서).
이러한 파일을 안전한 디렉토리(예: /etc/postgresql/ssl/)에 배치하고 PostgreSQL 사용자에게 읽기 권한이 있는지 확인하세요.
2. postgresql.conf 구성
postgresql.conf 파일(일반적으로 PostgreSQL 데이터 디렉토리에 있음)을 편집하여 SSL을 활성화하고 인증서 파일을 지정하세요.
#------------------------------------------------------------------------------
# SSL
#------------------------------------------------------------------------------
ssl = on
# 이들은 모두 PEM 형식이며, 서버 키/인증서가 구성되지 않은 경우 무시됩니다.
# 기본적으로 파일은 서버의 데이터 디렉토리에 있을 것으로 예상됩니다.
# 또는 전체 경로로 지정할 수 있습니다.
ssl_cert_file = '/etc/postgresql/ssl/server.crt' # (필요한 경우 파일 이름 변경)
ssl_key_file = '/etc/postgresql/ssl/server.key' # (필요한 경우 파일 이름 변경)
ssl_ca_file = '/etc/postgresql/ssl/root.crt' # (선택 사항, 클라이언트 인증서 확인용)
# 선택 사항: 필요한 경우 암호화 제품군 목록 지정
#ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL'
# 선택 사항: 클라이언트 인증서 확인 활성화
#ssl_ca_file은 신뢰할 CA 인증서를 포함하는 파일로 설정해야 합니다.
#ssl_crl_file = ''
#ssl_crl_dir = ''
ssl = on: 서버에서 SSL 지원을 활성화합니다.ssl_cert_file: 서버의 공개 인증서 경로.ssl_key_file: 서버의 개인 키 경로.ssl_ca_file: 클라이언트 인증서를 확인할 때 PostgreSQL이 신뢰해야 하는 CA 인증서 경로. 클라이언트는 서버를 확인하기 위해sslrootcert와 같은 자체 CA 파일을 사용합니다.
3. SSL 적용을 위한 pg_hba.conf 구성
pg_hba.conf 파일은 클라이언트 인증을 제어합니다. SSL 연결을 적용하려면 항목을 수정해야 합니다.
기본적으로 pg_hba.conf의 항목은 다음과 같습니다.
# TYPE DATABASE USER ADDRESS METHOD
local all all peer
# IPv4 로컬 연결:
host all all 127.0.0.1/32 scram-sha-256
# IPv6 로컬 연결:
host all all ::1/128 scram-sha-256
SSL을 적용하려면 host 항목을 hostssl로 변경하세요.
# TYPE DATABASE USER ADDRESS METHOD
local all all peer
# IPv4 로컬 연결:
hostssl all all 127.0.0.1/32 scram-sha-256
# IPv6 로컬 연결:
hostssl all all ::1/128 scram-sha-256
# 외부 네트워크 액세스 예시 - SSL 필요
hostssl all app_user 10.20.0.0/16 scram-sha-256
hostssl all app_user 2001:db8:20::/48 scram-sha-256
hostssl: 이 레코드 유형은 SSL 연결을 요구합니다. SSL 없는 연결 시도는 거부됩니다.hostnossl: 이 레코드 유형은 SSL 연결을 명시적으로 금지합니다.host: SSL 및 비SSL 연결을 모두 허용합니다. 일치하는host규칙이hostssl규칙보다 먼저 존재하거나 대신하는 경우 클라이언트는 여전히 TLS 없이 연결할 수 있습니다.
강력한 이유가 없고 다른 제어 수단이 마련되어 있지 않다면 0.0.0.0/0 액세스를 게시하지 마십시오. 대부분의 프로덕션 데이터베이스는 애플리케이션 서브넷, 배스천 호스트, 연결 풀러 또는 개인 네트워크 범위에서만 연결을 수락해야 합니다.
4. PostgreSQL 서버 다시 시작
postgresql.conf 및 pg_hba.conf를 수정한 후 변경 사항을 적용하려면 PostgreSQL 서비스를 다시 시작해야 합니다.
# systemd를 사용하는 시스템(대부분의 최신 Linux 배포판)
sudo systemctl restart postgresql
# init.d를 사용하는 시스템
sudo service postgresql restart
클라이언트 측 SSL/TLS 구성
클라이언트도 안전하게 연결하도록 구성해야 합니다. 여기에는 연결 매개변수 지정, 잠재적으로 클라이언트 인증서 제공, 서버 인증서 확인이 포함됩니다.
1. 연결 문자열 매개변수
psql 또는 PostgreSQL 클라이언트 라이브러리를 통해 연결할 때 연결 문자열이나 개별 옵션으로 SSL 매개변수를 지정할 수 있습니다.
기본 SSL 연결(서버 인증만):
psql "sslmode=require host=your_server_hostname dbname=your_db user=your_user"
sslmode: 클라이언트의 SSL 동작을 제어합니다.disable: 비SSL 연결만 허용합니다.allow: 비SSL을 허용하지만 서버가 지원하는 경우 SSL을 선호합니다.prefer(기본값): SSL을 선호하지만 SSL이 실패하면 비SSL을 허용합니다.require: SSL 연결만 허용합니다. 서버가 SSL을 지원하지 않으면 연결이 실패합니다.verify-ca: SSL 연결만 허용하고 서버 인증서가 신뢰할 수 있는 CA에 의해 서명되었는지 확인합니다.sslrootcert매개변수를 설정해야 합니다.verify-full: SSL 연결만 허용하고, 신뢰할 수 있는 CA에 대해 서버 인증서를 확인하며, 서버 호스트 이름이 인증서의 CN(Common Name) 또는 SAN(Subject Alternative Name)과 일치하는지 확인합니다.
서버 인증서 확인(verify-ca 또는 verify-full):
향상된 보안을 위해 클라이언트는 서버의 신원을 확인해야 합니다. 이렇게 하려면 클라이언트가 서버 인증서에 서명한 CA를 신뢰해야 합니다.
- CA 인증서 획득: 서버 인증서를 서명하는 데 사용된
root.crt파일(또는 적절한 CA 인증서)을 가져옵니다. sslrootcert지정: 클라이언트에게 이 CA 인증서를 찾을 위치를 알려줍니다.
psql "sslmode=verify-full host=your_server_hostname dbname=your_db user=your_user sslrootcert=/path/to/your/root.crt"
이것은 애플리케이션을 실행하는 동일한 호스트 또는 컨테이너에서 테스트해야 하는 연결 문자열입니다. 일반적인 실패는 관리자 노트북에서 CA 파일이 존재하기 때문에 psql이 작동하지만, CA 번들이 마운트되지 않았기 때문에 애플리케이션 컨테이너에서 실패하는 것입니다.
2. 클라이언트 인증서(상호 인증)
더 높은 수준의 보안을 위해 서버가 클라이언트 인증서를 사용하여 클라이언트의 신원을 확인하는 상호 인증을 구현할 수 있습니다.
클라이언트 인증서 생성:
서버 인증서와 유사하게 클라이언트 개인 키와 서버가 신뢰하는 CA(종종 서버 인증서와 동일한 CA)가 서명한 클라이언트 인증서가 필요합니다.
클라이언트 개인 키 생성:
openssl genrsa -des3 -out client.key 2048클라이언트 CSR 생성:
openssl req -new -key client.key -out client.csr세부 정보를 제공하고 CN(Common Name)이 클라이언트에 대해 고유한지 확인하세요.
CA로 클라이언트 CSR 서명:
sudo openssl x509 -req -days 365 -in client.csr -CA root.crt -CAkey root.key -set_serial <unique_serial> -out client.crt권한 설정:
chmod 600 client.key chmod 644 client.crt
클라이언트 인증 인증을 위한 pg_hba.conf 구성:
서버에서 클라이언트 인증 인증을 수락하도록 pg_hba.conf를 구성해야 합니다. 이는 종종 cert 인증 방법을 사용합니다.
# TYPE DATABASE USER ADDRESS METHOD
# 특정 사용자/DB에 대해 SSL 및 클라이언트 인증서 인증 필요
hostssl all your_user your_client_ip/32 cert map=your_cert_map
특정 클라이언트 인증서 세부 정보(예: Subject 또는 SubjectAltName)를 PostgreSQL 사용자에 매핑하려면 인증서 맵 파일(cert_map 옵션)을 정의해야 할 수도 있습니다. 자세한 cert 인증 및 인증서 매핑 설정은 PostgreSQL 문서를 참조하세요.
인증서를 사용하도록 클라이언트 구성:
클라이언트의 연결 문자열을 업데이트하여 인증서 및 키 경로를 포함시킵니다.
psql "sslmode=verify-full host=your_server_hostname dbname=your_db user=your_user \
sslrootcert=/path/to/your/root.crt sslcert=/path/to/your/client.crt sslkey=/path/to/your/client.key"
모범 사례 및 팁
verify-fullsslmode사용: 클라이언트 측에서verify-full을 사용하여 중간자 공격 위험을 줄이세요.- 개인 키 보호: 개인 키(
.key파일)에 엄격한 파일 권한(예:chmod 600)이 있고 서버의 PostgreSQL 사용자와 클라이언트의 연결 사용자만 읽을 수 있는지 확인하세요. - 정기적으로 인증서 갱신: 인증서에는 만료 날짜가 있습니다. 연결 중단을 방지하기 위해 만료되기 전에 인증서를 갱신하는 프로세스를 구현하세요.
- 중앙 집중식 인증서 관리: 대규모 배포의 경우 인증서 관리 시스템을 사용하거나 인증서 발급 및 갱신을 자동화하는 것을 고려하세요.
- 로그 모니터링: 시작 또는 연결 시도 중 SSL 관련 오류가 있는지 PostgreSQL 로그를 확인하세요.
- 문서 참조: PostgreSQL 버전에 특정한 최신 매개변수 및 고급 구성 옵션은 공식 PostgreSQL 문서를 참조하세요.
빠른 확인 체크리스트
PostgreSQL을 다시 시작한 후 서버가 TLS로 수신 대기 중인지 확인하세요.
SHOW ssl;
SHOW ssl_cert_file;
SHOW ssl_key_file;
그런 다음 클라이언트 호스트에서 테스트하세요.
psql "host=your_server_hostname dbname=your_db user=your_user sslmode=verify-full sslrootcert=/path/to/root.crt"
세션 내에서 연결이 암호화되었는지 확인하세요.
SELECT ssl, version, cipher
FROM pg_stat_ssl
WHERE pid = pg_backend_pid();
ssl이 false이면 pg_hba.conf 규칙이 예상대로 적용되지 않는 것입니다. verify-full이 실패하고 require가 작동하면 인증서에 올바른 호스트 이름이 없거나, 클라이언트가 CA를 신뢰하지 않거나, 애플리케이션이 IP 주소로 연결하는 반면 인증서는 DNS 이름으로 발급된 것입니다.
좋은 PostgreSQL TLS 설정은 단순히 ssl = on이 아닙니다. 올바른 이름이 있는 인증서, 엄격한 권한이 있는 개인 키, 실제로 TLS를 적용하는 hostssl 규칙, 소켓을 암호화하는 대신 서버를 확인하는 클라이언트로 이어지는 체인입니다.