[네트워크] TLS Deep with WireShark: HTTPS는 어떻게 연결되나요

windowook·2025년 1월 24일
post-thumbnail

🌱 머릿말

개발한 앱을 배포하는 과정에서 HTTPS를 설정하며 SSL 인증서 발급과 도메인을 연결해보신 분들은 SSL/TLS 인증서라는 걸 들어보셨을 겁니다. 혹시 TLS(Transport Layer Security)는 무엇인지 궁금하지는 않으셨나요?

일단 저는 궁금했습니다. 그래서 좀 딥하게 공부를 해봤습니다.

정의
전송 계층 보안이라고 부르기도 하는 네트워크 보안 프로토콜입니다. 응용 계층과 전송 계층 사이에서 웹 애플리케이션과 서버 간의 커뮤니케이션을 암호화하기 위해 사용합니다. 웹 애플리케이션에만 국한되지 않고 이메일, 메세지, 화상 회의 앱도(VoIP) 암호화합니다.

대부분의 서비스는 HTTPS를 사용하기 때문에 TLS를 기본적으로 활용하고 있습니다. HTTPS를 사용하기 위해서는 TLS가 필수적입니다. 만약 TLS가 없다면, 즉 HTTP만 사용하는 웹 애플리케이션에서 로그인하거나 결제를 하는 과정의 네트워크 통신의 패킷이 스니핑 당하면, 계정의 비밀번호나 신용카드 정보 같은 민감한 개인 정보가 그대로 해커에게 노출될 수 있습니다.
(스니핑: 네트워크에서 전송되는 패킷을 캡쳐하여 내용을 엿보는 해킹 기법.)

실제로 HTTP만 사용하는 웹사이트를 방문하면, 크롬과 같은 브라우저에서는 경고 페이지가 표시되며 사용자가 신중하게 접근하도록 안내합니다. 이는 크롬, 파이어폭스, 엣지, 사파리 등 최신 브라우저들이 기본적으로 HTTPS 사용을 권장하며 보안을 중시하기 때문입니다. 우리가 개발한 앱을 배포할 때 TLS 인증서를 발급받아서 443포트로 연결하고 HTTPS를 필수적으로 설정해야 하는 이유도 여기에 있습니다.

이번 글에서는 웹을 사용하는 일상 속에서 필수적인 TLS의 기본 개념과, 오픈 소스 패킷 분석 프로그램인 와이어샤크를 이용한 TLS Handshake 과정을 분석합니다. 특히 현재 사용되고 있는 TLS 1.2와 TLS 1.3의 차이점도 함께 살펴보며 TLS의 보안이 어떻게 이루어지는지 깊이 이해하는 시간을 가져보겠습니다.

🌱 역사

TLS는 국제 표준 기구 IETF에 의해서 처음 제안되었고 1999년 발표되었습니다.
원래 TLS는 SSL(Security Socket Layer)의 발전된 후속 버전으로 만들어졌습니다.
명칭을 변경하게 된 이유가 SSL은 Netscape가 개발해왔지만 TLS는 IETF가 개발했으므로 구분을 위함이라고 합니다. 이후 2006년에 TLS 1.1, 2008년 TLS 1.2, 2018년에 TLS 1.3이 출시되어 현재는 1.2와 1.3만 사용되고 있습니다.

🌱 사용 조건

웹 사이트나 애플리케이션이 TLS를 사용하기 위해서는 TLS 인증서가 있어야 합니다. TLS 인증서를 SSL 인증서라고 부르기도 합니다. SSL은 대체된 이후로 사용되지 않지만 TLS가 없던 시절에는 SSL로 불렸던 프로토콜이니 같은 의미로 통용됩니다.

CA(Certification Authority, 인증 기관)에서 도메인을 소유한 사람 혹은 비즈니스에게 TLS 인증서를 발행합니다. 이 TLS 인증서에는 서버 공개키와 도메인 소유자 정보가 포함되어있습니다. TLS 인증서를 발급 받으면 서버에 설치하고, 웹 서버에서 443 포트를 활성화하여 TLS 인증서를 사용하는 HTTPS 통신을 할 수 있습니다.

