14.4.4. CA 서명(공개 신뢰) 인증서

자체 서명 인증서는 양쪽 끝을 모두 제어할 때 동작합니다. 만약 임의의 클라이언트(브라우저, 휴대폰, 서드파티 소프트웨어)가 사용자 정의 인증서를 신뢰하라는 안내 없이 카메라에 연결해야 한다면, 인증서는 그러한 클라이언트들이 이미 신뢰하는 공개 인증 기관(CA)에 의해 서명되어야 합니다. 카메라의 TLS 코드는 자체 서명 경우와 동일합니다. DER 형식의 인증서와 키로 load_cert_chain 을 호출하는 것입니다. 달라지는 것은 그 인증서를 얻는 방법뿐입니다.

가장 중요한 단 하나의 핵심: 개인 키는 여러분이 직접 생성하며 결코 여러분의 기기를 떠나지 않습니다. CA는 그것을 절대 보지 못합니다. 여러분이 CA에 보내는 것은 인증서 서명 요청(CSR) – 여러분의 공개 키와 도메인 이름을 담은 작은 파일 – 이고, 돌려받는 것은 인증서(여러분의 공개 키와 이름에 CA가 서명한 것)입니다. 키와 인증서는 두 개의 별도 단계에서 생성되는 두 개의 별도 파일이며, CA는 오직 공개 절반만 다룹니다.

