2022.08.08 - [분류 전체보기] - [네트워크] "www.google.com"을 입력하면 어떻게 되나? 2편 DNS
[네트워크] "www.google.com"을 입력하면 어떻게 되나? 2편 DNS
2022.08.04 - [풀스택 개발자/Network] - [네트워크] 네트워크 흐름 - 주소창에 "www.google.com"을 입력하면 어떻게 되나? 1편 [네트워크] "www.google.com"을 입력하면 어떻게 되나? 1편 - LAN/WAN, TCP/IP 4 계..
daydayplus.tistory.com
지난 시간에는 주소창에 'www.google.com'을 입력했을 때, DNS 프로토콜을 이용하여 IP 주소를 얻어오는 것까지 알아보았습니다.
TCP 소켓 연결
IP를 얻어오고 난 다음에는 이 주소를 통해 구글의 서버에 찾아가 구글 서버의 *프로세스와 내 브라우저의 프로세스를 TCP 소켓으로 연결하는 과정이 시작됩니다.
*프로세스: 프로세스는 실행 중인 프로그램 정도로 이해할 수 있습니다.
이 과정이 어떻게 진행되는지 알아보기에 앞서, 소켓이 무엇이고 TCP가 무엇인지 알아보겠습니다.
소켓(Feat. Port)
우선, 구글 서버까지 찾아가기 위해서 IP 주소만 있으면 충분할까요? 사실 그렇지 않습니다. 하나의 아이피가 할당된 컴퓨터에슨 다수의 프로그램들이 동작하고 이것을 프로세스라고 부릅니다. 예를 들면, 서버측에서는 웹페이지를 보여주는 프로세스, 이메일 프로세스, 파일 전송 프로세스 등이 있을 수 있고, 클라이언트 측에도 크롬 브라우저 하나와 LoL게임 하나를 돌리고 있을수 있겠죠. 이 많은 프로세스 중에서 우리가 원하는 것은 서버의 웹페이지(구글 화면을 띄어주는) 프로세스와 내 컴퓨터의 크롬 브라우저 프로세스 간에 통신을 하고 싶습니다.
Port : 프로세스 식별자
그래서 필요한 것이 'Port'입니다. 이 포트 번호는 프로세스를 식별해주는 번호입니다. 하나의 IP가 식별하는 네트워크가 연결된 컴퓨터( 이걸 호스트라고 부릅니다) 안에서 이 포트 번호로 특정 프로세스를 식별할 수 있습니다.
이 포트 번호는 0번 부터 65535번까지 포트번호를 사용할 수 있는데, 그 중에서 1023번까지는 well-known port(잘 알려진 포트)라고 불리며, 인터넷 할당 번호 관리기관인 IANA에 의해 특정 프로토콜은, 미리 약속된 포트 번호를 사용하도록 권고됩니다. 앞서 배웠던 TCP/IP 4계층 모델에서 Application Layer에 속하는 프로토콜들은 주로 정해진 포트 번호를 사용합니다.
대표적인 well known port number는 아래와 같습니다.
-
SMTP - 25 (TCP)
-
DNS - 53 (TCP/UDP)
-
DHCP - 67 (UDP)
-
HTTP - 80 (TCP)
- HTTPS - 443 (TCP)
마찬가지로, 1024번에서 49151번 포트는 registered port(등록된 포트)라고 하여, 특별한 경우를 제외하고 특정 프로세스가 사용합니다. 대표적인 예로 3306번을 사용하는 mysql이 있습니다.
그리고 남은 49152번 ~ 65535번 포트를 dynamic port(동적 포트)라로 하며, 개발자가 임의로 지정하여 사용할 수 있는 포트 번호입니다.
다시 소켓: 클라이언트 식별, 통신 창구
자, 이제 프로세스를 식별할 준비가 되었습니다. 그런데 안타깝게도 이것으로는 부족합니다. 왜냐하면, 하나의 서버에는 수만 이상의 클라이언트가 동시에 접근할 수 있기 때문입니다. 그래서 서버와 하나의 클라이언트를 식별할 수 있어야하고 이것이 바로 '소켓'입니다. 클라이언트가 IP address와 Port를 통해 구글서버를 찾아가면, 나의 브라우저와 서버를 1대1로 식별하는 '소켓'을 생성합니다. 그리고 이 소켓은 서버 측에 하나, 클라이언트 측에 하나가 만들어지며, 이것을 통해 통신하는 것입니다. 서버 입장에서 보면, 서버와 통신하려고 하는 클라이언트 마다 소켓을 생성해서, 하나의 프로세스 아래 여러 소켓을 가지고 있죠.
소켓의 본질은 사실 파일이며, 일종의 버퍼입니다. 클라이언트의 통신이 Transport Layer까지 올란 뒤에, 전달한 내용을 이 파일 위에 씁니다. 그리고 Application Layer의 프로토콜이 이 파일을 읽어서 처리합니다. 그래서 소켓 계층이 Transport Layer와 Application Layer 사이에 있다라고 표현하기도 합니다.
그럼 이제 소켓까지 알았으니, TCP에 대해서 알아볼까요?
사실 지금은 'TCP 소켓을 여는 단계'이기 때문에, 여기서는 간략하게만 다루고 나중에 다시 자세히 다루겠습니다.
간단하게 말하면 TCP는 전송계층에 속해있기에 어플리케이션에 데이터를 잘 보내주는 역할을 하고 그래서 이때 앞서 알아본 포트 번호를 사용하고, 데이터의 신뢰성을 보장하면서 데이터를 보내는 방식을 사용합니다.(UDP라고 신뢰성을 보장하지 않는 전송계층의 프로토콜도 있습니다.) 그리고 신뢰성을 보장하기 위해 두 당사자(클라이언트와 서버)의 연결을 확실히 해놓죠. 이것을 연결지향형이라고 합니다.
소켓이 작동하는 방식은 다음과 같습니다.
클라이언트 관점
1. 소켓 생성 : 클라이언트에서 소켓을 생성합니다. 이때 어떤 전송계층의 프로토콜을 사용하는지에 따라 TCP는 스트림 타입을 , UDP는 데이터그램을 받습니다.
2. 연결 : 서버측의 소켓과 연결합니다. 이때도 TCP와 UDP에 따라 연결하는 방법이 달라집니다. (TCP의 연결방식에 대해서 뒤에 다루겠습니다.)
3. 데이터 송수신 : 연결된 소켓을 이용해 데이터를 주고 받습니다.
4. 소켓 닫기 : TCP의 소켓 닫는 방법도 다루겠습니다.
서버 관점
1. 소켓 생성
2. 바인딩(bind) : 특정 프로세스를 가리키는 특정 포트에 연결합니다.
3. 대기: 클라이언트의 요청을 기다립니다.
4. 연결 수립: 이때 1번에서 만들어 놓은 소켓으로 연결하는 것이 아니라, 새로운 소켓을 생성해서 클라이언트와 연결합니다. 1번 소켓은 이 포트로 들어오는 연결 요청을 듣는 역할만 수행합니다.
5. 데이터 송수신
6. 소켓 닫기
How It Works?
그럼 TCP 소켓이 무엇인지 알아봤으니, 어떤 과정으로 이뤄지는지 알아보겠습니다.
우선 구글에 'www.google.com'이라고 입력하면, 구글 브라우저에서 자동으로 앞에 'https://'를 붙여줍니다. 사용자가 특정하지 않을 경우, 브라우저에 설정된 디폴트 값으로 붙는데요, 최근 크롬 버전에서는 https에가 디폴트 값입니다. 그리고 당연히 서버가 사용하는 Application Layer의 프로토콜이 정해져있고, 구글의 경우는 https이며 well-known port로 433을 사용합니다. 만약 클라이언트가 http로 요청을 보낼 경우, 301에러를 보내 https로 redirect합니다. 또한 https는 기본적으로 전송계층에서 TCP를 사용합니다.
따라서, 브라우저는 DNS를 통해서 IP를 알았고, default값에 따라 HTTPS에 상응하는 433이라는 포트번호와 TCP를 통해 통신할 것을 알고 있는 상황입니다.
우선 브라우저(프로세스)는 TCP 소켓을 생성합니다. 그리고 구글의 IP주소와 포트번호로 연결 요청을 보냅니다. 이때 '3 way handshake'라는 TCP의 소켓 연결 방식을 이용합니다.
3-way-handshake
나중에 또 다시 다루겠지만, TCP의 특징 중 하나는 연결 지향형입니다. 그래서 두 당사자(클라이언트와 서버)가 제대로 통신이 되는지 확인하는 작업을 거쳐 논리적 연결을 만듭니다. 이 연결되는 과정을 알기 위해서 아래의 TCP 헤더를 잠깐 살펴보겠습니다.
눈여겨 보아야할 곳은 우선 Source port와 Destination port입니다. 이름처럼 송수신 포트 번호를 담습니다. google의 경우 수신 https를 사용함으로 포트번호는 433이 될 것이고, 송신은 랜덤으로 붙습니다.
다음은 Sequence number입니다. 이전에 패킷 교환 방식에서 살펴봤듯, 하나의 큰 데이터는 여러 개의 작은 패킷으로 나눠져서 송수신 됩니다. 이때, 여러 라우터를 거쳐서 가는데, 트래픽 상황에 따라 패킷의 순서가 바뀔 수도 있고 심지어 누락될 수도 있습니다. 그래서 패킷이 도착한 후, 다시 재조립할 때 패킷의 순서를 가리키는 것이 이 시퀀스 넘버입니다. 시퀀스 넘버는 새로운 연결이 만들어질 때 임의의 번호로 초기화 됩니다.
다음은 Acknowledgment number입니다. 이 부분은 수신자가 받을 다음 패킷의 시퀀스 넘버(현재 시퀀스의 +1)입니다.
다음은 NS부터 FIN까지를 묶어서 Flags라고 부르며, 패킷의 상태를 나타냅니다. 이 중에서 살펴봐야할 것은 SYN, ACK, FIN입니다.
SYN은 synchronize의 약자로, 처음 상대방와 연결을 생성할 때, 즉 3 way handshake를 진행하기 위한 패킷임을 표시합니다.
ACK는 Acknowlegment number 필드에 값이 채워져있음을 알리는 플래그입니다.
FIN은 상대방과 연결을 종료하고 싶다는 요청을 알리는 플래그입니다.
이제 본격적으로 3 way handskake의 과정을 다음과 같습니다.
1. 클라이언트가 SYN 패킷을 클라이언트에게 보냅니다.
패킷을 보낸다는 무슨 의미일까요?
보통의 패킷은 상위 레이어부터 데이터에 헤더를 붙여가면서 패킷을 구성합니다. 예컨데, Application Layer(HTTPS)에서 프로세스끼리 통신하고자하는 데이터를 Transport Layer(TCP)에 내려보면, 그 데이터에 TCP 헤더를 붙여 Segment를 구성하고, 다시 Internet Layer(IP)로 내려보내 IP 헤더를 붙여 Packet을 구성합니다. 그리고 다시 Network Access Layer(Ethernet)에 내려보내서 Ethernet 헤더를 붙여 Frame을 만듭니다. 여기서 Frame헤더에는 이 프레임이 당장 가야할 가까운 호스트를 MAC 주소를 이용해서 찾아가는데요. 사실 목적지에 도달하기 까지, 이 Frame헤더는 여러 호스트를 들르면서 Capsulation과 Incapsulation을 반복합니다. 그래서 패킷부터 목적지에 도착할 때까지 벗겨지지 않기 때문에, 패킷을 보낸다라는 표현을 사용합니다.
SYN 패킷은 무엇일까요?
위에서 말한 패킷과 다른 점이 있는데, 소켓 연결을 위한 SYN 패킷은 응용계층으로 부터 넘겨받은 데이터가 없는 형태입니다. 당연히, 연결을 위한 패킷이기 때문에, 어플리케이션(프로세스)끼리 주고 받을 정보는 없기 때문입니다. 그리고 위에서 TCP헤더의 주요 구성요소에는 다음과 같은 정보가 담겼습니다.
Sorce Port / Destination Port : 송수신 포트 번호
Sequence Number : 임의로 생성한 번호
Acknowledgment number: 초기에 0으로 리셋
SYN(flag중에 하나): 이진수의 1로 값이 세팅되어, 이 패킷이 연결을 요청하는 것임을 알립니다.
정리하자면,클라이언트가 서버에게
포트번호를 통해 통신하고자하는 프로세스에 찾아가서,
SYN에 1을 싣어 '나 너랑 연결하고 싶어!',
Sequence Number로 '나 이 번호로 패킷 순서를 식별할 거야!'
라고 말을 건내는 겁니다.
2. 서버는 SYN 패킷을 받아 ACK 패킷을 보냅니다.
서버는 ACK플래그와 SYN플래그를 설정한 후,
서버는 클라이언트에게 받은 SYN패킷의 Sequence number에 1을 더해서 Acknowlegment number에 담습니다. 이 뜻은 '어! 통신하자! 니 시퀀스 번호 잘 알았어!'.
그리고 임의 숫자를 생성하여 Sequence Number에 할당합니다. 이 뜻은 '내 시퀀스 번호는 이거야!'라고 대답을 합니다.
3. 클라이언트가 ACK 패킷을 보냄으로서 두 소켓을 연결합니다.
클라이언트는 서버가 준 패킷의 Acknowlegment number를 보고 서버가 나의 요청을 잘 받아드리고 있는지 확인한 후,
패킷에 ACK flag를 달고, 전달받은 서버의 시퀀스 번호에 1을 더해서 Acknowlegment number에 담아 보냅니다.
4. 서버가 클라이언트의 ACK를 최종확인한 후, 소켓을 연결합니다.
지금까지 구글 서버와 소켓을 통해 연결하는 과정을 알아봤습니다. 추가로 연결이 있으면, 연결 해제가 있겠죠? 지금 단계에서 바로 발생하지는 않지만, 미리 알아본 후 넘어가도록 하겠습니다.
4 way handshake
연결을 끊을 때는 4번 패킷이 오가서, 이렇게 불립니다.
위의 과정과 상당히 유사합니다. 다른 점은 연결을 요청한다는 의미의 SYN flag 대신, 연결을 종료한다는 의미의 FIN flag가 사용됩니다.
그리고, 클라이언트는 마지막 ACK 패킷을 보내고 난 후에 바로 연결을 종료하지 않고, 일정 시간 패킷을 기다리는 'TIME-WAIT' 상태가 되는데요, 이는 어떤 네트워크의 문제로 패킷이 늦게 도착할 경우를 대비하기 위함입니다.
참고
https://www.joinc.co.kr/w/Site/TCP_IP/TCP_Header#toc
https://parksb.github.io/article/36.html#still-getting-started%3A-ethernet%2C-dns-and-arp
'Computer Science > Network' 카테고리의 다른 글
[네트워크] "www.google.com"을 입력하면 어떻게 되나? 6편 TCP (0) | 2022.08.13 |
---|---|
[네트워크] "www.google.com"을 입력하면 어떻게 되나? 5편 HTTP (0) | 2022.08.10 |
[네트워크] "www.google.com"을 입력하면 어떻게 되나? 4편 SSL (TLS) (0) | 2022.08.10 |
[네트워크] "www.google.com"을 입력하면 어떻게 되나? 2편 DNS (0) | 2022.08.08 |
[네트워크] "www.google.com"을 입력하면 어떻게 되나? 1편 - LAN/WAN, TCP/IP 4 계층, 패킷 교환 방식 (0) | 2022.08.04 |