🌱 TLS의 기능(이점)

Encryption 암호화

TLS 암호화는 데이터를 전송 중 스니핑되거나 도청되는 것을 방지합니다. 캡처된 패킷의 내용을 암호화된 문자로 변환하여 주고받기 때문에, 악의적인 해커가 스니핑을 시도해도 TLS 키가 없이는 암호화된 패킷을 해독할 수 없습니다. TLS에서 데이터 암호화는 Handshake 과정에서 생성된 세션 키를 사용하며 클라이언트와 서버만 공유합니다. 세션 티켓을 통해 세션을 재개하려고 하면 별도의 키 교환 없이도 동일한 세션 키를 사용할 수 있습니다. 1.2에서는 세션 ID도 같이 전송해야 합니다. 세션은 TLS Handshake로 연결된 컨텍스트를 의미합니다.

TLS 1.2에서는 하나의 세션 키를 저장하고 사용하기 때문에 과거 세션의 캡처된 패킷도 복호화할 수 있는 문제가 있었습니다. 이는 PFS(Perfect Forward Secrecy)를 제공하지 않는 심각한 약점입니다. PFS란, 프로토콜 통신으로 생성된 키가 노출되어도 이전 통신 내용이 보호되는 특성을 의미합니다. PFS는 별도의 챕터로 어떻게 작동하는지 원리를 설명하겠습니다.

반면, TLS 1.3에서는 이러한 보안 취약점을 개선하여, 각 세션마다 임시 키(일회성 키)를 생성하고, 세션이 종료되면 해당 키는 더 이상 유효하지 않으며 파기됩니다. 심지어 이전에 연결된 적 있던 세션을 재개할 경우에도 새로운 연결이 이루어질 때마다 새로운 키 교환 과정을 통해 새로운 세션 키가 생성됩니다. 이렇게 생성된 키는 클라이언트와 서버가 각자 세션 동안만 사용하며 세션이 종료되면 재사용되지 않습니다.

Integrity 무결성

데이터가 전송 중에 변조되지 않았음을 보장합니다.
메세지 인증 코드를 사용하여 데이터 변조 여부를 체크합니다.

Authentication 인증

클라이언트가 연결하려는 서버가 신뢰할 수 있는 대상임을 보장합니다.
디지털 인증서를 활용하여 서버 및 선택적으로 클라이언트를 보장합니다.

🌱 TLS Handshake 과정

암호화 통신을 위한 TLS Handshake 이전에 먼저 클라이언트와 서버 간의 TCP 3-Way Handshake로 신뢰성 있는 연결이 수립됩니다. 그 후 TLS Handshake가 시작되고, 인증 과정을 거쳐 데이터가 암호화 된 보안 연결이 설정됩니다.

1.2와 1.3, 두 버전의 패킷 캡쳐 이미지에서 버전 간 동일한 필드의 차이점을 부각하면서 Handshake를 살펴보겠습니다. 실제 패킷에 담기는 필드 값이 동일하면 굳이 설명하지 않겠습니다.

TLS 1.2 2-RTT

TLS 1.3 1-RTT

클라이언트 헬로 차이점

TLS 1.2

Version: 클라이언트가 지원하는 최대 TLS 버전이 표시됩니다.
Random: 클라이언트 랜덤입니다. 32바이트 길이로 세션 키 생성에 사용됩니다.
Session ID: 현재 세션 ID입니다. 세션 ID를 패킷에 담아서 보냅니다.
Cipher Suites: TLS에서 사용 가능한 암호화 제품군 목록이며 총 16개가 포함되어있습니다. 1.2에서는 키 교환 방식, 암호화 알고리즘, 해시 알고리즘을 조합한 형태로 제공됩니다. 클라이언트와 서버는 암호화 제품군 목록 중 하나를 선택하여 암호화에 사용합니다.
Compression Methods: 압축을 사용하지만 대부분 압축 방법엔 null만 포함됩니다.

