Webship 블로그로 돌아가기

Webship 엔지니어링

Webship의 TLS 인증서: 내장 ACME CA

Webship 1.4.0가 내장 CA로 각 사이트별 개인 TLS 인증서를 발급하고 갱신하는 방식, 클라이언트 신뢰가 작동하는 방식, 그리고 내장된 인증서가 공개 ACME 및 수동 인증서와 공존하는 방식을 확인하세요.

# Webship의 TLS 인증서: 내장 ACME CA

TLS 인증서는 두 가지 역할을 합니다: 연결을 암호화하는 데 도움을 주고, 클라이언트에게 자신이 어떤 정체성과 통신하고 있는지 알려줍니다. 암호화는 강력할 수 있지만, 신뢰 결정이 대상 사용자에게 잘못될 수 있습니다. 그렇기 때문에 인증서 자동화는 한 가지 질문에서 시작해야 합니다: 누가 이 사이트를 신뢰해야 합니까?

Webship 1.4.0은 구성된 각 사이트에 대해 독립적으로 해당 선택을 합니다. 공개 웹사이트는 브라우저가 신뢰하는 ACME 인증서를 사용할 수 있고, 내부 서비스는 Webship의 내장 개인 인증 기관을 사용할 수 있으며, 기존 PKI가 있는 사이트는 운영자가 관리하는 인증서 파일을 유지할 수 있습니다. 이들은 모두 하나의 Webship 프로세스를 공유할 수 있지만, 하나의 개인 키나 하나의 신뢰 경계를 공유하지는 않습니다.

사이트별로 선택 가능한 네 가지 자동 인증서 모드

certificate_mode 필드는 각 [[sites]] 항목에 속합니다. 이것은 전역 스위치가 아닙니다.

| 모드 | 신뢰할 수 있는 출처 | 가장 적합 | 검증 경로 | | --- | --- | --- | --- | | per_site | 공용 브라우저 및 운영 체제 신뢰 저장소 | 정확히 하나의 호스트 이름을 가진 공용 사이트 | TLS-ALPN-01 지원 공용 ACME | | 플릿 | 공개 브라우저 및 운영 체제 신뢰 저장소 | 명시적으로 등록된 도메인 하위의 3단계 및 4단계 이름 대규모 세트 | DNS-01을 사용하는 공개 ACME 및 안정적인 인증서 조각 | | 내장 | 운영자가 설치한 개인 Webship 루트 | 내부 서비스, 관리되는 장치, 개인 플릿, 테스트 환경 | 프로세스 내 발급; 외부 인증 없음 | | 공유 | 공개 브라우저 및 운영 체제 신뢰 저장소 | 의도적으로 하나의 공개 다중 SAN 그룹을 사용하는 기존 배포 | TLS-ALPN-01을 사용하는 공개 ACME |

기본값은 per_site입니다. 이는 사이트의 정확한 이름에 대해 하나의 공개 인증서를 발급합니다. 플릿 모드는 많은 깊은 서브도메인에 대해 확장 가능한 공개 옵션입니다. 임베디드 모드는 Webship의 사설 프로세스 내 CA를 사용합니다. 공유 모드는 호환성을 위해 계속 사용할 수 있지만 기본값은 아닙니다.

[sites.tls] 하의 완전한 인증서와 키는 항상 해당 사이트의 자동 발급보다 우선합니다.

“내장형 ACME CA”가 의미하는 것

구성 섹션의 이름은 [acme_ca]이지만, 내장된 CA는 공개적이거나 네트워크에서 접근 가능한 ACME 서비스가 아닙니다. 디렉토리 엔드포인트를 제공하지 않고, 원격 등록을 받지 않으며, 등록자 API를 호출하지 않고, 제어 증명(challenge)도 수행하지 않습니다.

대신, Webship는 전체 개인 발행 경로를 하나의 프로세스에서 유지합니다:

  1. 사이트가 certificate_mode = "embedded"를 선택합니다.
  2. Webship은 구성된 상태 디렉토리에서 개인 루트 아이덴티티를 로드하거나 생성합니다.
  3. Webship는 사이트를 위한 새로운 개인 키를 생성합니다.
  4. 내장된 루트가 해당 정확한 이름에 대한 인증서를 서명합니다.
  5. Webship은 라이브 TLS 리졸버에 설치하기 전에 완료된 신원을 검증합니다.
  6. 그 인증서는 해당 사이트의 모든 활성화된 프로토콜에서 이용할 수 있습니다.

