SSL 개인키 배포에 NGINX를 사용하세요.
이번 포스트에서는 NGINX가 SSL 암호화 웹사이트를 호스팅할 때 사용하는 SSL 개인키 를 안전하게 배포하는 몇 가지 방법을 다음과 같이 설명합니다.
- NGINX를 사용하여 SSL을 구성하기 위한 표준 접근 방식 및 잠재적인 보안 제한 사항
- NGINX 구성과 별도로 저장된 암호를 사용하여 Key를 암호화하는 방법
- 디스크 드라이브를 사용하지 않고 비밀번호 암호화를 안전하게 배포한 다음 필요할 때 암호를 해지하는 방법
대부분의 배포의 경우 표준 접근 방식으로 충분합니다. 아래에 논의된 두 가지 접근 방식은 공격자가 SSL 개인키 를 얻을 수 있는 방법을 차단하는 것 입니다.
- HashiCorp Vault와 같은 타사 비밀 저장소를 사용하여 암호를 안전하게 배포합니다.
- Private Key 자료가 디스크에 저장되지 않도록 Vault에서 NGINX Plus의 Key-Value Store로 인증서 프로비저닝(Provisioning)을 자동화합니다.
이 포스트에 제시된 접근 방식은 자신의 Key를 관리하고 자신만의 안전한 Key 배포 전략을 만들어야 하는 사용자에게 적용됩니다. Kubernetes와 같이 이미 비밀 저장소와 통합된 환경에서 NGINX를 실행하는 사용자에게는 필요하지 않습니다.
이 포스트는 NGINX Open Source와 NGINX Plus 모두에 적용됩니다. 읽기 쉽도록 전체적으로 NGINX로 용어를 통일 하도록 하겠습니다.
목차
1. SSL 개인키 를 보호하는 이유
2. NGINX 보안 경계
3. 표준 NGINX 구성
3-1. 표준 구성의 보안적 의미
4. SSL 개인키 암호화
4-1. SSL 암호 파일 사용
4-2. 별도의 파일에 있는 암호화된 Key의 보안 의미
5. SSL 암호 목록을 보다 안전하게 배포
5-1. 중앙 암호 배포 지점 생성
5-2. PDP의 보안 의미
6. 요약
1. SSL 개인키 를 보호하는 이유
SSL/TLS는 네트워크 트랜잭션의 무결성을 인증, 암호화 및 확인하는 데 사용됩니다. 웹 사이트는 인증 기관(CA)이 서명한 Public 인증서를 사용하여 자신을 인증하고, 해당 Private Key(비밀로 유지해야 합니다)를 사용하여 대조를 수행하여 인증서를 소유하고 있음을 입증합니다.
Private Key가 손상된 경우 두 가지 주요 위험이 있습니다.
- 위험 1: 위장(Impersonation) – Private Key를 가진 공격자는 네트워크 트래픽을 가로챈 다음 MITM(Man-In-The-Middle) 공격을 시작할 수 있습니다. 이 공격은 클라이언트나 웹 사이트가 인식하지 못한 채 모든 트래픽을 캡처하고 해독하며 어쩌면 트래픽을 수정할 수도 있습니다.
- 위험 2: 복호화(Decryption) – Private Key를 가지고 있고 네트워크 트래픽을 기록한 공격자는 오프라인에서 네트워크 트래픽의 암호를 해독할 수 있습니다. PFS(Perfect Forward Secrecy) 암호를 사용하는 연결에는 이 공격을 사용할 수 없습니다.
Private Key가 손상된 경우 유일한 방법은 CA에 연락하여 인증서를 해지하도록 요청하는 것입니다. 그런 다음 해지 상태를 확인하고 적용하려면 클라이언트에 의존해야 합니다.
또한 만료 시간이 짧은 인증서를 사용하는 것이 좋습니다(예: Let’s Encrypt 인증서는 90일 후에 만료됩니다). 인증서가 만료되기 직전에 새 Private Key를 생성하고 CA에서 새 인증서를 받아야 합니다. 이렇게 하면 Private Key가 손상되어 노출될 위험이 줄어듭니다.
2. NGINX 보안 경계
NGINX에서 SSL 개인키 에 액세스할 수 있는 사용자 및 프로세스는 무엇입니까?
우선, NGINX를 실행하는 서버에 대한 root 액세스 권한을 얻은 모든 사용자는 NGINX 자체에서 사용하는 모든 리소스를 읽고 사용할 수 있습니다. 예를 들어 실행 중인 프로세스의 메모리에서 SSL 개인키 를 추출하는 방법이 있습니다.
따라서 Private Key가 어떻게 저장되고 배포되더라도 호스트 서버에 대한 root 권한을 가진 공격자로부터 Private Key를 보호하는 것은 불가능합니다.
다음으로, NGINX 구성을 수정하고 Commit할 수 있는 모든 사용자는 내부 서비스에 대한 Proxy 액세스를 열고 인증 수단을 우회하는 등 여러 가지 방법으로 권한을 사용할 수 있습니다. SELinux 및 AppArmor와 같은 도구를 사용하면 서버에 대한 root 액세스를 얻을 수 있지만 NGINX 구성을 수정하는 가능성을 완화하는데 도움이 됩니다.
따라서 NGINX 구성을 수정하고 Commit할 수 있는 공격자로부터 Private Key를 보호하는 것은 일반적으로 불가능합니다.
다행히도, 유능한 기업은 공격자가 root 권한을 얻거나 NGINX 구성을 수정하는 것을 어렵게 만드는 안전한 보안 프로세스를 가지고 있습니다.
그러나 권한이 낮은 공격자가 Private Key에 대한 액세스 권한을 얻을 수 있는 다른 두 가지 방법이 있습니다.
- 사용자가 NGINX 구성을 확인해야 하는 합당한 이유가 있거나 구성 데이터베이스 또는 백업에 대한 액세스 권한을 얻을 수 있습니다. NGINX 개인키 는 일반적으로 구성에 저장됩니다.
- 사용자는 하이퍼바이저(Hypervisor) 또는 시스템 백업을 통해 NGINX 서버의 파일 시스템에 대한 액세스 권한을 얻을 수 있습니다. Private Key 자료를 포함하여 파일 시스템에 저장된 모든 데이터에 잠재적으로 액세스할 수 있습니다.
이 포스트에 설명된 프로세스는 이 두 가지 공격 방법을 방어합니다.
3. 표준 NGINX 구성 (SSL 개인키)
먼저 SSL/TLS를 사용하는 일반적인 NGINX 구성이 어떻게 구성되었는지 검토합니다.
server {
listen 443 ssl;
server_name a.dev0;
ssl_certificate ssl/a.dev0.crt;
ssl_certificate_key ssl/a.dev0.key;
location / {
return 200 "Hello from service A\n";
}
}
SSL Public 인증서(a.dev0.crt
) 및 Private Key(a.dev0.key
)는 파일 시스템의 /etc/nginx/ssl/
에 저장됩니다. Private Key는 일반적으로 root로 실행되는 NGINX Master 프로세스에서만 읽을 수 있으므로 가장 엄격한 액세스 권한을 설정할 수 있습니다.
root@web1:/etc/nginx/ssl# ls -l a.dev0.key
-r-------- 1 root root 1766 Aug 15 16:32 a.dev0.key
Private Key는 항상 사용할 수 있어야 합니다. NGINX Master 프로세스는 NGINX 소프트웨어가 시작되거나 구성이 Reload 되거나 구문 검사가 수행될 때마다 이를 읽습니다(nginx -t
).
3-1. 표준 구성의 보안적 의미
위에서 언급한 것처럼 SSL 개인키 는 실행 중인 컨테이너, 가상 머신(VM) 또는 NGINX 소프트웨어를 실행 중인 서버에 대한 root 액세스 권한을 얻은 공격자가 읽을 수 있습니다.
4. SSL 개인키 암호화
NGINX는 AES256과 같은 보안 알고리즘을 사용하여 암호화된 Private Key를 지원합니다.
root@web1:/etc/nginx/ssl# mv a.dev0.key a.dev0.key.plain
root@web1:/etc/nginx/ssl# openssl rsa -aes256 -in a.dev0.key.plain -out a.dev0.key
writing RSA key
Enter PEM pass phrase: secure password
Verifying - Enter PEM pass phrase: secure password again
그런 다음 NGINX를 시작하거나 NGINX 구성을 Reload 하거나 테스트할 때 NGINX는 대화식으로 암호 해독을 요청합니다.
root@web1:/etc/nginx# nginx -t
Enter PEM pass phrase: secure password
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
4-1. SSL 암호 파일 사용
대화식으로 암호를 입력하는 것은 불편하고 자동화하기 어렵지만 ssl_password_file 지시문으로 명명된 별도의 파일에 저장된 암호 목록을 사용하도록 NGINX를 구성할 수 있습니다. NGINX는 Private Key를 읽어야 할 때 파일의 각 암호를 차례로 사용하여 Key 해독을 시도합니다. 유효한 암호가 없으면 NGINX가 시작을 거부합니다.
ssl_password_file /var/lib/nginx/ssl_passwords.txt;
ssl_password_file은 구성과 별도로 배포되어야 하며 root 사용자만 읽을 수 있습니다. 신뢰할 수 있는 서버에 배치된 인증 토큰으로 간주할 수 있습니다. NGINX는 인증 토큰이 있는 서버에서 실행 중일 때만 Private Key를 해독할 수 있습니다.
4-2. 별도의 파일에 있는 암호화된 Key의 보안 의미
이 방법은 공격자에게 NGINX 구성만 사용할 수 없도록 하여 공격 표면을 줄입니다. 공격자는 ssl_password_file의 내용도 얻어야 합니다.
공격자가 ssl_password_file이 저장된 파일 시스템에 대한 root 액세스 권한을 얻은 경우(예: 백업 또는 호스트 시스템을 통해) 공격자는 파일을 읽고 암호를 사용하여 SSL 개인키 를 해독할 수 있습니다.
RAM
디스크 또는 tmpfs
에 ssl_password_file을 저장하여 이 위험을 줄일 수 있습니다. 이 저장소는 일반적으로 외부 공격자가 액세스하기가 어렵고(예: 서버가 다시 시작되면 지워짐) 시스템 백업에서 제외될 수 있습니다. 시스템 부팅 시 암호 파일이 초기화되었는지 확인해야 합니다.
5. SSL 암호 목록을 보다 안전하게 배포
아래 프로세스는 중앙 배포 지점에서 SSL 암호 목록을 보다 안전하게 배포하는 방법을 설명합니다.
NGINX는 SSL Key를 해독해야 할 때마다 중앙 배포 지점을 쿼리하고 암호를 로컬 디스크에 저장하지 않고 사용합니다. 중앙 암호 서버로 자신을 인증하기 위해 NGINX 인스턴스는 언제든지 취소할 수 있는 토큰을 사용하여 암호에 대한 액세스를 차단합니다.
5-1. 중앙 암호 배포 지점 생성
암호 배포 지점(PDP)을 생성하여 시작합니다. 이 간단한 구현을 위해 HTTPS 서비스를 사용하여 사용자 이름과 암호로 인증된 암호 목록을 제공합니다.
$ curl -u dev0:mypassword https://pdpserver.local/ssl_passwords.txt
password1
password2
...
그런 다음 필요에 따라 PDP에서 인증 토큰을 추가하거나 제거하여 액세스를 활성화하거나 취소할 수 있습니다. NGINX와 같은 웹 서버를 사용하여 암호 배포 서버를 구현할 수 있으며, 적절한 종류의 인증 토큰을 사용할 수 있습니다.
다음으로 PDP에서 암호를 검색하도록 NGINX를 설정해야 합니다. 다음 내용으로 connector.sh라는 셸 스크립트를 만드는 것으로 시작합니다.
#!/bin/sh
# Usage: connector.sh
CONNECTOR=$1
CREDS=$2
PDP_URL=$3
[ -e $CONNECTOR ] && /bin/rm -f $CONNECTOR
mkfifo $CONNECTOR; chmod 600 $CONNECTOR
while true; do
curl -s -u $CREDS -k $PDP_URL -o $CONNECTOR
done
스크립트는 다음과 같이 호출되는 백그라운드 프로세스로 실행되어야 합니다.
root@web1:~# ./connector.sh /var/run/nginx/ssl_passwords \
dev0:mypassword https://pdpserver.local/ssl_passwords.txt &
커넥터는 지정된 로컬 경로(/var/run/nginx/ssl_passwords)에 연결되며 ssl_password_file 지시문을 사용하여 해당 경로에 액세스하도록 NGINX를 구성합니다.
ssl_password_file /var/run/nginx/ssl_passwords;
커넥터 경로에서 읽어 커넥터를 테스트합니다.
root@web1:~# cat /var/run/nginx/ssl_passwords
password1
password2
...
NGINX가 암호를 읽고 SSL Key를 해독할 수 있는지 확인합니다.
root@web1:~# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
중앙 PDP 접근 방식을 사용하여 NGINX가 일반적으로 디스크에서 읽는 모든 리소스(예: 개별 Private Key 또는 기타 중요한 데이터)를 안전하게 배포할 수 있습니다.
5-2. PDP의 보안 의미
이 솔루션은 디스크에 SSL 암호를 저장하는 것과 비교하여 다음과 같은 몇 가지 이점이 있습니다.
- SSL 암호는 서버의 파일 시스템에 저장되지 않으므로 파일 시스템에 액세스할 수 있는 공격자가 직접 액세스할 수 없습니다.
- 암호는 중앙 액세스 지점에서 배포되므로 모니터링 및 감사를 보다 쉽게 수행할 수 있습니다.
- 개별 서버의 액세스를 중앙에서 제어할 수 있습니다. 예를 들어, 서버 권한이 해제되면 액세스 토큰을 해지합니다.
파일 시스템에 액세스할 수 있는 사용자는 잠재적으로 PDP에 액세스하는 데 사용되는 자격 증명을 추출할 수 있습니다. 이러한 자격 증명은 더 이상 필요하지 않을 때 취소하는 것이 중요합니다.
6. SSL 개인키 배포 요약
보안 및 복잡성 수준을 높이면서 노출로부터 SSL 개인키 를 보호하는 방법에는 여러 가지가 있습니다.
- 대부분의 기업에서는 권한이 없는 사용자가 root 액세스 권한을 얻지 못하고 NGINX 구성을 볼 수 없도록 NGINX를 실행하는 환경에 대한 액세스를 제한하는 것으로 충분합니다.
- 일부 환경에서는 NGINX 구성에 대한 액세스를 완전히 제한하는 것이 불가능할 수 있으므로 SSL 암호 파일을 사용할 수 있습니다.
- 제한된 경우 조직은 Key와 암호가 디스크에 저장되지 않도록 할 수 있습니다. 암호 배포 지점 프로세스는 이 솔루션의 개념 증명을 보여줍니다.
NGINX Plus와 함께 안전한 SSL 개인키 배포 테스트를 사용해 보려면 지금 30일 무료 평가판을 신청하거나 사용 사례에 대해 최신 소식을 빠르게 전달받고 싶으시면 아래 뉴스레터를 구독하세요.