Extension: server_name > Server Name Indication(SNI):
도메인 네임으로 IP 주소를 식별하는 SNI가 포함됩니다.
Extension: session_ticket: 세션 티켓이 포함됩니다.
EXtension: signature_algorithms: 인증서 서명에 필요한 해시 알고리즘입니다.

TLS 1.3

Version: 실제로는 1.3으로 고정되어있습니다. 하지만 와이어샤크 캡쳐에서 TLS 1.3의 실제 버전을 확인하기 위해서는 supported versions를 확인해야 합니다. 일반 Version에는 TLS 1.2라고 나와있습니다. 왜냐하면 TLS 1.3을 지원하지 않는 브라우저에서는 fallback 프로토콜로써 TLS 1.2가 자동으로 사용되도록 설정되어있기 때문입니다.
Session ID: 1.3에서는 포함되지 않습니다. 세션 티켓만 메세지에 포함됩니다.
Cipher Suites: 1.2와 달리 암호화 제품군의 키 교환 방식과 암호화 알고리즘, 해시 알고리즘이 분리되어있습니다. 키 교환은 Cipher Suite 외부의 Extension: key_share를 통해 이루어집니다. 암호화 알고리즘은 Extension: Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302), 해시 알고리즘은 Extension: signature_algorithms (len=30)으로 어떤 알고리즘이 사용되었는지 알 수 있습니다.
Compression Methods: 압축을 사용하지 않습니다. TLS 1.2에서는 CRIME 공격을 사용해서 특정 데이터를 삽입하여 압축한 뒤, 원래 데이터와 압축 비율의 변화를 관찰하는 과정을 반복하여 세션 쿠키나 인증 토큰을 추측하는 변태같은 공격을 한 사례가 있습니다.

Extension: supported versions: TLS 1.3과 1.2를 둘 다 지원합니다. 이 때는 1.3을 기본으로 사용하되 이를 지원하지 않는 브라우저에서는 1.2로 변경됩니다.
Extension: encrypted_client_hello: 1.3은 클라이언트 헬로부터 암호화되어있습니다.
Extension: key_share: 클라이언트와 서버 간 (EC)DHE 알고리즘과 관련된 공개 키를 교환합니다. 클라이언트가 자신의 Key Share를 ClientHello 메시지에 포함하여 보내면 서버가 추가 요청 없이 바로 Handshake를 진행할 수 있도록 합니다. 클라이언트와 서버는 서로의 공개 키를 사용하여 (EC)DHE 알고리즘으로 Shared Secret을 생성합니다.
Extension: psk_key_exchange_modes: TLS 1.3 버전에서는 PSK와 (EC)DHE 알고리즘만 지원합니다. PSK with (EC)DHE key는 PSK와 (EC)DHE 키 교환을 함께 사용하는 모드를 의미합니다. 1.2에서 사용했던 취약점이 발견된 암호화 알고리즘을 지원하지 않습니다. 대표적으로 CBCRSA가 있습니다. 둘 다 PFS(Perfect Forward Secrecy)를 제공하지 않아서 삭제되었습니다.

정리

버전TLS 1.2TLS 1.3
Handshake 메시지버전, 암호화 제품군, SNI...버전, 암호화 제품군, SNI, Key Share, Supported Version...
세션 ID 포함OX
암호화 제품군키 교환 방식, 암호화 알고리즘, 해시 알고리즘 조합분리
알고리즘RSA, CBC 포함RSA, CBC 제외
압축 사용OX

서버 헬로 차이점

TLS 1.2

하나의 패킷에 4개의 Handshake 메세지가 포함됩니다.

Server Hello: 선택한 버전, 선택한 암호화 제품군, 서버 랜덤 등이 포함됩니다.
Certificate: 서버가 전달하는 인증서입니다. 암호화 되어있습니다.
Server Key Exchange: 키 교환 데이터를 전달합니다.
Server Hello Done: 서버의 Handshake 단계 완료 알림.

TLS 1.3

