개발을 하다 보면 클라이언트와 서버의 환경이 달라 TLS(Transport Layer Security) 버전이 맞지 않을까 걱정될 때가 있습니다. 특히 상호 인증을 통해 더욱 강력한 보안을 구축하는 mTLS(Mutual TLS) 환경에서, 이 작은 버전 차이가 통신 전체를 실패하게 만들까 봐 불안해지기도 하죠.
과연 클라이언트와 서버가 선호하는 TLS 버전이 다르면 mTLS 통신은 불가능할까요?

✅ 결론부터 말하면, 괜찮습니다! (단, 조건이 있어요)
클라이언트와 서버가 서로 다른 버전의 TLS를 선호하더라도, 둘 사이에 공통으로 지원하는 TLS 버전이 하나라도 있다면 문제없이 통신할 수 있습니다. 시스템은 자동으로 그 공통 버전을 찾아내 통신을 시작하고, 그 기반 위에서 mTLS 인증을 수행하게 됩니다.
🤝 마법의 과정, TLS 버전 협상 (Version Negotiation)
이것이 어떻게 가능한지 이해하려면, 모든 TLS 통신의 첫 관문인 'TLS 핸드셰이크(Handshake)' 과정을 알아야 합니다. 이 과정에서 클라이언트와 서버는 마치 첫 만남에서 인사를 나누듯, 어떤 암호화 방식과 '언어(TLS 버전)'로 대화할지 결정합니다. 이것을 '버전 협상(Version Negotiation)'이라고 부릅니다.
전체적인 흐름은 다음과 같습니다.
- 🙋♂️ ClientHello: 클라이언트의 자기소개 클라이언트가 서버에 접속하면서 "안녕하세요! 저는 이런 기술들을 쓸 수 있어요."라고 말하는 단계입니다. 이때 자신이 지원하는 TLS 버전 목록을 선호하는 높은 버전부터 차례대로 서버에 전달합니다.
- 클라이언트 ➡️ 서버: "저는 TLS 1.3과 TLS 1.2를 지원합니다. 가능하면 최신 버전인 1.3으로 통신하고 싶어요!"
- 🙋♀️ ServerHello: 서버의 응답과 결정 서버는 클라이언트가 보낸 목록을 보고, 자신이 지원하는 버전 목록과 비교합니다. 그리고 둘 모두가 지원하는 버전 중 가장 높은 버전을 선택하여 "좋아요! 우리 그 버전으로 대화합시다."라고 응답합니다.
- 서버 ➡️ 클라이언트: "반갑습니다. 저는 TLS 1.2와 TLS 1.1을 지원하네요. 우리 둘 다 쓸 수 있는 가장 좋은 버전은 TLS 1.2이니, 이걸로 통신을 시작하죠!"
- 🤝 통신 시작 이렇게 협상된 TLS 1.2 버전을 기반으로 암호화 통신 채널이 생성됩니다. mTLS에 필요한 클라이언트와 서버 간의 인증서 교환 및 검증 절차는 바로 이 채널 위에서 안전하게 진행됩니다.
💡 mTLS는 언제 등장할까?
mTLS는 독립적인 프로토콜이 아니라, TLS 프로토콜 위에서 동작하는 '인증 강화 옵션'입니다. 따라서, 가장 먼저 기본적인 TLS 핸드셰이크(버전 협상 포함)가 성공적으로 완료되어야만 mTLS 인증 절차를 시작할 수 있습니다. 버전 협상이 mTLS보다 항상 먼저 일어나는 이유입니다.
🎬 실전 예시로 완벽 이해하기!
✅ 통신 성공 시나리오
- 클라이언트 지원 버전: TLS 1.3, TLS 1.2
- 서버 지원 버전: TLS 1.2, TLS 1.1
- 협상 결과:
- 클라이언트는 [TLS 1.3, TLS 1.2] 목록을 서버에 보냅니다.
- 서버는 자신의 목록 [TLS 1.2, TLS 1.1]과 비교합니다.
- 공통으로 지원하는 버전은 TLS 1.2입니다.
- 최종적으로 **TLS 1.2**로 통신이 결정되고, 이후 mTLS 인증이 정상적으로 수행됩니다. 🎉
❌ 통신 실패 시나리오
- 클라이언트 지원 버전: TLS 1.3 (오직 1.3만 지원)
- 서버 지원 버전: TLS 1.2 (오직 1.2만 지원)
- 협상 결과:
- 클라이언트는 [TLS 1.3] 목록을 서버에 보냅니다.
- 서버는 자신의 목록 [TLS 1.2]과 비교합니다.
- 공통으로 지원하는 버전이 하나도 없습니다.
- 결국 TLS 핸드셰이크가 실패하고 연결이 중단됩니다. mTLS 인증은 시도조차 할 수 없습니다. 😥
👨💻 실제 데이터 엿보기: Wireshark로 본 핸드셰이크
실제 네트워크 패킷에서는 이 과정이 어떻게 보일까요? Wireshark와 같은 도구로 캡처한 TLS 핸드셰이크 데이터는 다음과 같습니다.
1. ClientHello 패킷
클라이언트가 자신이 지원하는 버전 목록(supported_versions)을 보내는 것을 볼 수 있습니다.
Transport Layer Security
TLSv1.3 Record Layer: Handshake Protocol: Client Hello
Handshake Protocol: Client Hello
Version: TLS 1.2 (0x0303)
Extension: supported_versions (len=5)
Supported Versions Length: 4
Supported Version: TLS 1.3 (0x0304)
Supported Version: TLS 1.2 (0x0303)
ℹ️ 위 데이터에서 클라이언트는 TLS 1.3과 1.2를 지원한다고 알리고 있습니다.
2. ServerHello 패킷
서버는 클라이언트의 목록을 보고 자신이 선택한 단 하나의 버전을 응답합니다.
Transport Layer Security
TLSv1.3 Record Layer: Handshake Protocol: Server Hello
Handshake Protocol: Server Hello
Version: TLS 1.2 (0x0303)
Extension: supported_versions (len=2)
Supported Version: TLS 1.2 (0x0303)
ℹ️ 서버는 클라이언트가 보낸 목록과 자신의 능력을 고려하여 최종적으로 TLS 1.2를 선택했음을 명확히 알려줍니다.
✨ 핵심 정리: 이것만 기억하세요!
복잡해 보이지만 핵심은 간단합니다.
클라이언트와 서버가 mTLS 통신을 할 때, 각자가 선호하는 TLS 버전이 다른 것은 전혀 문제가 되지 않습니다. 가장 중요한 것은 양측이 공통으로 지원하는 TLS 버전이 단 하나라도 존재하는가 입니다.
만약 공통 버전이 있다면, 시스템은 알아서 최적의 버전으로 협상하여 안전한 통신을 시작할 것입니다. 이제 버전 차이에 대한 막연한 불안감은 떨쳐버리고, 시스템의 똑똑한 '협상' 능력을 믿어보세요!
'일반IT > IT보안' 카테고리의 다른 글
| [Windows Security] 윈도우 일반 유저(Domain User)의 권한, 정말 '아무것도' 못할까? (Default Deny의 오해와 진실) (0) | 2025.11.23 |
|---|---|
| 수천 개 에이전트, 더 이상 SSH로 접속하지 마세요! 🤫 (OpAMP 완전 정복) (0) | 2025.11.12 |
| [IT 상식] PCI DSS? GDPR? 헷갈리는 보안 인증, 5분 만에 완벽 정리! 💳 (1) | 2025.10.08 |
| 다운로드 파일, 정말 믿어도 될까요? GPG 서명으로 안전하게 검증하기 🛡️ (0) | 2025.10.07 |
| 🛡️ Express.js 서버, CSRF 공격으로부터 안전하게 지키는 방법 (코드 분석) (0) | 2025.10.05 |