본문으로 건너뛰기
김신건의 로그

[Auth] mTLS (Mutual TLS): 양방향 인증서 인증

· 수정 · 📖 약 3분 · 989자/단어 #mtls #tls #security #service-mesh #backend
Service Mesh, mTLS, Mutual TLS, client certificate, client cert auth, service mesh mtls, SPIFFE/SPIRE

정의

mTLS (Mutual TLS)서버뿐 아니라 클라이언트도 TLS 인증서로 자기 신분 증명. 일반 TLS = 서버 인증만, mTLS = 양방향.

활용: 서비스 메시 (Istio, Linkerd), 기업 내부 API, 금융 / B2B 통합, IoT 기기.

TLS vs mTLS 흐름

sequenceDiagram
    autonumber
    participant C as Client
    participant S as Server

    rect rgb(220,240,220)
    Note over C,S: 일반 TLS
    C->>S: ClientHello
    S-->>C: ServerHello + Certificate
    C->>C: 서버 인증서 검증
    C-->>S: Finished
    end

    rect rgb(255,235,220)
    Note over C,S: mTLS
    C->>S: ClientHello
    S-->>C: ServerHello + Certificate<br/>+ CertificateRequest
    C->>S: ClientCertificate + Finished
    S->>S: 클라이언트 인증서 검증
    S-->>C: Finished
    end

인증서 발급 흐름

flowchart LR
    CA[Root CA] -->|sign| IntCA[Intermediate CA]
    IntCA -->|sign| ServerCert[Server Cert]
    IntCA -->|sign| ClientCert[Client Cert]
    Client -->|보유| ClientCert
    Server -->|보유| ServerCert

자세한 인증서 체인은 TLS 참고.

사용 시나리오

1. Service Mesh (Istio, Linkerd, Consul)

flowchart LR
    subgraph A[Service A]
        AApp[App]
        AProxy[Sidecar Envoy]
    end
    subgraph B[Service B]
        BProxy[Sidecar Envoy]
        BApp[App]
    end
    AApp -->|plain HTTP| AProxy
    AProxy -->|mTLS auto| BProxy
    BProxy -->|plain HTTP| BApp
  • 애플리케이션이 mTLS 를 신경 쓰지 않음. Sidecar 가 자동.
  • Zero Trust 네트워크의 토대.

2. SPIFFE/SPIRE: 워크로드 신원

SPIFFE ID = spiffe://example.com/ns/prod/sa/web

쿠버네티스 ServiceAccount → SVID (SPIFFE Verifiable Identity Document) → 짧은 mTLS 인증서.

IMPORTANT

수동 인증서 발급/배포 없이 SPIRE 가 자동 회전. 회전 주기는 시간 단위. 침해 시 영향 최소화.

3. 기업 VPN / Zero Trust

  • BeyondCorp 류 디바이스 인증 + 사용자 인증.
  • 기기 인증서 + 사용자 OIDC.

4. IoT / 디바이스

  • 수백만 디바이스 각자 인증서.
  • 제조 시점에 발급 (factory cert).

인증서 회전

gantt
    title 인증서 라이프사이클
    dateFormat YYYY-MM-DD
    section Cert
    유효기간 1: 2026-01-01, 90d
    유효기간 2 (회전):  active, 2026-03-15, 90d
    유효기간 3 (회전):  2026-06-01, 90d
회전 주기적합
1년legacy 시스템
90일Let’s Encrypt 표준
24시간짧은 SVID (SPIFFE)
1시간고보안 환경

짧을수록 침해 영향 최소화. 자동화 없으면 운영 불가.

OAuth + mTLS (RFC 8705)

OAuth 의 client_credentials 에서 client_secret 대신 client cert. 큰 기업 / 금융 API.

sequenceDiagram
    Service A->>Auth: POST /token<br/>(mTLS client cert)<br/>grant_type=client_credentials
    Auth->>Auth: cert 검증
    Auth-->>Service A: access_token (cnf claim 에 cert hash)
    Service A->>Service B: Bearer <token><br/>(mTLS, 같은 cert)
    Service B->>Service B: token 의 cnf == cert hash?
    Service B-->>Service A: 자원

흔한 함정

WARNING

  1. 인증서 만료 사고 = 자동화 없으면 언젠가는 만료 → 서비스 다운. 모니터링 + 자동 갱신 필수.
  2. 인증서 회전과 사용 동시 = 회전 직후 옛 인증서로 검증 실패. grace period 필요.
  3. CRL (Certificate Revocation List) 의 체크 누락 = 침해 인증서가 수개월 유효. 짧은 인증서 (SPIFFE) 가 현실적 답.
  4. mTLS 끝점에 L7 LB = TLS 종료 시점에 클라이언트 인증서 정보 손실. X-Forwarded-Client-Cert 같은 헤더로 전달 또는 passthrough LB.

인증서 형식

