Published on

HTTP와 TCP/IP, HTTPS

Authors
  • avatar
    Name
    Hoehyeon Jung
    Twitter

Intro

개발을 진행하다보면 항상 사용하기 때문에 간과하기 쉬운 네트워크에 대해 다시 한번 알아보고자 합니다. 이를 가장 일반적인 상황으로부터 네트워크에 대해 설명하고자 합니다.

Situation

브라우저에 URL을 입력하면 어떤 일이 일어날까?

  1. 사용자는 브라우저에 URL을 입력합니다.
  2. 브라우저는 해당 URL을 DNS 서버에 요청합니다.
  3. DNS 서버는 해당 URL에 대한 IP 주소를 응답합니다.
  4. 브라우저는 해당 IP 주소로 HTTP 요청을 보냅니다.

각 과정에 대해 상세하게 살펴보면 아래와 같습니다.

1. 사용자는 브라우저에 URL을 입력합니다.

사용자가 브라우저에 URL을 입력하면 브라우저는 해당 URL을 해석하게 됩니다. 기본적으로 서버는 특정 공인 IP 상에서 운영되고 있고, 이를 통해 서버에 접근할 수 있습니다. 하지만 이러한 무작위적인 숫자들은 IP는 사용자들이 외우기 어렵기 때문에 의미있는 문자인 도메인을 사용하게 됩니다. 이러한 도메인을 IP로 변환해주는 역할을 하는 것이 DNS 서버입니다.

2. 브라우저는 해당 URL을 DNS 서버에 요청합니다.

DNS 서버는 해당 URL에 대한 IP 주소를 제공하는 역할을 가지고 있습니다. 이를 위해 https://gonewbie.github.io/blog/http-tcp-and-tls/ URL을 분리하면 아래와 같이 이루어져 있습니다.

  • 통신 규약(Protocol)

흔히 URL 앞에 https:// 혹은 http:// 로 시작되는 도메인이 많다. 이러한 부분을 통신 규약으로 주어지며 브라우저는 이를 해석하여 해당 규약에 맞는 방식으로 서버에 요청을 보냅니다. 일반적으로 HTTPS는 443 포트, HTTP는 80 포트를 사용합니다.

  • 도메인(Domain)

일반적인 서버 고유의 이름에 대응되는 부분이 gonewbie.github.io 입니다. 이러한 도메인을 통해 서버에 접근할 수 있습니다.

  • 경로(Path)

도메인 이후에 오는 /blog 부분입니다. 서버에서 정적/동적 자원 제공을 위한 경로 해당 경로를 지정하여 서버 자원을 관리합니다.

  • 자원(Resource)

경로 이후에 오는 /http-tcp-and-tls 부분입니다. 해당 자원을 통해 서버의 특정 자원에 접근할 수 있습니다.

이 중에서 도메인 부분을 DNS 서버에 전달하게 됩니다.

3. DNS 서버는 해당 URL에 대한 IP 주소를 응답합니다.

DNS 서버에 접근하고 IP 주소를 가져오는 것은 복잡하기도 하고 상당한 시간을 소요하기 때문에 기본적으로 캐싱을 통해 이를 해결합니다. 이를 위해 브라우저는 먼저 자신의 캐시를 확인하고, 없을 경우 운영 체제, 라우터 로컬 캐시, 인터넷 서비스 제공업체(ISP)의 DNS 재귀 확인자(recursive resolver)에 요청을 보내게 됩니다. 만일 ISP의 DNS 재귀 확인자 여기에 저장되지 않았다면 루트 DNS 서버에 요청을 보내게 됩니다.

