VPN 개인 키는 어디에 있어야 하는가: 파일, CNG, TPM?
VPN ID를 위해 키 파일, 내보낼 수 없는 소프트웨어 저장소, TPM 중에서 고르고, 그 선택을 명령과 롤백 계획으로 증명한다.
VPN 개인 키가 어디에 있어야 하는지는 두 질문이 정한다. 키 재료를 호스트 밖으로 복사할 수 있는가, 그리고 아무도 키보드 앞에 없어도 프로세스가 그것을 쓸 수 있는가. 저장소의 마케팅 이름은 둘 다에 답하지 않는다. 재부팅 뒤 다시 올라와야 하는 터널 데몬은 무인 사용이 필요하고, 사람이 입력하는 PIN에 묶인 것은 배제된다.
복사와 사용 중 무엇을 택할지
복사와 사용은 서로 다른 방식으로 실패한다. 그래서 하나가 아니라 두 요구 사항으로 다뤄야 한다. 키 바이트를 읽을 수 있는 공격자는 ID를 다른 호스트로 가져가고, 원래 기계는 알아채지 못한다. 바이트는 읽지 못하지만 서명 과정에 닿는 공격자는 그 접근이 유지되는 동안 계속 인증된다.
파일 키는 아주 쉽게 복사된다. 그래서 백업과 복원도 가장 쉽다. 소프트웨어 키 저장소는 API를 바꾸지 경계를 바꾸지 않는다. 공급자는 자체 내보내기 호출을 거부하지만, 키를 설치한 같은 관리자 컨텍스트에는 보통 다른 경로가 있다. 소프트웨어 공급자에서의 내보낼 수 없음은 지원되는 작업에 대한 진술이지 하드웨어 벽의 증거가 아니다. 무심한 복사에 대한 감속 방지턱으로 보고, 이미 세션을 쥔 상대에 대한 방어로 여기지 말 것.
TPM이나 스마트 카드는 서명 작업을 하드웨어 안에서 수행하고 결과만 돌려준다. 이것으로 복사 경로가 닫히고, 사용 경로는 서명을 요청할 수 있는 모든 것에 열린 채로 남는다.
저장소를 터널 데몬에 맞춘다
데몬은 보안 정책보다 더 강하게 이를 제한한다. WireGuard는 base64 개인 키를 파일이나 wg set 입력에서 받고 인증서 저장소로 가는 경로가 없다. 따라서 TPM 기반 인터페이스 키는 논외다. OpenSSL 3에 맞춰 빌드한 OpenVPN은 공급자 URI로 키를 읽을 수 있고 strongSwan은 PKCS#11 지원과 함께 TPM 플러그인을 제공하지만, 둘 다 패키지가 어떻게 컴파일됐는지에 달려 있다.
고른 저장소에 닿지 못하는 데몬은 하드웨어 경계를 장식으로 만든다. 누군가 키를 한 번 내보내 파일에 남기고, 나머지 설계는 그 사본 위에서 조용히 돌아간다.
갱신은 짝 맞추기의 나머지 절반이고, 여기서 대부분의 설계가 무너진다. 첫 등록에서는 되지만 재발급마다 콘솔 로그인을 요구하는 저장소는 인증서가 불편한 시각에 만료되는 첫 순간 우회된다. 현재 키에 아직 몇 달이 남아 있을 때 재발급 경로를 시험하라.
키를 옮기기 전에 목록을 만든다
키가 무엇이고 어디에 사는지를 바꾸기 전에 기록하라. subject alternative names를 잃는 이전은 라우팅 장애처럼 읽히는 방식으로 터널을 깨뜨린다. 인증서를 덤프하고, 데몬이 기대하는 곳에서 개인 키를 읽을 수 있는지 확인하고, 쌍이 실제로 맞는지 검사하라.
openssl x509 -in vpn.crt -noout -subject -ext subjectAltName
openssl pkey -in vpn.key -check -noout
openssl x509 -in vpn.crt -noout -pubkey | openssl sha256
openssl pkey -in vpn.key -pubout | openssl sha256
마지막 두 다이제스트는 같아야 한다. 그렇지 않으면 데몬은 설정을 마친 뒤 실제 원인 근처도 가리키지 않는 인증서나 서명 오류로 매번 실패한다. WireGuard 쪽은 더 짧다. 공개 키가 개인 키에서 직접 나오기 때문이다. wg pubkey < /etc/wireguard/wg0.key는 서버가 이미 보관한 피어 키를 출력해야 한다.
권한도 같은 목록에 속한다. stat -c '%a %U:%G' /etc/wireguard/wg0.key는 600 root:root를 돌려줘야 하고, 그룹이나 전체가 읽을 수 있다면 의도하지 않은 프로세스에 키가 이미 노출된 것이다.
저장소와 사용 경로를 확인한다
검증은 세 부분이고 세 번째가 빠진다. 고른 저장소에 키가 있는지, 데몬이 남은 사본이 아니라 그 키를 읽었는지, 그리고 내보내기 산출물이 사라진 뒤에도 시작되는지 확인한다.
certutil -store -user My
certutil -csp "Microsoft Platform Crypto Provider" -key -user
certutil -verifykeys -user My
ipsec listcerts
Windows에서 첫 명령은 개인 저장소를 나열하고 각 항목 옆에 키 공급자를 찍는다. 여기서 하드웨어 지원처럼 보이지만 소프트웨어 공급자에 앉아 있는 인증서가 드러난다. 두 번째는 플랫폼 암호 공급자가 가진 키를 나열하므로, 인증서는 있는데 VPN ID가 거기 없다면 개인 절반은 다른 곳에 사는 것이다. Linux 게이트웨이에서 ipsec listcerts는 strongSwan이 읽은 것을 TPM 플러그인에서 온 키까지 보고한다. 항목 수를 믿지 말고 지문이나 공개 키 해시를 목록과 비교하라.
부정 테스트가 설계를 증명한다. 내보낸 키를 데몬 설정 디렉터리 밖으로 옮기고, 서비스를 다시 시작하고, 로그에서 어떤 ID를 제시하는지 읽어라. 그래도 올라오는 터널은 저장소를 쓰는 것이고, 시작에 실패하면 설계는 정말 사본 위에서 돌고 있었다.
갱신과 롤백을 적는다
롤백은 두 계열에서 크게 다르고, 그 차이는 사고 대응 전화가 아니라 설계 메모에 속한다. 파일 키는 암호화해 백업하고 복원할 수 있으므로 실패한 이전은 되돌릴 수 있다. 내보낼 수 없는 키는 아예 백업할 수 없어서, 장치가 죽으면 재발급과 재등록이 유일한 복구 경로가 된다.
중단이 되기 전에 만료를 점검하라. openssl x509 -in vpn.crt -noout -checkend 2592000는 인증서가 삼십 일 안에 만료되면 영이 아닌 코드로 끝나므로 감시 점검에 그대로 들어간다. 그 줄을 매주 돌리면 아무도 계획하지 않은 갱신을 잡는다.
삭제는 서버에서 한다. 피어를 지우거나 일련번호를 폐기하고, 터널이 실패하는지 확인하라. 캐시된 세션을 가진 클라이언트는 절반만 끝난 폐기를 한동안 숨길 수 있다. 폐기는 CA 데이터베이스만이 아니라 집중기의 CRL이나 OCSP 경로에도 닿아야 한다. 인증서는 공개 문서이고 RFC 5280 프로파일이 검증 방법을 다루지만, 그 검증은 회전 전에 복사된 개인 키를 보호하지 않는다.
결정을 한곳에 적어라. 어느 저장소가 키를 보관하고, 어느 프로세스가 써도 되고, 누가 재발급할 수 있고, 롤백은 무엇인지. 그 문단이 감사인이 묻는 것이고, 담당자가 바뀌어도 남는 것이다.