[Auth] mTLS (Mutual TLS): 양방향 인증서 인증
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
- 인증서 만료 사고 = 자동화 없으면 언젠가는 만료 → 서비스 다운. 모니터링 + 자동 갱신 필수.
- 인증서 회전과 사용 동시 = 회전 직후 옛 인증서로 검증 실패. grace period 필요.
- CRL (Certificate Revocation List) 의 체크 누락 = 침해 인증서가 수개월 유효. 짧은 인증서 (SPIFFE) 가 현실적 답.
- mTLS 끝점에 L7 LB = TLS 종료 시점에 클라이언트 인증서 정보 손실.
X-Forwarded-Client-Cert같은 헤더로 전달 또는 passthrough LB.
인증서 형식
| 형식 | 의미 |
|---|---|
.crt / .pem | base64 인코딩 X.509 (텍스트) |
.der | binary DER |
.p7b / .p7c | PKCS#7 (체인 포함) |
.pfx / .p12 | PKCS#12 (인증서 + private key) |
.key | private 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["자동화 필수, 권장 방식"]
| 방식 | 확인 방법 | 단점 |
|---|---|---|
| CRL | CA 발행 폐지 목록 다운로드 | 큰 파일, 갱신 주기 지연 |
| 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 SuitePeer certificate:서버 인증서 Subject / IssuerNo 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
| 모드 | 동작 |
|---|---|
PERMISSIVE | mTLS + plain 혼용 (마이그레이션 중) |
STRICT | mTLS 강제 (권장 최종 상태) |
DISABLE | mTLS 비활성 |
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
관련 위키
- TLS
- OAuth2
- Service Mesh (Istio, Linkerd)
- Kubernetes RBAC
이 글의 용어 (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, …
이 개념을 다룬 위키 페이지 (6)
- wiki[Auth] OAuth 2.0 / 2.1: Authorization Code + PKCE
- wiki[Concurrency] Circuit Breaker: cascade failure 방어
- wiki[Pattern] API Gateway: BFF, 라우팅, auth, rate limit
- wiki[Pattern] Microservices vs Monolith: 언제 분리, 언제 통합
- wiki[K8s] NetworkPolicy: pod 간 네트워크 차단
- wiki[K8s] RBAC: Role, ClusterRole, ServiceAccount, RoleBinding
💬 댓글