ServerHello 이후에 별도의 Server Key Exchange나 Server Hello Done 메시지가 필요하지 않고 바로 암호화 스펙 변경과 함께 Finished됩니다. 키 교환에 (EC)DHE를 사용하고 RSA 기반 키 교환 제거되었으므로 1.2보다 보안이 강화되었습니다.

정리

버전TLS 1.2TLS 1.3
Handshake 메시지ServerHello, Certificate, Server Key Exchange, Server Hello Done단일 메시지로 축소
키 교환 방식RSA, DH(ECDH)Key Share
암호화 제품군협상 추가 메시지 필요ServerHello에서 완료
PFS 보장 여부선택적기본 제공
성능느림빠름

0-RTT 지원

TLS 1.3은 Handshake 프로세스가 1-RTT로 속도가 향상되었습니다. 더하여 연결한 적 있는 서버와 재연결 시 0-RTT를 지원합니다.

서버는 첫 번째 세션 중에 세션 티켓을 클라이언트로 전송했었죠? 세션 티켓은 클라이언트와 서버 간의 세션 정보를 암호화한 데이터로, 재연결 시 Shared Secret을 기반으로 PSK(Pre-Shared Key)를 생성하는 데 사용됩니다. 이전에 연결한 적이 있는 클라이언트와 서버는 첫 번째 세션에서 받은 세션 티켓으로부터 PSK를 도출합니다. 클라이언트는 재연결하는 서버에 첫 번째 세션에서 받은 세션 티켓을 클라이언트 헬로 메시지에 포함하여 전송합니다.

서버는 클라이언트가 전송한 세션 티켓을 기반으로 동일한 PSK를 생성하고, 이를 사용해 0-RTT 데이터를 즉시 처리하며 추가적인 지연 없이 바로 통신을 시작합니다. 클라이언트는 이 PSK로 0-RTT 데이터를 암호화하여 전송하며, 서버는 이를 검증한 후 처리합니다.

0-RTT는 성능이 중요한 환경에서 매우 유용하지만, Replay Attack에 취약할 수 있습니다.
(Replay Attack: 유효한 데이터 전송이 악의적으로 또는 사기적으로 반복되거나 지연되는 공격. 스푸핑의 일종으로 공격자가 해시를 가로채서 자신이 클라이언트의 정당한 액세스 권한을 가지려고 할 때 주로 사용함.)

0-RTT가 성능을 위해서 보안과 트레이드 오프를 한 거라 CDN(Content Delivery Network) 또는 API 서버와 같은 성능이 우선인 환경에서 이전 연결을 기반으로 빠르게 재연결하여 응답 속도를 향상시킬 목적으로 사용됩니다. 따라서 서버에서는 캐시 데이터 요청 같이 민감하지 않은 작업에만 사용하거나 세션 티켓의 TTL을 짧게 하는 등의 설정을 하는 것이 좋고, 민감한 데이터를 주고 받아야하는 상황이라면 정책 설정으로 0-RTT 요청을 거부하고 매번 1-RTT로 전환할 수 있습니다.

PFS 완전 순방향 비밀성

완전 순방향 비밀성이란 비밀키가 노출되더라도 그 후의 키 분배 과정에서 얻는 세션 키의 안전성에는 영향을 미칠 수 없어야 한다는 성질입니다.(출처: 한국정보통신기술협회, 정보통신용어사전)

TLS 1.3는 TLS 1.2에서 사용하던 취약한 알고리즘인 CBC와 RSA를 삭제했다고 했습니다. PFS를 제공하지 못 해서요. PFS는 그만큼 TLS 1.3의 핵심 기능 중 하나입니다. 위에서 상세하게 설명하지 않았던 CBC와 RSA 알고리즘의 개념을 살펴보면서 왜 PFS를 제공하지 못 하는지 봅시다.

CBC(Cipher Block Chaining)