DNS Query DNS 조회 (이미지 출처: https://www.cloudflare.com/img/learning/dns/dns-server-types)

모든 DNS 재귀 확인자에 알려져 있는 루트 DNS 서버는 gonewbie.github.io 도메인의 .io 도메인 TLD(Top Level Domain) 서버에 요청을 보내게 됩니다. TLD 서버는 해당 도메인의 권한있는 네임 서버(authoritative nameserver)를 알려주게 되고, 이를 통해 해당 도메인의 네임 서버에 요청을 보내게 됩니다. 권한있는 네임 서버는 해당 도메인의 IP 주소를 DNS A 레코드(IPv4)에서 조회하여 알려주게 됩니다.

4. 브라우저는 해당 IP 주소로 HTTP 요청을 보냅니다.

이제 브라우저는 해당 도메인을 가진 서버의 IP를 알게 되었습니다. 이를 통해 서버에 HTTP 요청을 보내게 됩니다. 이를 위해 브라우저는 해당 IP 주소로 TCP 연결을 시도하게 됩니다. 일반적으로 모든 요청에 대해 서버와 직접 통신하는 것은 지리상 효율적이지 않습니다. 따라서 정적인 파일 등은 CDN 등의 서비스를 통해 사용자와 지리적으로 가까운 위치에서 문서들을 빠르게 제공합니다. 이후 IP 주소로 해당 서버와 직접 혹은 로드 밸런서를 경유하여 서버에 연결됩니다.

Deep dive

각 키워드 별로 더 자세히 살펴보겠습니다.

HTTP 버전별 특징

HTTP의 경우 기본적으로 TCP/IP를 사용합니다. TCP는 연결 지향적이기 때문에 연결을 위한 3-way handshake, 연결 종료를 위한 4-way handshake를 통해 연결을 맺게 됩니다. 또한, HTTP 버전에 따라 연결을 유지하는 방식이 다릅니다. HTTP 1.0의 경우 연결을 유지하지 않지만, HTTP/1.1의 경우 기본적으로 연결을 유지하게 됩니다. 이를 통해 요청을 보낼 때마다 연결을 맺고 끊는 것이 아니라 연결을 유지한 상태에서 요청을 보내게 됩니다. 또한 데이터를 Pipelining 하여 여러 개의 데이터를 보내게 됩니다. 다만 Pipelining 된 데이터는 반드시 순차적으로 수신 받아야 됐기 때문에 Head of Line Blocking이 발생하게 됩니다.

http2HTTP/2 변경점

여기에 HTTP/2가 되면서, Header를 압축하여 전송하고, HTTP/1.1의 한계 순차적으로 데이터를 전송해야 하는 문제를 해결 frame의 interleaving을 통해 Head of Line Blocking을 개선하였습니다. Stream 단위로 데이터를 전송하게 되어, 여러 개의 데이터를 동시에 전송할 수 있게 되었습니다. 또한 HTTP/1.1에서 리소스 인라인화로 무거운 리소스를 HTTP/2에서는 서버 푸시를 통해 비동기적으로 전송할 수 있게 되었습니다.

특징HTTP/1.0HTTP/1.1HTTP/2
연결비연결형연결형(keep-alive)연결형
헤더 압축XXO
동시 전송XPipeliningStream
서버 푸시XXO
프로토콜TCPTCPTCP

HTTP/3

HTTP/3는 이전의 TCP 기반과는 달리 UDP를 기반으로 하는 QUIC(Quick UDP Internet Connections) 프로토콜을 사용합니다. QUIC는 UDP 기반으로 TCP의 기능을 대체하고, TLS 1.3 기반으로 암호화를 제공합니다. 이를 통해 TCP의 3-way handshake, 4-way handshake를 대체하고, TLS의 handshake를 줄여 더 빠른 연결을 제공합니다. 또한, Zero RTT를 통해 최초 연결 시간을 줄여 더 빠른 연결을 제공합니다. UDP 기반 위에 흐름 제어를 통해 관리하는 만큼, TCP 프로토콜의 한계인 순서 보장으로 인한 Head of Line Blocking가 완전히 해결 되었습니다. 또한, 기존 IP 기반의 TCP/IP 통신이 아닌 QUIC의 경우 IP가 변경되더라도 동일한 클라이언트일 경우 끊김 없이 데이터를 전송할 수 있습니다.

TCP/IP

TCP/IP는 인터넷 프로토콜 스택으로, 전송계층의 TCP와 네트워크 계층의 IP를 합친 용어입니다. 원래 OSI 7계층에서는 전송 계층과 네트워크 계층이 분리되어 있지만, TCP/IP는 이를 합쳐서 사용합니다. TCP/IP는 5계층으로 이루어져 있으며 통신 프롵토콜 보급이 TCP/IP를 기준으로 되어 있어 사실상 TCP/IP의 흐름을 따르게 됩니다.

LayerOSI 7 LayerTCP/IP 5 Layer
(Updated)
Protocol
Application7. Application5. ApplicationHTTP, FTP, SMTP, DNS
Presentation6. Presentation--
Session5. Session-(TLS)
Transport4. Transport4. TransportTCP, UDP
Network3. Network3. NetworkIP
Data Link2. Data Link2. Data LinkEthernet
Physical1. Physical1. Physical-

HTTPS 보안 연결

HTTPS의 경우 기본적인 HTTP와 다르게 TLS를 통해 암호화된 연결을 맺게 됩니다. TLS는 기본적으로 공개키 암호화 방식을 사용합니다. 이를 통해 서버는 공개키를 통해 암호화된 데이터를 받을 수 있고, 클라이언트는 개인키를 통해 데이터를 복호화할 수 있습니다. HTTP 통신 전에 TLS handshake를 통해 보안 연결을 구축한 후 통신을 하게 됩니다.

~TLS v1.2

아래는 TLS v1.2를 기준으로 TLS handshake 과정을 나타낸 것입니다.

TLS handshake
TLS handshake 과정
  1. Client Hello

우선 클라이언트(브라우저)는 자신의 TLS 버전, 지원 가능한 Cipher Suite 리스트, Session ID(최초 연결시 0), 랜덤 난수, SNI(Server Name Indication)을 서버에 전달합니다. 이 과정에서 SNI는 평문으로 전송되기 때문에 TLS 표준을 확장하여 ESNI(Encrypted SNI)를 통해 암호화된 SNI를 전송할 수 있도록 하거나 ECH(Encrypted Client Hello)를 통해 전체 Client Hello를 암호화하여 전송할 수 있도록 합니다.

  1. Server Hello

서버는 응답으로 서버의 TLS 버전, 사용할 Cipher Suite, 서버 생성 난수, Session ID를 전송합니다.

  1. Server Certificate

서버는 추가적으로 자신의 인증서를 클라이언트에게 보내게 됩니다. 클라이언트는 이 때 받은 인증서를 OS 및 브라우저의 CA(인증 기관)의 공개키로 복호화하여 인증서를 검증하게 됩니다.

  1. Server Hellow Done

서버는 클라이언트에게 Server Hello Done 메시지를 전송합니다.

  1. Client Key Exchange

사전에 서버와 협의된 Cipher Suite를 기반으로 클라이언트는 pre-master-secret을 생성하여 서버의 공개키로 암호화하여 전달합니다.

  1. Key generation

서버는 클라이언트로부터 전달받은 암호화된 pre-master-secret을 서버의 개인키로 복호화하여 pre-master-secret을 알아냅니다. 이로서 서버와 클라이언트는 대칭된 pre-master-secret키를 공유하게 됩니다. 이를 최종적으로 각 TLS 버전에 맞는 PRF(PseudoRandom Function)을 통해 48 bit의 master-secret을 생성합니다.

  1. Change Cipher Spec

최종적으로 지정된 알고리즘과 키로 클라이언트와 서버가 통신을 진행합니다.

  1. Finished

TLS Handshake 과정이 완료되고 서버와 클라이언트는 이후 암호화된 통신으로 데이터를 전달하게 됩니다.

PFS(Perfect Forward secrecy)

RSA로 암호화할 경우 Server의 private key가 유출될 경우 이전에 나눈 Client-Server간의 통신이 복호화되어 해당 private key를 가진 제 3자가 볼 수 있게 됩니다. 이를 방지하기 위해 Diffie-Hellman(DH) 알고리즘에 Forward Secrecy(암호화 키가 노출되어도 이전 통신이 노출되지 않음)가 추가된 DHE(Diffie-Hellman Ephemeral)를 사용하면 통신 정보가 안전하게 보호됩니다. 여기에 ECC(Elliptic curves cryptography)를 사용하면 같은 수준의 암호화를 제공하는 알고리즘 중 key 값이 더 작아 더 빠른 속도로 암호화 가능하게 됩니다.

TLS v1.3

TLS 1.3 handshake
TLS 1.3 handshake 과정

TLS 1.2 버전에는 TCP Handshake + TLS Handshake 과정이 존재하여 Full handshake 진행 시 총 3RTT(Round Trip Time)가 소요됩니다. TLS 1.3 버전에서는 Client(Server) Hellow와 Client(Server) Key Exchange 기능이 통합되어 TLS 연결에 필요한 Round Trip 시간이 줄어들게 됩니다.

또한, 보안적으로 취약한 알고리즘들이 제거되어 Cipher Suite가 좀 더 안전한 것들만 지원하도록 축소되었습니다.

참고

브라우저 - DNS 흐름

DNS 설명

HTTP/1.1과 HTTP/2 비교

TLS 인증서 발급 및 검증

TLS Handshake 과정

TLS 버전 별 차이

TLS 암호화 상세 과정