블로그 | NGINX

HashiCorp Vault를 사용하여 NGINX에서 SSL 개인 키 보호

NGINX-F5-수평-검정-유형-RGB의 일부
오웬 개렛 썸네일
오웬 개렛
2019년 4월 16일 게시

이 시리즈의 첫 번째 게시물 에서는 SSL 개인 키의 보안을 개선하기 위한 여러 가지 접근 방식을 설명합니다. 이 게시물은 NGINX 인스턴스와 암호화된 비밀번호를 안전하게 공유하는 데 사용되는 원격 비밀번호 배포 지점(PDP) 시연으로 마무리되었습니다.

HashiCorp Vault 와 같은 비밀 관리 시스템은 샘플 PDP와 유사한 방식으로 작동합니다.

  • HTTPS 또는 다른 API를 사용하여 액세스하는 중앙(또는 고가용성 및 분산) 비밀 서비스를 사용합니다.
  • 클라이언트는 인증 토큰이나 기타 수단을 통해 인증됩니다.
  • 토큰은 비밀에 대한 액세스를 제어하기 위해 필요에 따라 취소될 수 있습니다.

이 게시물에서는 HashiCorp Vault를 설정하여 SSL 비밀번호를 배포하는 방법을 보여드립니다. 보안을 더욱 강화하려면 외부 하드웨어 보안 모듈(HSM)을 설정할 수 있습니다.

SSL 인증서-키 쌍의 디스크 저장을 완전히 없애려면 이 시리즈의 세 번째 게시물 인 NGINX Plus 키-값 저장소를 사용하여 HashiCorp Vault에서 임시 SSL 키를 보호하는 방법을 참조하세요. HashiCorp Vault에서 임시 SSL 키를 생성하고 이를 NGINX Plus 키-값 저장소의 메모리에 저장하는 방법을 설명합니다.

이 게시물은 NGINX 오픈 소스와 NGINX Plus에 모두 적용됩니다. 읽기 편하도록 이 문서 전체에서 NGINX를 참조하겠습니다.

HashiCorp Vault를 사용하여 SSL 개인 키 보호

이 섹션의 지침에서는 Vault를 사용하여 SSL 비밀번호를 배포하는 중앙 PDP 서버를 설정합니다. 이러한 정책은 DigitalOcean의 지침을 기반으로 하며, 사용자의 Vault 정책을 준수하도록 필요에 따라 수정하시기 바랍니다.

우리의 예에서 각 원격 웹 서버는 고유한 인증 토큰을 가지고 있습니다. 이러한 토큰은 Vault의 secret/webservers/ 경로에 있는 비밀에 액세스하는 데 사용할 수 있으며, SSL 비밀번호는 secret/webservers/ssl_passwords 에 저장됩니다.

토큰을 보호하는 방법과 필요한 경우 개별 인증 토큰을 취소하는 방법을 살펴보겠습니다.

PDP 서버에서 HashiCorp Vault 다운로드, 설치 및 초기화

  1. DigitalOcean의 지침 에 따라 PDP 서버에 Vault를 다운로드하고 추출하세요. 다음 샘플 /etc/vault.hcl 파일을 사용하여 Vault에 원격으로 접근할 수 있게 하고, 테스트 시 사용하기 쉽도록 TLS를 비활성화합니다.

    백엔드 "파일" { 경로 = "/var/lib/vault"
    }
    
    리스너 "tcp" {
    주소 = "0.0.0.0:8200"
    tls_disable = 1
    }
    
  2. 시작 스크립트(만든 경우)를 사용하여 Vault를 시작하거나 수동으로 시작합니다.

    사용자@pdp:~$ sudo /usr/local/bin/vault 서버 -config=/etc/vault.hcl
    
  3. Vault를 초기화하고 초기 루트 토큰을 얻습니다.

    user@pdp:~$ export VAULT_ADDR=http://localhost:8200 user@pdp:~$ vault init -key-shares=3 -key-threshold=2 user@pdp:~$ vault operator unseal 초기 루트 토큰: 86c5c2a4-8ab2-24dd-1816-48449c83114e
    
  4. 다음 명령의 대부분에서 초기 루트 토큰을 제공해야 합니다. 편의상 root_token 셸 변수에 할당합니다.

    사용자@pdp:~$ root_token=86c5c2a4-8ab2-24dd-1816-48449c83114e
    