암호화 블록 체이닝으로 대칭 암호화 모드 중 하나입니다. 데이터를 고정된 블록 크기로 분할하여 블록 단위로 데이터를 암호화합니다. 마지막 블록이 고정 크기에 맞지 않으면 패딩(padding)을 추가해 크기를 맞춥니다. 여기서 문제가 생깁니다. 패딩을 노린 Padding Oracle 공격으로 패딩 처리 중 발생하는 오류 메세지를 기반으로 공격자가 암호화된 메시지 중 일부를 변조해 서버로 전송합니다. 서버는 변조된 메시지를 복호화하고 패딩 검증을 수행합니다. 공격자가 서버로부터 "패딩이 올바르지 않다"는 응답을 받을 수 있다면, 이를 활용해 암호화된 데이터를 한 바이트씩 복호화할 수 있습니다. CBC 모드의 특성상, 이전 블록의 암호 텍스트를 XOR 연산하여 현재 블록의 평문을 복호화합니다. 따라서 공격자가 이전 블록의 암호화 된 텍스트를 조작하면 복호화 결과의 패딩 값을 컨트롤할 수 있습니다. 이를 반복하여 한 바이트씩 평문으로 복호화합니다.

RSA(Rivest-Shamir-Adleman)

공개 키 암호화 방식의 하나입니다. 비대칭 키 암호화를 사용하며 암호화에는 공개 키 복호화에는 비공개 키를 이용합니다. 이 방식의 치명적인 문제는 서버의 비공개 키가 유출되면 과거에 캡처한 모든 패킷 내용을 복호화할 수 있는 문제가 있습니다. 서버 헬로 이후에 2-RTT에서 클라이언트가 서버로 전송하는 메세지 내부의 암호화 된 Pre-Master Secret은 오직 비공개 키로 복호화할 수 있습니다. 만약에 공격자가 서버의 비공개 키를 손에 넣으면, 해당 키를 사용해 과거에 캡처한 모든 TLS Handshake 데이터를 복호화할 수 있습니다. 게다가 키의 크기가 커질 수록 내용을 복호화 하는 데에 O(n³)에 가까운 시간 복잡도를 가지는 문제도 있습니다.

그래서 TLS 1.3에서는 이 두 암호화 방법을 제외시켰습니다. 대신 PFS를 보장하기 위해서 클라이언트와 서버는 첫 번째 세션에서 받은 세션 티켓으로부터 PSK를 도출한다고 위에서 말했는데, 이를 위해 (EC)DHE가 사용됩니다.

(EC)DHE 타원 곡선 Diffie-Hellman 알고리즘

TLS 1.3에서 도입된 키 교환 알고리즘으로, 일시적인 키를 사용해 키 교환을 수행하므로 비공개 키가 유출되더라도 과거의 통신 내용을 복호화할 수 없게 만듭니다.

먼저 클라이언트와 서버는 각각 임의의 개인 키를 생성하고, 이를 기반으로 공개 키를 계산합니다. 공개 키는 Extensions: key_share를 통해 교환됩니다. 그 후 클라이언트와 서버는 상대방의 공개 키와 자신의 개인 키를 사용하여 동일한 Shared Secret을 계산합니다. 이 과정에서 (EC)DHE 알고리즘이 사용됩니다. (EC)DHE 알고리즘은 Shared Secret과 클라이언트 랜덤, 서버 랜덤을 조합한 대칭 키를 생성합니다. 이 대칭 키를 메시지 암호화에 사용합니다.

이 대칭 키는 임시 키로 사용되기 때문에 유출되어도 과거 데이터를 복호화 할 수는 없습니다.

정리

TLS 1.2의 세션 키는 동일한 서버-클라이언트 간의 모든 세션에서 사용합니다.
TLS 1.3의 각 세션은 고유한 임시 키(일회용)를 갖고 있어 동일한 세션에 재사용 + 세션 간 사용이 불가능합니다.

그래서 (EC)DHE를 사용하는 TLS 1.3의 PKS with (EC)DHE가 PFS를 보장할 수 있는 것이죠.


🌱 TLS 인증 체인

TLS 인증 체인은 서버 인증서부터 시작하여 루트 인증서까지 이어지는 신뢰 체계입니다. 클라이언트는 서버 헬로 메시지에서 제공된 인증서를 통해 인증 체인을 확인합니다. 이 과정에서 클라이언트는 인증 체인의 각 단계가 상위 인증서에 의해 유효하게 서명되었는지 검증하며, 최종적으로 루트 인증서를 신뢰할 수 있는지 판단합니다.