전체 흐름은 (카메라가 아닌) 일반 머신에서 모두 수행됩니다:

  1. 도메인 이름을 확보하십시오. 공개 CA는 사용자가 제어하는 DNS 이름(예: cam.example.com)을 인증합니다. 단순 IP 주소나 mycam 같은 로컬 전용 이름에 대해서는 발급하지 않습니다.

  2. 키와 CSR을 생성하십시오. 하나의 OpenSSL 명령으로 개인 키와 그에 맞는 CSR이 생성됩니다. 자체 서명 인증서에 사용하는 것과 동일한 키 유형을 사용하십시오(개념: 신뢰, 키, 그리고 파일 형식 참조). ECDSA P-256이 권장됩니다.

    ECDSA P-256 – 권장:

    openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 \
        -nodes -keyout domain.key -out domain.csr \
        -subj "/CN=cam.example.com" \
        -addext "subjectAltName=DNS:cam.example.com"
    

    ECDSA P-384 – 더 강력하지만 더 크고 느림:

    openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:secp384r1 \
        -nodes -keyout domain.key -out domain.csr \
        -subj "/CN=cam.example.com" \
        -addext "subjectAltName=DNS:cam.example.com"
    

    RSA-2048 – 최대 호환성:

    openssl req -new -newkey rsa:2048 \
        -nodes -keyout domain.key -out domain.csr \
        -subj "/CN=cam.example.com" \
        -addext "subjectAltName=DNS:cam.example.com"
    

    domain.key 는 비밀로 유지하십시오. 이것이 결국 카메라에 넣게 될 키 파일입니다. domain.csr 은 CA에 건네는 파일이며 비밀 정보를 담고 있지 않습니다.

  3. CSR을 제출하고 도메인을 제어함을 증명하십시오. 여기서 두 가지 일반적인 경로가 갈립니다:

    • Let’s Encrypt 같은 자동화된 ACME CA는 certbot 이나 acme.sh 같은 도구로 구동되어 2단계와 3단계를 대신 수행합니다. 키를 생성하고, CSR을 구성하고, 챌린지에 자동으로 응답하고(HTTP-01: 도메인의 80번 포트로 토큰을 제공, 또는 DNS-01: 해당 DNS에 TXT 레코드 게시) 완성된 파일을 작성합니다.

    • 상용 CA(직접 구매하거나 도메인/호스팅 리셀러를 통해 구매): domain.csr 텍스트를 웹 양식에 붙여 넣은 다음, 검증 이메일에 회신하거나, DNS 레코드를 게시하거나, 해당 도메인의 웹 서버에 파일을 배치하여 제어권을 증명합니다. 검증되면 발급된 파일을 다운로드합니다.

  4. 발급된 파일을 수집하십시오. 받은 것을 이해하려면 인증서가 신뢰 체인을 이룬다는 것을 아는 것이 도움이 됩니다. 도메인의 인증서는 중간 CA에 의해 서명되고, 그 중간 CA는 다시 루트 CA에 의해 서명됩니다. 각 연결 고리가 그 아래 것을 보증합니다. 최종적으로 다음을 얻게 됩니다:

    • 여러분의 개인 키(2단계에서 생성). CA는 이것을 가진 적이 없습니다. 이것은 여러분의 기기에 남아 있으며 결국 카메라에 넣게 될 키입니다.

    • 리프 인증서 – 엔드 엔티티 또는 서버 인증서라고도 합니다. 이것은 여러분의 특정 도메인(cam.example.com)을 위한 인증서로, 공개 키와 이름을 담고 있으며 CA의 중간 인증서에 의해 서명됩니다. 이것이 카메라가 자신을 식별하기 위해 제시하는 인증서입니다.

    • 하나 이상의 중간 CA 인증서(“체인” 또는 “CA 번들”). CA는 자신의 루트로 여러분의 리프에 직접 서명하지 않습니다 – 루트의 키는 오프라인으로 보관되며 철저히 보호됩니다 – 대신 중간 인증서로 서명하고, 그 중간 인증서는 루트로 서명됩니다. 중간 인증서는 여러분의 리프를 루트까지 연결하는 고리입니다.

    루트 인증서는 신뢰 앵커입니다. 체인의 최상위에 위치하는, CA에 속한 자체 서명 인증서입니다. 모든 클라이언트가 이미 가지고 있기 때문에 여러분에게는 제공되지 않으며 배포하지도 않습니다. 운영 체제, 브라우저, 휴대폰, 언어 런타임은 루트 인증서로 이루어진 내장 “신뢰 저장소”를 함께 제공합니다. 클라이언트는 체인을 따라가며 여러분의 리프를 신뢰합니다. 이미 루트를 신뢰하고, 루트가 중간 인증서를 보증하며, 중간 인증서가 여러분의 리프를 보증합니다. (이것이 바로 자체 서명 경우에서 단일 server.der / cafile 이 하는 일입니다. 거기서는 여러분 자신이 자신의 루트입니다.)

    fullchain 파일은 단순히 리프와 중간 인증서를 리프를 먼저 두고 하나의 파일로 연결한 것이며, 의도적으로 루트를 포함하지 않습니다(루트를 보내는 것은 무의미합니다. 클라이언트는 이미 가지고 있는 루트만 신뢰하기 때문입니다). 일반 서버는 어떤 클라이언트라도 체인을 따라갈 수 있도록 이 전체 fullchain을 제시합니다. 카메라는 그럴 수 없습니다. 하나의 인증서(리프)만 로드하고 제시하며, CA가 준 중간 인증서를 함께 보낼 수 없습니다.

    실제로 보게 될 파일 이름: certbot 같은 ACME 도구는 privkey.pem(키), cert.pem(리프 단독), chain.pem(중간 인증서 단독), fullchain.pem(리프 + 중간 인증서)을 작성합니다. 상용 CA는 보통 리프에 대해 .crt 를, 중간 인증서에 대해 .ca-bundle 을 제공하며, .key 는 여러분이 직접 생성한 것입니다.

  5. 변환하고 복사하십시오. 개인 키와 리프 인증서를 DER로 변환하고 자체 서명 인증서 에서와 똑같이 카메라로 복사하십시오. 그러면 카메라는 이를 자신의 서버 인증서로 제시하며, 표준 클라이언트는 이미 CA를 신뢰하기 때문에 연결을 자동으로 수락합니다. 클라이언트 측 구성은 필요 없습니다.

실제로, 카메라가 리프만 제시하고(중간 인증서는 절대 제시하지 않고) 동작하는 양상은 다음과 같습니다:

  • CA의 중간 인증서를 이미 캐시해 둔 클라이언트(주류 브라우저와 HTTPS 라이브러리는 보통 그렇습니다)는 스스로 체인을 완성하여 문제없이 연결됩니다.

  • 중간 인증서를 서버가 제공해 주기를 기대하는 클라이언트는 카메라에 대한 핸드셰이크에 실패합니다.

가능한 모든 클라이언트가 반드시 성공해야 한다면, 공개 TLS를 카메라에서 직접 종단하지 마십시오. 외부 세계에 전체 체인을 제공하는 게이트웨이/리버스 프록시를 그 앞에 두고, 그 프록시가 위에서 설명한 자체 서명 흐름으로 카메라에 도달하도록 하십시오.