비밀을 저장하세요

  1. PDP 서버에서 작업 중이라면, 비밀번호가 들어 있는 /tmp/ssl_passwords.txt 라는 임시 파일을 만드세요.

  2. 이 파일을 Vault에 비밀로 저장하고 검색할 수 있는지 확인하세요.

    user@pdp:~$ VAULT_TOKEN=$root_token vault kv 비밀/웹 서버/ssl_암호 값을 넣습니다=@/tmp/ssl_passwords.txt user@pdp:~$ VAULT_TOKEN=$root_token vault kv get -필드=값 비밀/웹 서버/ssl_암호 암호1 암호2 ...
    
  3. 보안을 위해 /tmp/ssl_passwords.txt를 삭제하세요.

  4. 다음 내용으로 web.hcl 이라는 파일에 정책 사양을 만듭니다.

    경로 "secret/webservers/*" {
    기능 = ["읽기"]
    }
    
  5. Vault에 정책을 로드하고 이름을 web으로 지정합니다.

    user@pdp:~$ VAULT_TOKEN=$root_token vault 정책 쓰기 웹 web.hcl
    
  6. 새 인증 토큰을 만들고 정책과 연결하고, 선택적으로 display-name 매개변수를 포함하여 사용자에게 친숙한 이름을 지정합니다. tokentoken_accessor 값을 기록해 두세요. 이후 명령에서 이 값을 사용하게 됩니다.

    user@pdp:~$ VAULT_TOKEN=$root_token vault 토큰 생성 -policy=web -display-name=webserver1 키 값 --- ----- 토큰 dcf75ffd-a245-860f-6960-dc9e834d3385 토큰_액세스자 0c1d6181-7adf-7b42-27be-b70cfa264048
    

    NGINX 웹 서버는 이 토큰을 사용하여 SSL 비밀번호를 검색합니다. 정책은 웹 서버가 secret/webservers/* 경로 외부의 비밀을 검색하는 것을 방지합니다.

웹 서버가 토큰을 검색할 수 있는지 확인

  1. NGINX 웹 서버에서 작업하여 Vault 바이너리를 설치합니다.
  2. 원격 Vault 서버의 위치(여기서는 http://pdp:8200 )를 선언한 다음, 웹 서버 머신이 토큰을 사용하여 SSL 비밀번호를 검색할 수 있는지 확인합니다.

    user@web1:~$ export VAULT_ADDR=http://pdp:8200 user@web1:~$ VAULT_TOKEN=dcf75ffd-a245-860f-6960-dc9e834d3385 vault kv get -field=value secret/webservers/ssl_passwords password1 password2 ...
    

웹 서버에서 NGINX Vault Connector 구성

  1. 첫 번째 게시물 의 샘플 PDP를 설정하는 과정의 일부로 NGINX 호스트(웹 서버 머신)에 connector.sh 라는 셸 스크립트를 만들었습니다. 여기서는 Vault를 사용하도록 수정합니다.

    #!/bin/sh
    # 사용법: connector_v.sh 
    
    CONNECTOR=$1
    CREDS=$2
    
    [ -e $CONNECTOR ] && /bin/rm -f $CONNECTOR
    
    mkfifo $CONNECTOR; chmod 600 $CONNECTOR
    
    export VAULT_ADDR=http://pdp:8200
    export VAULT_TOKEN=$CREDS
    
    while true; do
    vault kv get -field=value secret/webservers/ssl_passwords > $CONNECTOR
    sleep 0.1 # 경쟁 조건, EOF 보장
    done
    
  2. 다음과 같이 호출하여 백그라운드 프로세스로 스크립트를 실행합니다.

    root@web1:~# ./connector_v.sh /var/run/nginx/ssl_passwords \dcf75ffd-a245-860f-6960-dc9e834d3385 &
    
  3. 커넥터 경로에서 읽어 커넥터를 테스트합니다.

    root@web1:~$ cat /var/run/nginx/ssl_passwords 비밀번호1 비밀번호2 ...
    
  4. NGINX가 시작 시 ssl_passwords 파일을 읽고, 그 내용을 암호로 사용하여 암호화된 개인 키를 해독하도록 구성합니다. ssl_password_file 지시문을 서버 블록(첫 번째 게시물의 표준 구성 에 대해 생성된 것과 같은)이나 http 컨텍스트에 포함하여 여러 가상 서버에 적용할 수 있습니다.

    ssl_password_file /var/run/nginx/ssl_passwords;
    
  5. NGINX가 비밀번호를 읽고 SSL 키를 해독할 수 있는지 확인하세요.

    root@web1:~# nginx -t nginx: 설정 파일 /etc/nginx/nginx.conf 구문은 정상입니다. nginx: 설정 파일 /etc/nginx/nginx.conf 테스트가 성공했습니다.
    

웹 서버의 인증 토큰 취소

웹 서버가 손상되거나 사용이 중단된 경우 쉽게 접근을 취소할 수 있습니다. 그렇게 하려면 웹 서버에서 사용하는 인증 토큰을 직접 취소할 수 있습니다.

user@pdp:~$ VAULT_TOKEN=$root_token 볼트 토큰 취소 dcf75ffd-a245-860f-6960-dc9e834d3385

Vault 토큰은 민감한 데이터 항목이며, 많은 Vault 워크플로는 인증된 클라이언트에게 발급된 토큰 사본을 저장하지 않습니다. 토큰 사본이 유출되면 공격자는 클라이언트를 사칭할 수 있습니다.

대신, 토큰에 대한 제한적인 권한을 부여하고 토큰 값을 검색하는 데 사용할 수 없는 접근자를 사용하여 활성 토큰을 관리하는 것이 일반적입니다. 토큰이 발급될 때 토큰을 저장하는 대신, 해당 접근자를 저장합니다.

웹 서버의 인증 토큰에 대한 액세서를 확인해야 하는 경우 vault list 명령을 실행하여 액세서 목록을 검색하고, 각 액세서에서 vault token lookup 명령을 실행하여 관련 표시 이름과 정책이 있는 액세서를 찾습니다.

user@pdp:~$ VAULT_TOKEN=$root_token vault list /auth/token/accessors 키 ---- 83be5a73-9025-1221-cb70-4b0e8a3ba8df 0c1d6181-7adf-7b42-27be-b70cfa264048 f043b145-7a63-01db-ea85-9f22f413c55e user@pdp:~$ VAULT_TOKEN=$root_token vault 토큰 조회 -accessor 0c1d6181-7adf-7b42-27be-b70cfa264048 키 값 --- ----- ... 표시 이름 웹 서버1 ... 정책 웹 ...

그런 다음 접근자를 사용하여 토큰을 취소할 수 있습니다.

user@pdp:~$ VAULT_TOKEN=$root_token 볼트 토큰 취소 -액세서 0c1d6181-7adf-7b42-27be-b70cfa264048

보안 의미

Vault를 사용하면 첫 번째 게시물 에서 설명한 샘플 PDP와 유사한 보안 프로필을 갖게 됩니다. SSL 개인 키는 해당 비밀번호를 얻은 경우에만 얻을 수 있으며, 이를 위해 공격자는 현재 인증 토큰의 값을 알아야 합니다.

Vault를 사용하는 주요 이점은 비밀 저장소를 자동화하고 확장하는 것입니다.

외부 HSM을 사용하여 개인 키 관리

지금까지 이 시리즈에서 다룬 솔루션 중 어느 것도 공격자가 NGINX 서버의 루트 액세스 권한을 얻었을 때 개인 키를 보호하지 못합니다. 공격자가 NGINX의 런타임 메모리에 액세스하거나 코어 덤프를 생성할 수 있는 경우 프로세스의 메모리를 스캔하고 개인 키 데이터를 찾는 잘 알려진 기술이 있습니다.

외부 하드웨어 보안 모듈(HSM)은 SSL 개인 키를 변조 방지 외부 하드웨어에 저장하여 이 문제를 해결합니다. 이들은 복호화를 서비스로 제공하고, NGINX는 kay가 필요한 SSL 작업을 수행할 때마다 해당 서비스에 액세스합니다.

NGINX 서버는 SSL 개인 키 데이터를 볼 수 없습니다. 서버에서 루트 액세스 권한을 얻은 공격자는 SSL 개인 키를 얻을 수 없지만, NGINX 자격 증명을 사용하여 HSM 암호 해독 서비스에 액세스하여 필요에 따라 데이터를 암호 해독할 수 있습니다.

HSM에 액세스하기 위한 NGINX 구성

NGINX는 모든 SSL 개인 키 작업을 OpenSSL이라는 암호화 라이브러리에 위임합니다. 타사 HSM 장치는 HSM 공급업체의 OpenSSL 엔진을 사용하여 NGINX에서 사용할 수 있습니다.

NGINX 구성은 각 공급업체 HSM에 따라 다르지만 일반적으로 간단한 경로를 따릅니다.

  • 기본 소프트웨어 엔진이 아닌 공급업체의 OpenSSL 엔진을 사용하도록 NGINX를 구성합니다.

    ssl_certificate_key 엔진:공급업체-hsm-엔진:...;
    
  • 실제 개인 키를 사용하는 대신 공급업체에서 제공한 '가짜' 키를 사용하도록 NGINX를 구성합니다. 이 키에는 HSM 장치의 실제 키를 식별하는 핸들이 포함되어 있습니다.

    ssl_certificate_key ssl/vendor.private.key;
    

    키에는 HSM 장치에 액세스하는 데 필요한 자격 증명이 포함되어 있을 수도 있고, 추가적인 공급업체별 구성을 사용하여 자격 증명을 제공할 수도 있습니다.

  • (선택 사항) NGINX 작업자 프로세스 수를 늘리는 등 원하는 튜닝을 적용하여 NGINX 및 HSM의 성능을 극대화합니다.

HSM 설정의 예는 Amazon의 CloudHSM 설명서를 참조하세요.

보안 의미

외부 HSM은 SSL 개인 키를 저장하는 매우 안전한 방법입니다. NGINX 서버에 대한 루트 액세스 권한이 있는 공격자는 NGINX 자격 증명을 활용하여 HSM을 사용하여 임의의 데이터를 해독할 수 있지만, 암호화되지 않은 개인 키를 얻을 수는 없습니다. HSM은 공격자가 웹사이트를 사칭하거나 오프라인에서 임의의 데이터를 해독하는 것을 상당히 어렵게 만듭니다.

결론

SSL 개인 키와 같은 비밀 데이터는 공개 시 매우 심각한 결과를 초래할 수 있으므로 완벽하게 보호하는 것이 필수적입니다.

적절한 보안 프로세스를 구축한 많은 조직의 경우, 프런트엔드 로드 밸런서에 개인 키를 저장한 다음 해당 서버에 대한 모든 액세스를 제한하고 감사합니다(첫 번째 게시물에서 설명한 표준 구성 ).

NGINX 구성을 자주 배포해야 하는 조직의 경우 이 게시물과 첫 번째 게시물 의 조치를 사용하여 개인 키 데이터를 볼 수 있는 사용자 또는 엔터티를 제한할 수 있습니다.

이 시리즈의 세 번째 게시물 인 NGINX Plus 키-값 저장소를 사용하여 HashiCorp Vault의 임시 SSL 키를 보호하는 방법 에서는 NGINX Plus API를 사용하여 Vault에서 NGINX Plus의 키-값 저장소 로 키와 인증서를 자동으로 프로비저닝하는 방법을 설명합니다.

이러한 방법 중 어느 것도 실행 중인 NGINX 인스턴스를 원격 액세스나 구성 조작으로부터 완벽하게 보호할 필요성을 줄여주지는 않습니다.

NGINX Plus를 직접 사용해 보세요. 오늘 무료 30일 체험판을 시작하거나 저희에게 연락하여 사용 사례에 대해 논의해 보세요 .


"이 블로그 게시물에는 더 이상 사용할 수 없거나 더 이상 지원되지 않는 제품이 참조될 수 있습니다. 사용 가능한 F5 NGINX 제품과 솔루션에 대한 최신 정보를 보려면 NGINX 제품군을 살펴보세요. NGINX는 이제 F5의 일부가 되었습니다. 이전의 모든 NGINX.com 링크는 F5.com의 유사한 NGINX 콘텐츠로 리디렉션됩니다."