도커로 구축한 랩에서 혼자 실습하며 배우는 네트워크 프로토콜 입문 #5-1 TLS
자손킴 @jasonkim@hackers.pub
L7 애플리케이션
전송 계층은 전송 제어를 하고 애플리케이션별로 패킷을 분류하는 것 까지만 담당한다. 애플리케이션 계층은 패킷을 애플리케이션으로 처리하고 애플리케이션과 사용자를 연결하는 계층이다.
OSI 7계층의 L5, L6을 다루지 않는 이유
OSI 7계층 모델에서는 세션 계층(L5)과 프레젠테이션 계층(L6)이 별도로 정의되어 있다. 세션 계층은 애플리케이션 간의 세션(연결) 설정, 관리, 종료를 담당하고, 프레젠테이션 계층은 데이터의 형식 변환, 암호화, 압축을 담당한다.
하지만 현대 인터넷의 근간인 TCP/IP 모델에서는 이 두 계층을 애플리케이션 계층과 분리하지 않는다. TCP/IP 모델은 OSI의 L5~L7을 하나의 애플리케이션 계층으로 통합하며 세션 관리나 데이터 표현 방식은 각 애플리케이션 프로토콜이 자체적으로 처리한다. 예를 들어 TCP는 이미 전송 계층에서 연결의 설정과 해제(3-way handshake, 4-way handshake)를 관리하고 TLS는 애플리케이션 프로토콜 수준에서 암호화와 데이터 무결성을 처리한다.
실제로 RFC 3439에는 "Layering considered harmful"이라는 섹션이 있을 정도로 엄격한 계층 분리보다는 실용적인 프로토콜 설계가 중시된다. 이러한 이유로 이 책에서도 L5, L6을 별도로 다루지 않고 애플리케이션 프로토콜로 통합하여 설명한다.
다양한 프로토콜
이 책에서는 HTTP, SSL/TLS, DNS, DHCP에 대해서 다룬다.
-
HTTP(Hypertext Transfer Protocol): 웹 브라우저와 웹 서버 간의 통신을 위한 프로토콜이다. 요청-응답 방식으로 동작하며, 웹 페이지, 이미지, API 데이터 등 다양한 리소스를 전송한다.
-
SSL/TLS(Secure Sockets Layer/Transport Layer Security): 네트워크 통신을 암호화하여 보안을 제공하는 프로토콜이다. HTTPS는 HTTP에 TLS를 결합한 것으로 웹에서 가장 널리 사용되는 보안 통신 방식이다.
-
DNS(Domain Name System): 도메인 이름(예: www.example.com)을 IP 주소로 변환하는 시스템이다. 사용자가 기억하기 쉬운 도메인 이름을 사용하여 웹사이트에 접속할 수 있게 해준다.
-
DHCP(Dynamic Host Configuration Protocol): 네트워크에 연결된 장치에게 IP 주소, 서브넷 마스크, 기본 게이트웨이, DNS 서버 등의 네트워크 설정을 자동으로 할당하는 프로토콜이다.
HTTP는 따로 정리하지 않을 것이고, TLS, DNS, DHCP에 대해서만 정리 할 것이다.
TLS
TLS(SSL)은 애플리케이션을 암호화하는 프로토콜이다.
SSL에서 TLS로의 전환
SSL은 1995년 Netscape가 웹 통신 보안을 위해 개발한 프로토콜이다. SSL 2.0이 최초로 공개되었지만 심각한 보안 취약점이 발견되어 1996년 SSL 3.0으로 대체되었다. 이후 IETF(Internet Engineering Task Force)가 SSL을 표준화하는 과정에서 프로토콜 이름이 TLS(Transport Layer Security)로 변경되었다. 1999년 TLS 1.0이 RFC 2246으로 발표되었는데 이는 SSL 3.0을 기반으로 하되 상호 운용성이 없을 정도로 충분한 차이가 있었다.
SSL 3.0은 2014년 POODLE(Padding Oracle On Downgraded Legacy Encryption) 공격 취약점이 발견된 후 2015년 공식적으로 폐기되었다. TLS 1.0과 1.1도 2020년 주요 브라우저들에 의해 지원이 중단되었고 2021년 RFC 8996을 통해 공식 폐기되었다.
현재는 TLS 1.2(2008년 출시)와 TLS 1.3(2018년 출시)이 사용되며 TLS 1.3이 권장된다.
책에서는 TLS 1.2와 RSA를 기반으로 설명하고 있지만 이 포스팅에서는 TLS 1.3과 Ed25519, X25519를 기반으로 정리 할 것이다.
TLS로 막을 수 있는 위협
TLS는 스푸핑, 변조, 도청이라는 세 가지 주요 보안 위협을 방지한다.
암호화로 도청 방지
도청은 통신 당사자가 아닌 제3자가 네트워크를 흐르는 데이터를 몰래 가로채 읽는 행위이다. 공공 와이파이에서 로그인 정보를 훔치거나 네트워크 패킷을 캡처하여 민감한 정보를 탈취하는 것이 대표적인 예다.
암호화는 정해진 규칙(암호화 알고리즘)에 따라 데이터를 변환하는 기술이다. TLS는 대칭키 암호화를 사용하여 통신 내용을 암호문으로 변환한다. 도청자가 암호화된 패킷을 가로채더라도 복호화 키 없이는 원본 데이터를 알 수 없다.
해싱으로 변조 방지
변조(Tampering)는 통신 중인 데이터를 제3자가 중간에서 가로채어 내용을 바꾸는 행위이다. 예를 들어 은행 송금 요청에서 수신자 계좌번호나 금액을 변경하는 중간자 공격(Man-in-the-Middle Attack)이 있다.
해싱은 불규칙한 길이의 데이터에서 정해진 계산(해싱 알고리즘)에 따라 고정된 길이의 데이터(해시값)를 생성하는 기술이다. TLS는 메시지 인증 코드(MAC)를 사용하여 각 메시지에 해시 기반 태그를 붙인다. 수신자는 받은 데이터로 동일한 해시를 계산하고 송신자가 보낸 MAC 태그와 비교한다. 만약 데이터가 조금이라도 변경되었다면 해시값이 완전히 달라지므로 변조를 즉시 탐지할 수 있다.
디지털 인증서로 스푸핑 방지
스푸핑(Spoofing)은 공격자가 다른 서버나 사용자로 위장하여 통신 상대방을 속이는 행위이다. 가짜 은행 웹사이트를 만들어 사용자의 로그인 정보를 탈취하는 피싱 공격이 대표적이다.
디지털 인증서는 인터넷에 있는 다른 단말에 "나는 진짜입니다!"라고 증명하는 파일이다. TLS는 신뢰할 수 있는 인증 기관(CA, Certificate Authority)이 발급한 디지털 인증서를 사용하여 서버의 신원을 검증한다. 클라이언트는 서버가 제시한 인증서가 신뢰할 수 있는 CA에 의해 서명되었는지 인증서의 도메인이 접속하려는 도메인과 일치하는지 확인한다. 이 검증을 통해 가짜 서버에 연결되는 것을 방지한다.
TLS를 지탱하는 기술
TLS는 암호화 알고리즘, 키 교환 알고리즘, 디지컬 서명 알고리즘, 메시지 인증 알고리즘 4가지 기술을 조합하여 사용한다.
암호화 알고리즘
암호화는 평문(원본 데이터)을 암호문(읽을 수 없는 형태)으로 변환하는 과정이며 복호화는 암호문을 다시 평문으로 되돌리는 과정이다. TLS에서 실제 데이터 암호화에는 대칭키(공통키) 암호화 방식을 사용한다.
대칭키 암호화는 암호화와 복호화에 동일한 키를 사용하는 방식이다. AES-GCM이나 ChaCha20-Poly1305 같은 알고리즘이 대표적이며 처리 속도가 빨라 대용량 데이터 암호화에 적합하다.
하지만 대칭키 암호화에는 근본적인 문제가 있다. 통신을 시작하기 전에 양측이 동일한 키를 가지고 있어야 하는데 이 키를 어떻게 안전하게 전달할 것인가? 키를 평문으로 네트워크에 전송하면 도청자에게 탈취당할 수 있다. 키가 탈취되면 해당 키로 암호화된 모든 통신 내용이 노출된다. 이것이 바로 '키 전달 문제'이며 이를 해결하기 위해 키 교환 알고리즘이 필요하다.
키 교환 알고리즘
공통키 암호 방식을 사용하면 키 전달시 보안 문제를 피할 수 없다. 키 교환 알고리즘은 도청자가 지켜보는 공개 채널을 통해서도 양측이 안전하게 공유 비밀(Shared Secret)을 생성할 수 있게 해주는 기술이다.
RSA의 문제점
이전에는 RSA 키 교환을 사용했다. 클라이언트가 무작위 비밀값을 생성하고 서버의 RSA 공개키로 암호화하여 전송하면 서버가 자신의 개인키로 복호화하는 방식이다. 하지만 이 방식에는 심각한 문제가 있다.
만약 공격자가 암호화된 통신을 모두 저장해두었다가, 나중에 서버의 RSA 개인키가 유출되면 과거의 모든 통신을 복호화할 수 있다. 이를 '전방 비밀성(Forward Secrecy)'이 없다고 한다.
X25519로의 전환
TLS 1.3에서는 RSA 키 교환이 완전히 제거되고, X25519(또는 ECDHE) 같은 임시(Ephemeral) Diffie-Hellman 키 교환만 사용한다. X25519는 Curve25519 타원 곡선을 기반으로 한 ECDH(Elliptic Curve Diffie-Hellman) 키 교환 함수로 Daniel J. Bernstein이 2006년에 설계했다.
X25519의 장점은 다음과 같다:
- 완전 순방향 비밀성(Perfect Forward Secrecy): 매 세션마다 새로운 임시 키 쌍을 생성하므로 서버의 인증서 개인키가 유출되어도 과거 세션의 통신 내용을 복호화할 수 없다.
- 높은 성능: 256비트 키로 128비트 보안 수준을 제공하면서도 기존 알고리즘보다 훨씬 빠르다.
- 구현 안전성: 타이밍 공격 등 부채널 공격에 강하도록 설계되었다.
X25519 키 교환 동작 원리
- 키 쌍 생성: 영희와 철수는 각각 32바이트의 무작위 개인키(a, b)를 생성한다.
- 공개키 계산: 각자 자신의 개인키와 타원 곡선의 기준점(G)을 곱하여 공개키를 계산한다. 영희의 공개키 = a × G, 철수의 공개키 = b × G
- 공개키 교환: 영희와 철수는 자신의 공개키를 상대방에게 전송한다. 이 공개키는 도청자가 볼 수 있어도 안전하다.
- 공유 비밀 계산: 영희는 자신의 개인키(a)와 철수의 공개키(b × G)를 곱하여 공유 비밀을 계산한다. 철수는 자신의 개인키(b)와 영희의 공개키(a × G)를 곱한다. 타원 곡선의 수학적 특성에 의해 a × (b × G) = b × (a × G)가 성립하므로, 양측은 동일한 공유 비밀을 얻는다.
- 세션 키 유도: 공유 비밀은 HKDF(HMAC-based Key Derivation Function)를 통해 실제 암호화에 사용할 세션 키로 변환된다.
도청자는 공개키(a × G, b × G)만 볼 수 있는데 여기서 개인키(a, b)를 알아내는 것은 타원 곡선 이산 로그 문제(ECDLP)를 푸는 것으로 현재 기술로는 계산적으로 불가능하다.
디지털 서명 알고리즘
앞서 언급했듯이 TLS는 디지털 인증서에 포함된 디지털 서명을 통해 상대방이 제3자가 신뢰 할 수있는 상대인지 여부를 판단한다.
RSA에서 Ed25519로
예전에는 RSA가 디지털 서명에 널리 사용되었지만 몇 가지 한계가 있다. 동등한 보안 수준을 위해 훨씬 큰 키 크기가 필요하고(RSA 3072비트 ≈ Ed25519 256비트) 서명 생성 속도가 상대적으로 느리며 구현 시 패딩 오라클 공격 등에 취약할 수 있다.
Ed25519는 이러한 문제를 해결한 현대적인 디지털 서명 알고리즘이다. Edwards 곡선 기반의 EdDSA(Edwards-curve Digital Signature Algorithm) 구현체로, Daniel J. Bernstein 팀이 설계했다. 2023년 FIPS 186-5에 공식 포함되어 미국 연방 정부 시스템에서도 승인된 서명 알고리즘이 되었다.
Ed25519의 특징
- 작은 키와 서명 크기: 공개키 32바이트, 서명 64바이트로 매우 컴팩트하다.
- 빠른 성능: 서명 생성이 RSA보다 약 33배 빠르다.
- 높은 보안성: 128비트 보안 수준을 제공하며, 부채널 공격에 강하도록 설계되었다.
- 결정적 서명: 난수 생성기에 의존하지 않아 구현 오류로 인한 개인키 노출 위험이 없다. (Sony PlayStation 3 펌웨어 서명키 유출 사건은 ECDSA의 잘못된 난수 사용으로 발생했다.)
디지털 서명 생성과 검증 과정
서명 생성 (서버/발급자 측):
- 서명할 메시지(예: 인증서 내용)를 준비한다.
- 개인키와 메시지를 사용하여 해시를 계산한다.
- 이 해시와 개인키를 타원 곡선 연산에 사용하여 서명값(R, s)을 생성한다.
- 서명을 메시지(인증서)에 첨부한다.
서명 검증 (클라이언트 측):
- 서버로부터 인증서와 서명을 받는다.
- 인증서에 포함된 공개키를 추출한다.
- 공개키, 메시지, 서명을 사용하여 타원 곡선 방정식을 검증한다.
- 방정식이 성립하면 서명이 유효하고, 인증서가 해당 개인키 소유자에 의해 서명되었음이 증명된다.
통신 상대방 인증:
- 클라이언트가 서버에 연결하면 서버는 자신의 디지털 인증서를 제시한다.
- 인증서에는 서버의 공개키와 CA(인증 기관)의 디지털 서명이 포함되어 있다.
- 클라이언트는 이미 신뢰하고 있는 CA의 공개키로 인증서의 서명을 검증한다.
- 검증이 성공하면 인증서에 있는 서버 공개키가 진짜 해당 서버의 것임이 보장된다.
메시지 인증 알고리즘
TLS에서 앞서 언급한 디지털 서명 알고리즘은 통신 상대방을 인증하는 것일 뿐 이후 주고받는 애플리케이션 데이터(메시지)를 인증하는 것은 아니다.
디지털 서명은 비대칭키 암호화를 사용하므로 연산 비용이 높다. 매 메시지마다 서명을 생성하고 검증하는 것은 성능상 비효율적이다. 따라서 TLS는 핸드셰이크 과정에서 합의한 대칭키를 사용하는 MAC(Message Authentication Code)으로 각 메시지의 무결성과 인증을 보장한다.
MAC이란?
MAC은 메시지와 공유 비밀키를 입력으로 받아 고정 길이의 인증 태그를 생성하는 알고리즘이다. 단순한 해시와 달리, 비밀키가 없으면 올바른 MAC 태그를 생성할 수 없다. 따라서 MAC은 메시지 무결성(변조 여부)과 메시지 인증(발신자 확인)을 동시에 제공한다.
TLS에서는 주로 HMAC(Hash-based MAC)을 사용한다. HMAC은 SHA-256 같은 해시 함수와 비밀키를 결합하여 MAC 태그를 생성한다. TLS 1.3에서는 AEAD(Authenticated Encryption with Associated Data) 모드인 AES-GCM이나 ChaCha20-Poly1305를 사용하는데, 이들은 암호화와 메시지 인증을 동시에 수행한다.
MAC으로 변조 검증하는 과정
- 송신자: 암호화된 메시지와 공유 비밀키를 MAC 알고리즘에 입력하여 MAC 태그를 생성한다.
- 전송: 암호화된 메시지와 MAC 태그를 함께 전송한다.
- 수신자: 받은 메시지와 동일한 공유 비밀키로 MAC을 직접 계산한다.
- 비교: 계산한 MAC과 받은 MAC 태그를 비교한다.
- 판정: 두 값이 일치하면 메시지가 변조되지 않았음이 보장된다. 일치하지 않으면 메시지가 전송 중에 변조되었거나 올바른 키를 가진 발신자가 보낸 것이 아니므로 메시지를 폐기한다.
이 과정에서 공격자가 메시지 내용을 조금이라도 바꾸면 해시값이 완전히 달라지므로 올바른 MAC 태그를 생성할 수 없다. 또한 공유 비밀키 없이는 위조된 메시지에 대한 유효한 MAC을 만들 수 없어 메시지의 출처도 검증된다.