SSL/TLS 핸드셰이크 심화 — 인증서 체인, SNI, ALPN
HTTPS의 S는 TLS입니다. 브라우저가 서버와 안전하게 통신하기 위해 수행하는 핸드셰이크 과정을 심화적으로 정리합니다.
TLS 1.3 핸드셰이크
TLS 1.3은 1-RTT 로 핸드셰이크를 완료합니다 (TLS 1.2는 2-RTT).
클라이언트 서버
│ │
│── ClientHello ──────────────────→│
│ (지원 암호, 키 교환 파라미터, │
│ SNI, ALPN) │
│ │
│←── ServerHello + Certificate ────│
│ + CertificateVerify │
│ + Finished │
│ │
│── Finished ─────────────────────→│
│ │
│←─── 암호화된 Application Data ──→│
TLS 1.2에서 제거된 것:
- RSA 키 교환 (Forward Secrecy 없음)
- 정적 DH
- CBC 모드 암호 (BEAST 공격 취약)
- 압축 (CRIME 공격 취약)
인증서 체인
Root CA (브라우저에 내장)
│ 서명
▼
Intermediate CA
│ 서명
▼
서버 인증서 (example.com)
검증 과정:
1. 서버가 인증서 + 중간 인증서 전송
2. 브라우저가 중간 인증서를 Root CA로 검증
3. Root CA가 신뢰 목록에 있는지 확인
4. 인증서의 도메인이 요청 도메인과 일치하는지
5. 인증서 만료 여부
6. 인증서 폐기(CRL/OCSP) 확인
SNI (Server Name Indication)
하나의 IP에 여러 도메인의 HTTPS를 호스팅할 때, 어떤 도메인의 인증서를 보낼지 알려주는 TLS 확장입니다.
ClientHello에 포함:
server_name: example.com
→ 서버가 example.com의 인증서를 선택하여 응답
SNI가 없던 시절에는 IP당 하나의 SSL 인증서만 가능했습니다.
주의: SNI는 평문으로 전송됨 → ESNI(Encrypted SNI) / ECH(Encrypted Client Hello) 로 개선
ALPN (Application-Layer Protocol Negotiation)
TLS 핸드셰이크 중에 상위 프로토콜(HTTP/1.1, h2, h3) 을 협상합니다.
ClientHello:
ALPN: ["h2", "http/1.1"]
ServerHello:
ALPN: "h2"
→ HTTP/2로 통신
0-RTT (TLS 1.3 Early Data)
이전 연결의 키를 재사용하여 핸드셰이크 없이 즉시 데이터 전송 합니다.
재연결 시:
클라이언트 → ClientHello + Early Data (0-RTT)
→ 첫 HTTP 요청이 핸드셰이크와 동시에!
주의: 재생 공격(Replay Attack) 가능 → GET 같은 멱등한 요청에만 사용
핵심 포인트
- TLS 1.3이 1.2보다 빠른 이유: 1-RTT 핸드셰이크, 불필요한 암호 제거
- Forward Secrecy: 서버 비밀키가 유출되어도 과거 통신은 복호화 불가 (ECDHE 사용)
- 인증서 체인 검증 실패 시: 브라우저에서 "이 연결은 안전하지 않습니다" 경고
정리
TLS 1.3은 보안과 성능을 모두 개선한 현대 암호화 프로토콜입니다. SNI로 가상 호스팅을 지원하고, ALPN으로 프로토콜을 협상하며, 0-RTT로 재연결 속도를 극대화합니다.