ACME 스타일의 네트워크 챌린지는 오직 Webship 에게만 증명될 수 있으므로, 임베디드 경로에는 의도적으로 네트워크 프로토콜이 없습니다. [acme_ca] 섹션은 개인 PKI 상태로, 루트가 어디에 있는지와 발급된 리프 인증서가 얼마나 오래 유효한지를 정의합니다.

한 사이트에 임베디드 인증서를 구성합니다

이것은 개인 사이트를 위한 최소 형태입니다:

~~~톰엘 listen = "0.0.0.0:443"

[tls] unknown_sni = "reject"

[자동_tls] enabled = true cache_dir = "/var/lib/webship/acme"

[acme_ca] state_dir = "/var/lib/webship/acme-ca" leaf_validity_days = 90

[[사이트]] 도메인 = "service.internal.example" root = "/srv/service" certificate_mode = "embedded"

[사이트.프로토콜] h1 = 참 h2 = true h3 = 참 ~~~

루트 아이덴티티는 임베디드 사이트가 처음 필요로 할 때 지연 생성됩니다. Webship는 state_dir에 제한된 권한으로 루트 키를 유지합니다. 루트 인증서의 유효 기간은 10년이며, 리프의 유효 기간은 leaf_validity_days에 의해 제어됩니다.

두 저장 위치를 모두 생산 상태로 취급하십시오:

  • ACME 캐시는 자동으로 관리되는 사이트 아이덴티티를 저장합니다.
  • 내장 CA 상태 디렉토리는 개인 루트 ID를 보관합니다.
  • 서비스 계정에는 접근 권한이 필요하지만, 애플리케이션 사용자는 필요하지 않습니다.
  • 백업은 기밀성과 파일 권한을 유지해야 합니다.
  • 생산, 개발, 테스트는 각각 다른 루트와 다른 디렉터리를 사용해야 합니다.

루트 디렉토리를 삭제한다고 TLS가 '재설정'되는 것은 아닙니다. 이는 새로운 신뢰 앵커를 생성합니다. 이전 루트를 신뢰하는 클라이언트는 신뢰 저장소가 업데이트될 때까지 교체된 루트에서 발급된 인증서를 거부합니다.

사적 신탁은 의도적이다

임베디드 CA의 인증서는 공개 브라우저나 운영 체제에서 자동으로 신뢰되지 않습니다. 운영자가 내보낸 Webship 루트 인증서를 클라이언트의 신뢰 저장소에 설치한 후에야 신뢰됩니다.

그것은 임베디드 모드가 다음에 적합하다는 것을 의미합니다:

  • 디바이스 관리로 등록된 회사 관리 노트북 및 휴대폰;
  • 명시된 CA 번들을 사용한 내부 서비스 간 트래픽;
  • 개인용 가전 제품 및 제어되는 엣지 플릿;
  • 실제 TLS 동작을 수행해야 하는 개발 및 테스트 환경;
  • 공용 CA에 의존할 수 없는 단절된 네트워크.

관리되지 않는 브라우저를 사용하는 일반 대중 웹사이트에는 적합한 모드가 아닙니다. 정확한 공개 이름에는 공개 per_site 발급을 사용하고, 대규모 공개 하위 도메인 집합에는 fleet 발급을 사용하며, 의도된 레거시 다중 SAN 배포에는 shared만 사용하거나 이미 신뢰된 PKI에서 수동 파일을 사용하십시오.

루트 인증서만 클라이언트에게 배포하십시오. 루트 개인 키는 절대 배포하지 마십시오. 해당 키를 소유하면 모든 등록된 클라이언트가 신뢰하는 신원을 발급할 수 있는 권한을 갖게 됩니다.

공용 인증서와 사설 인증서는 공존할 수 있다

Webship 1.4.0은 동일한 리스너에서 인증서 전략을 혼합할 수 있습니다:

~~~톰엘 listen = "0.0.0.0:443"

[tls] unknown_sni = "거부"