인증 체인을 검증한 후, 클라이언트는 Pre-Master Secret을 생성하여 서버로 전송합니다. 이후 클라이언트는 클라이언트 랜덤과 서버 랜덤을 조합해 Master Secret을 생성하며, 서버도 동일한 방식으로 동일한 Master Secret을 생성합니다. 이 Master Secret은 세션 키를 생성하는 데 사용되며, 이후 데이터 전송은 이 세션 키로 암호화됩니다.

인증서 3단계

  • 서버 인증서: 특정 도메인에 발급된 인증서입니다. 클라이언트가 접속한 서버가 신뢰할 수 있는지 검증하는 첫 단계입니다.
  • 중간 인증서(Intermediate Certificate): 서버 인증서와 루트 인증서 간의 연결 고리 역할을 합니다. 일반적으로 한 개 이상 포함되며, 체인의 신뢰성을 연결합니다.
  • 루트 인증서(Root Certificate): 신뢰할 수 있는 인증 기관(CA)에 의해 발급된 최상위 인증서입니다. 클라이언트 운영체제나 브라우저에서 저장된 신뢰할 수 있는 루트 인증서 저장소에 등록되어 있습니다.

TLS 1.2 서버 헬로 패킷의 Certificate Handshake로 들어가면 하위 필드에 issuersubject 확인이 가능합니다. issuer는 해당 인증서를 발급한 기관의 정보를 나타내고 있고, subject는 인증서의 소유자 정보를 나타냅니다. 일반적으로 서버 인증서와 중간 인증서는 issuer와 subject가 서로 다릅니다. 루트 인증서에서는 issuer와 subject가 동일합니다. 제가 캡처한 패킷에서는 자가 서명이 되어있으므로 루트 인증서라고 보시면 됩니다.

signature는 서명입니다. 이 서명을 검증하려면 상위 인증서의 공캐 키를 사용해야 합니다. sha256WithRSAEncryption은 SHA-256 해시 알고리즘과 RSA를 조합하여 서명을 생성하는 방식입니다.

validity는 유효기간입니다. 클라이언트는 현재 시간이 유효 기간 내에 포함되는지 확인합니다. 이 정보가 유효하지 않으면 클라이언트는 인증서를 신뢰하지 않습니다.

TLS 인증 체인이 중요한 이유

TLS 인증 체인은 각 단계에서 서명 검증과 유효성 확인을 통해 클라이언트에게 서버의 신뢰성을 증명하며, 악의적인 공격자로부터 사용자를 보호하는 역할을 합니다. 이 인증 체인 검증 과정은 TLS가 제공하는 궁극적인 목적인 보안과 직결됩니다.

예를 들어, 피싱 사이트가 특정 서비스를 모방하여 사용자 정보를 탈취하기 위해 가짜 인증서를 제시하더라도 클라이언트는 해당 인증서가 신뢰할 수 있는 CA에서 발급된 것인지 대조합니다. CA의 서명을 위조하는 것은 사실상 불가능하기 때문에 인증 체인이 가짜 인증서를 차단할 수 있습니다.

따라서 TLS는 인증 체인을 반드시 거치며, 이를 통해 신뢰성과 무결성을 검증합니다. 이 과정 덕분에 HTTPS 통신이 안전하게 유지되며 사용자는 데이터 전송 과정에서 도청이나 변조 걱정 없이 서비스를 이용할 수 있습니다.


단순히 'HTTP보다 HTTPS가 안전하다.'라는 개념만 머리에 넣고 있었는데, 이에 사용되는 보안 프로토콜인 TLS가 어떤 역할을 하기에 HTTPS가 안전한 네트워크 통신을 할 수 있는지 문득 궁금해졌습니다. 이번 기회에 이 원리에 대해서 제대로 알 수 있는 계기가 된 것 같습니다.

profile
안녕하세요

0개의 댓글