머지않아 VPN 사용자가 개인 키를 이메일로 보내 관리자가 인증서를 만들게 해 주겠다고 제안합니다. 거절해야 할 것은 바로 그 제안입니다. 작동하는 흐름은 첫 명령부터 키를 클라이언트에 둡니다. 클라이언트가 키를 생성하고 인증서 서명 요청을 보내면, 발급자가 이를 검증하고 승인하며, 서명된 인증서는 그것을 만든 키 옆으로 돌아옵니다. 아래 체크리스트는 각 단계에서 폐쇄적으로 실패하며, 그것이 핵심입니다. 다섯 단계 중 둘은 사람들이 급할 때 건너뛰는 단계이기 때문입니다.

1단계: 키가 살 자리에서 생성하세요

키를 보관할 기계에서 생성하고 그곳에 두세요. 소프트웨어 키는 엄격한 권한을 가진 파일이 됩니다. 하드웨어 기반 키나 관리형 저장소의 키는 파일이 되지 않으며, 등록 경로는 보통 OpenSSL 명령이 아니라 별도 도구입니다. 어느 쪽이든 개인 절반을 누가 볼 필요는 없습니다.

소프트웨어 흐름은 이렇습니다. 키와 요청을 한 세션에서 만듭니다.

umask 077
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out client.key
openssl req -new -key client.key -out client.csr -subj "/CN=alice-vpn/O=Example"

umask 줄은 보기보다 중요합니다. 이것이 없으면 기본적으로 관대한 시스템에서 키가 누구나 읽을 수 있게 기록되고, 나중에 파일을 복사하면 그것이 퍼집니다. 기존 키의 재사용은 이미 보호되어 있고 정책에 맞는다면 정당합니다. 기기마다 새로 만드는 편이 설명하기 쉽습니다.

2단계: 신원은 요청 안에 두고 이메일에는 두지 마세요

요청이 만들어지기 전에 VPN이 실제로 무엇을 인증하는지 정하세요. 그 답은 CSR 안에 들어가야 하기 때문입니다.OpenVPN 는 전통적으로 클라이언트 신원을 인증서의 일반 이름에 묶고, strongSwan 같은 도구는 신원 문자열을 주체나 주체 대체 이름과 대조합니다. 내 이름은 alice라고 말하는 이메일은 증거가 아니며, 주체가 같은 말을 하는 요청은 조금 나을 뿐입니다.

검증기가 주체 대체 이름을 확인한다면 추가하세요. 현대의 대조는 흔히 오래된 CN을 무시합니다.

openssl req -new -key client.key -out client.csr \
  -subj "/CN=alice-vpn/O=Example" \
  -addext "subjectAltName=DNS:alice-vpn"

CN은 짧고 안정적으로 유지하고 노트북 모델이 아니라 계정에 묶으세요. 사용자 기기의 일련번호가 들어간 이름은 첫 하드웨어 교체를 기다리는 지원 문제입니다.

3단계: 서명하기 전에 요청을 검증하세요

발급자는 두 가지 다른 것을 검증하며, 이를 혼동하는 것이 전형적인 실수입니다. 첫째, 요청이 내부적으로 일관되는지입니다. 서명은 요청이 지닌 공개 키에 대해 검증됩니다. 둘째, 요청자가 요청하는 것에 대한 권리가 있는지입니다. 이는 어떤 암호학적 검사로도 답할 수 없습니다.

기계적인 부분은 명령 하나이며, 주체와 함께 검증 결과를 출력해야 합니다.

openssl req -in client.csr -noout -verify -subject
openssl req -in client.csr -noout -pubkey | openssl pkey -pubin -noout -text

이것이 무엇을 증명하는지 보세요. 검증을 통과한 요청은 보낸 사람이 제출 시점에 대응하는 개인 키를 가지고 있었다는 것만 보여 줍니다. 보낸 사람이 주체에 적힌 사람이라는 것을 증명하지 않으며, 요청된 그룹이나 경로 접근을 승인하지도 않습니다. 등록 심사는 별도의 관문이며, 아무도 승인하지 않은 그룹을 요청하는 요청은 조용히 편집하는 대신 거부해야 합니다.

4단계: 승인한 뒤 명시적 확장으로 서명하세요

서명은 CA가 요청을 그대로 받아들이는 대신 정책을 결정하는 지점입니다. 유효 기간, 키 용도, 역할 확장은 확장 파일에 속하며, 반년 뒤에 기억나지 않을 기본값에 속하지 않습니다. VPN 인증용 클라이언트 인증서는 용도로 클라이언트 인증이 필요합니다.

cat > client.ext <<'EOF'
basicConstraints = CA:FALSE
keyUsage = digitalSignature
extendedKeyUsage = clientAuth
EOF
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \
  -CAcreateserial -days 365 -extfile client.ext -out client.crt

이미 사용 중인 일련번호 파일이 있다면 -CAserial 를 그것과 함께 사용하고, CA 키는 오프라인이나 정책이 지정한 보호된 저장소에 두세요. 인증서 일련번호는 발급자마다 고유해야 합니다. 일련번호 파일을 처음부터 다시 만들면 충돌 위험이 있고 폐기가 모호해집니다.

무엇이 발급되었는지 기록하세요. 일련번호, 주체, 요청된 신원, 승인자, 만료입니다. 그 기록이 나중에 폐기 결정이 기대는 대상이며, 등록 흔적이 우편함에만 있다면 인증서만으로 재구성할 수 없습니다.

5단계: 대응하는 키 옆에 설치하고 쌍을 증명하세요

클라이언트가 받는 것은인증서와 발급자 체인이며, 키가 아닙니다. 연결하기 전에 인증서가 디스크에 이미 있는 키와 실제로 쌍을 이루는지 확인하세요. 맞지 않는 쌍은 훨씬 뒤에 혼란스러운 핸드셰이크 실패를 만듭니다:

openssl x509 -in client.crt -noout -pubkey | openssl pkey -pubin -outform DER | openssl sha256
openssl pkey -in client.key -pubout -outform DER | openssl sha256

두 다이제스트가 일치해야 합니다. 그런 다음 연결하고 서버가 기록하는 신원이 승인한 신원인지 확인하세요. 터널이 올라왔다는 것만으로는 부족합니다. 키를 잃거나 기기를 교체하면 답은 폐기와 새 기기에서의 새 요청입니다. 관리자에게 다른 곳에서 키를 다시 보내 달라고 해도 원본은 되찾지 못하고, 요청을 안전하게 만든 모델이 조용히 깨집니다.

관련 글