[자동_tls] enabled = true directory_url = "https://acme-v02.api.letsencrypt.org/directory" cache_dir = "/var/lib/webship/acme" contacts = ["mailto:ops@example.com"] 서비스_약관_동의 = true

[acme_ca] state_dir = "/var/lib/webship/acme-ca" leaf_validity_days = 90

[[사이트]] 도메인 = "www.example.com" root = "/srv/public" certificate_mode = "사이트별"

[[사이트]] 도메인 = "control.internal.example" root = "/srv/control" certificate_mode = "embedded"

[[사이트]] 도메인 = "payments.example.com" root = "/srv/payments"

[사이트.tls] cert = "/etc/webship/payments-fullchain.pem" key = "/etc/webship/payments-private-key.pem" ~~~

여기서 www.example.com은 자체 공개 ACME 인증서를 받습니다. control.internal.example은 내장 CA에서 개인 인증서를 받습니다. payments.example.com은 명시적인 파일이 우선순위를 가지기 때문에 운영자의 외부 PKI 아래에 그대로 있습니다.

공용 ACME 디렉토리는 내장 사이트에서 무시됩니다. 내장 루트는 공용 사이트를 절대 서명하지 않습니다. 수동 사이트는 자동 워크플로우 중 어느 쪽에도 조용히 등록되지 않습니다.

H1, H2, H3 및 WebTransport용 단일 인증서 해결기

인증서 선택은 HTTP 요청이 존재하기 전에 TLS 핸드셰이크 동안 발생합니다. Webship는 ClientHello 서버 이름을 사용하여 사이트 ID를 선택한 다음 응용 프로그램 프로토콜을 협상합니다.

  • HTTP/1.1와 HTTP/2는 TCP 위에서 TLS를 사용합니다.
  • HTTP/3과 WebTransport는 UDP를 통한 QUIC 내에서 TLS를 사용합니다.
  • 하나의 유효한 사이트 아이덴티티가 모든 활성화된 프로토콜에 사용될 수 있습니다.
  • HTTP/3 또한 UDP 연결 가능성을 필요로 합니다; H1과 H2는 TCP 경로를 사용합니다.
  • Alt-Svc는 TCP 폴백을 유지하면서 H3을 광고할 수 있습니다.

TCP, TLS 및 QUIC는 동일한 사이트 인식 식별 모델을 사용합니다. 정확한 이름이 우선되며, 와일드카드 인증서가 구성된 경우 가장 긴 유효 와일드카드가 적용되고, 알 수 없는 이름의 SNI는 관련 없는 기본 인증서를 받는 대신 거부될 수 있습니다.

알 수 없는 호스트명이 실패해야 하는 경우 멀티 사이트 리스너에서 unknown_sni = "reject"를 사용하십시오. 프로덕션 배포 전에 인식된 이름, 인식되지 않은 이름 및 예상되는 SNI 없음 동작을 테스트하십시오.

임베디드 아이덴티티를 서비스 간격 없이 회전

Webship은 인증된 루프백 바인딩 MCP 서버를 통해 인증서 상태와 제어된 변이를 노출합니다:

  • webship.tls.get_status는 활성 인증서 해결자와 갱신 상태를 보고합니다.
  • webship.tls.reissue_certificate는 해당 사이트가 임베디드 모드를 사용할 때만 자동으로 관리되는 사이트를 즉시 재발급합니다.
  • webship.tls.reload은 일반적인 보호된 TLS 경로를 통해 인증서 상태를 다시 불러옵니다.
  • webship.acme_ca.status는 개인 CA가 선택되었는지, 그 상태 디렉터리, 인증서 유효 기간, 발급 수, 폐기 수 및 최근 도메인 샘플을 보고합니다.
  • webship.sites.apply는 고정된 구성 버전에 대해 사이트를 추가하거나 제거합니다.

임베디드 재발급의 경우, Webship는 교체품을 생성하고 검증한 후 서비스에 교체합니다. 새로운 인증이 준비될 때까지 현재 유효한 인증이 계속 서비스를 제공합니다. 교체품이 설치된 후에만 퇴역된 인증이 기록됩니다.

즉시 재발급 작업은 공개 per_site 인증서를 의도적으로 거부합니다. 공개 갱신은 개인 진행 중 서명과 혼동되지 않고 공개 ACME 수명 주기 내에서 유지되어야 합니다. 멀티 SAN 그룹을 변경하면 신원 경계가 재구성되므로 공유 모드 멤버십도 재시작 시 동결됩니다.