형식의미
.crt / .pembase64 인코딩 X.509 (텍스트)
.derbinary DER
.p7b / .p7cPKCS#7 (체인 포함)
.pfx / .p12PKCS#12 (인증서 + private key)
.keyprivate key 만

mTLS vs 대안 비교

방식강도복잡도주요 용도
mTLS최강 (인증서 기반)높음서비스 간 Zero Trust
API Key중간 (공유 비밀)낮음외부 API 파트너
JWT Bearer중간 (서명 검증)낮음유저 인증, OIDC
HMAC 서명중간 (요청 무결성)중간Webhook
IP Whitelist낮음 (위조 가능)낮음최후 수단

IMPORTANT

mTLS 는 인증서 유효 + 개인키 보유를 동시에 증명. API Key 는 탈취 시 즉시 재사용 가능. 고보안 서비스 간 통신에는 mTLS.

OCSP vs CRL vs 단기 인증서

인증서 폐지 확인 3가지 방법:

flowchart TD
    Verify["인증서 유효성 확인"]
    Verify --> CRL["CRL 다운로드<br/>전체 폐지 목록"]
    Verify --> OCSP["OCSP 단건 조회<br/>실시간 CA 확인"]
    Verify --> Short["단기 인증서<br/>만료로 자동 폐지"]
    CRL --> R1["큰 파일, 갱신 지연"]
    OCSP --> R2["실시간, CA 의존성"]
    Short --> R3["자동화 필수, 권장 방식"]
방식확인 방법단점
CRLCA 발행 폐지 목록 다운로드큰 파일, 갱신 주기 지연
OCSP실시간 CA 단건 조회CA 다운 시 검증 불가 (Fail-Open 위험)
OCSP Stapling서버가 미리 조회, 인증서에 첨부서버 설정 필요
단기 인증서짧은 유효기간 (SPIFFE)자동화 없으면 운영 불가

디버깅: openssl s_client

# 서버 인증서 확인
openssl s_client -connect example.com:443 -showcerts

# mTLS: 클라이언트 인증서 제시
openssl s_client \
  -connect api.example.com:443 \
  -cert client.crt \
  -key client.key \
  -CAfile ca.crt

# ALPN 협상 확인
openssl s_client -alpn h2 -connect example.com:443 2>&1 | grep ALPN

주요 확인 포인트:

  • Verify return code: 0 (ok) = 검증 성공
  • SSL-Session: 안의 Protocol 및 Cipher Suite
  • Peer certificate: 서버 인증서 Subject / Issuer
  • No client certificate CA names sent = 서버가 클라이언트 인증서 요구 안 함

Istio PeerAuthentication (mTLS in K8s)

flowchart LR
    subgraph SvcA["Service A Pod"]
        AppA[App]
        ProxyA["Envoy Proxy<br/>자동 mTLS"]
    end
    subgraph SvcB["Service B Pod"]
        ProxyB["Envoy Proxy<br/>자동 mTLS"]
        AppB[App]
    end
    AppA -->|"plain HTTP"| ProxyA
    ProxyA -->|"mTLS (SPIFFE)"| ProxyB
    ProxyB -->|"plain HTTP"| AppB
# PeerAuthentication: 네임스페이스 전체 STRICT mTLS 강제
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: production
spec:
  mtls:
    mode: STRICT
모드동작
PERMISSIVEmTLS + plain 혼용 (마이그레이션 중)
STRICTmTLS 강제 (권장 최종 상태)
DISABLEmTLS 비활성

TIP

PERMISSIVE 로 시작 → 모니터링으로 확인 → STRICT 로 전환. 한 번에 STRICT 하면 레거시 서비스 차단 위험.

구현 체크리스트

  • CA 인프라: 독립 Root CA, Intermediate CA 분리
  • 인증서 만료 모니터링: Datadog, Prometheus alert
  • 자동 갱신: SPIRE / cert-manager
  • grace period: 이전 인증서 30일 중복 신뢰
  • CRL 체크: OCSP Stapling 또는 단기 인증서
  • L7 LB 고려: passthrough 또는 X-Forwarded-Client-Cert
  • 폐기 절차: 침해 시 즉시 폐기 + 신규 발급 SLA

관련 위키

이 글의 용어 (3개)
[Auth] OAuth 2.0 / 2.1: Authorization Code + PKCEauth-security
정의 OAuth 2.0 (RFC 6749, 2012) 은 제3자 앱이 사용자 동의로 자원에 접근 하게 하는 권한 위임 프레임워크. 인증 (authentication) 이 아니라 …
[K8s] RBAC: Role, ClusterRole, ServiceAccount, RoleBindingkubernetes
정의 RBAC (Role-Based Access Control) = K8s 의 권한 부여 모델. 주체 + 권한 + 바인딩. 사용 시나리오 | 상황 | RBAC 역할 | |---|…
TLS / SSLnetwork
정의 TLS (Transport Layer Security) 는 (또는 위 ) 위에서 동작하는 암호화·인증 프로토콜이다. SSL 은 TLS 의 전신 (Netscape 1995, …

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기