MCP는 권한이 부여된 제어 인터페이스입니다. 루프백 상태로 유지하고, TLS와 강력한 베어러 토큰을 요구하며, 원격 관리를 위해 인증된 터널을 사용하고, 모든 변경 사항을 감사하십시오.

중요한 실패 경계

보안 인증서 시스템은 올바른 방향으로 실패해야 한다.

  • 새로 구성된 임베디드 사이트는 발급이 보류 중인 동안 다른 사이트의 신원을 받지 못합니다.
  • 잘못된 교체 항목은 작동 중인 인증서 위에 설치되지 않습니다.
  • 명시적인 매뉴얼 파일은 해당 사이트의 자동 소유를 방지합니다.
  • 알 수 없는 이름의 SNI는 HTTP 라우팅 전에 거부될 수 있습니다.
  • 내장된 CA는 비공개로 유지되며 원격 등록 엔드포인트가 없습니다.
  • 공용 및 내장 신원은 자동 TLS 상태 내에서 별도의 캐시 경로를 사용합니다.

내장 CA가 초기화되지 않았다는 경고는 Webship가 구성된 상태 디렉터리를 활성화할 수 없음을 의미합니다. 영향을 받는 사이트로 트래픽을 보내기 전에 소유권, 권한, 지속성 또는 저장소 가용성을 수정하십시오. 다른 환경의 루트 키를 복사하여 오류를 우회하지 마십시오.

생산 체크리스트

임베디드 모드를 활성화하기 전에:

  1. 사이트를 신뢰해야 하는 모든 고객 집단을 식별하십시오.
  2. 루트 인증서를 내보내고 설치하기 위한 통제된 절차를 만드세요.
  3. 운영, 개발 및 테스트를 위해 별도의 루트 상태를 사용하십시오.
  4. 임베디드 CA 상태 디렉터리와 자동 TLS 캐시를 지속하고 보호하십시오.
  5. 필요한 키 자료에만 접근할 수 있는 전용 서비스 계정으로 Webship을 실행하십시오.
  6. 신뢰 경계가 명확해야 하는 모든 사이트에서 certificate_mode를 선택하십시오.
  7. 알 수 없는 SNI 정책을 설정하고 테스트하십시오.
  8. H1, H2, H3를 의도적으로 활성화하고 TCP 및 UDP 경로를 모두 확인하세요.
  9. 운영 환경 외에서 재발행, 재시작, 백업, 복원 및 클라이언트 신뢰 검증을 실행하십시오.
  10. 배포 전에 webship --check-config를 실행한 후, 실제 클라이언트에서 발급자, 이름, 유효성, 체인 및 협상된 프로토콜을 확인하십시오.

먼저 신뢰를 선택하고, 그다음에 자동화를 선택하세요

임베디드 CA는 개인 인프라를 위해 외부 인증서 서비스 의존성을 제거합니다. 이는 개인 루트를 전 세계적으로 신뢰되게 만들지 않으며, 운영자의 PKI 책임을 제거하지도 않습니다.

Webship는 키 생성, 서명, 검증, 설치, 교체 및 프로토콜 전반의 인증서 선택을 자동화합니다. 운영자는 여전히 루트 관리, 클라이언트 등록, 환경 분리, 백업, 복구 및 공개 신뢰 경로 또는 비공개 신뢰 경로 사용 여부에 대한 결정을 소유합니다.

그 분리는 특징입니다. 독립형 서버는 공개 CA인 척하지 않고도 사설 TLS를 자동화할 수 있으며, 공개 사이트는 여전히 동일한 과정에서 브라우저에서 신뢰하는 사이트별 또는 그룹 발급을 사용할 수 있습니다.

배포 전에 버전이 지정된 Webship 1.4.0 문서를 읽으세요. RFC 5280은 인증서 프로필과 검증을 정의하고, RFC 6066은 TLS 서버 이름 신호를 정의하며, RFC 8446은 TLS 1.3를 정의하고, RFC 8555는 공개 ACME를 정의하며, RFC 9525는 서비스 ID 검증을 정의합니다.