TCP 3 way handshake, 4 way handshake 알아보기 (feat wireshark)

skyepodium·2022년 2월 2일
2
post-thumbnail
post-custom-banner

TCP 전체 프로세스

TCP 프로토콜은 1974년에 설계되었고, 1981년에 작성된 rfc793 문서에는 전체 과정이 기술되어있습니다.

사실 봐도 잘 이해는 되지 않습니다.

다음 2개에 대해 알아보겠습니다.

  • 연결에 사용되는 - 3 way handshake
  • 종료에 사용되는 - 4 way handshake

3 way handshake

1) 정의

3 way handshake는 클라이언트와 서버가 서로 통신할 준비가 되었음을 확인하는 과정입니다.

2) 과정

3개의 과정이 진행됩니다.

1. syn sent

먼저, 클라이언트는 임의의 난수로 생성된 seq 번호 x를 서버로 보냅니다.
syn(x)

클라이언트의 상태를 syn sent라고 부릅니다.

2. syn received

서버는 받은 seq 번호에 1을 더한 값을 ack번호로, 임의의 난수로 생성된 번호를 seq 번호로 보냅니다.
ack(x+1), syn(y)

서버의 상태를 syn received라고 부릅니다.

3. established

클라이언트는 받은 syn 번호에 1을 더한 값을 ack번호로 보내고 통신이 수립됩니다.
ack(y+1)

클라이언트의 상태는 established입니다.

3) 와이어샤크 확인

다음은 HTTP/1.1 프로토콜로 통신할 때 3 way handshake가 일어나는 과정입니다.

참고로 HTTP 프로토콜은 3.0까지 나왔습니다.

  • 1.1, 2.0 - TCP 기반
  • 3.0 - UDP 기반

1. syn sent

클라이언트는 임의의 seq 번호(896377445)를 생성하고, syn flag를 1로 설정 후 서버에 보냅니다.

2. syn received

서버는 클라이언트로 받은 seq번호에 1을 더한 값(896377446)을 ack 번호로 설정합니다. 그리고 임의의 난수(533696001)을 생성해서 seq 번호로 클라이언트로 보냅니다.

이때 syn, ack 플래그를 1로 만듭니다.

3. established

클라이언트는 서버로 부터 받은 seq 번호에 1을 더한 값(533696002) 을 ack 번호로 설정하고 ack 플래그를 1로 설정하여 서버로 보내고 연결을 수립합니다.

4. 이후

3 way handshake로 통신준비가 되었음을 확인하면 HTTP 프로토콜로 서버에 요청합니다.

4 way handshake

1) 정의

4 way handshake는 클라이언트와 서버가 서로의 통신을 종료하는 과정입니다.

2) 과정

1. fin-wait1

첫번째로 서버는 클라이언트에 fin번호(x)를 보냅니다.

2. close-wait, last-ack

두번째로 클라이언트는 fin에 대한 ack번호(x+1)과, 임의의 난수로 생성된 fin번호(y)를 보냅니다.

3.fin-wait2, time-wait

마지막으로 서버는 fin번호에 대한 ack 번호를 전송하고 닫기 전에 시간 초과를 기다립니다. 이전 연결을 통해 클라이언트에서 보내진 후속 패킷을 기다리기 위함입니다.

이것만 보면 3 way 인데 왜 4 way 라고 하냐 할 수 있는데요. 위키피디아에 따르면 fin & ack를 한번에 보낼수 있다고 합니다.

3) 와이어샤크 확인

4 way handshake에서 종료를 위한 fin은 서버가 먼저 보냈습니다. 위키 피디아에서도 딱히 누가 먼저 보낸다는 언급은 없는것을 볼때 꼭 누가 먼저보내야하는것은 아닌듯

1. fin-wait1

서버가 클라이언트에 fin 번호(533696405)를 보냅니다.

2. close-wait, last-ack

클라이언트가 받은 fin번호에 1을 더해 ack 번호로 설정하고(533696406), 임의의 난수를 fin번호(896377897)로 설정해서 서버에 보냅니다.

3. fin-wait2, time-wait

서버는 받은 fin번호에 1을 더해 ack 번호(896377898)로 설정하고 클라이언트에 보냅니다.

이후 이전 연결에서 보내진 패킷이 올 수 있기 때문에 타임아웃을 기다립니다.

정리

사실 여기까지 대단한것은 없습니다.

결국 보내진 syn, fin 번호에 1을 더한 값을 ack 번호로 전송하고

연결을 원하는 쪽은 syn 번호를 보내고

종료를 원하는 쪽은 fin 번호를 보내면됩니다.

참고

1) syn, ack, fin 이란?

syn, ack, fin은 TCP 헤더에 사용되는 플래그로 쓰임새가 다릅니다.
syn은 연결 생성, fin은 연결 종료, ack는 syn과 fin에 대한 응답으로 사용됩니다.

syn, fin 번호는 32비트의 난수로 생성되며 syn 또는 fin 플래그를 1로 만들고 seq번호를 번호를 전송하면 syn, fin 번호로 사용됩니다.

ack는 syn fin에 대한 응답으로 받은 syn, fin 번호에 1을 더한 값을 ack 번호로 전송합니다.

다음은 TCP 헤더입니다.

1.syn 번호 전송

syn 비트를 1로 만들고, seq 번호를 보내면 syn 번호로 사용됩니다.

2. ack 번호 전송

ack 비트를 1로 만들고, ack 번호(그림에서 octet 8)를 설정 후 보내면됩니다.

ack가 syn 또는 fin번호 x에 1을 더해서 반환하는 이유는 x 번호를 잘 받았고, 다음 번호 x+1를 달라는 의미입니다.

3. fin 번호 전송

fin 비트를 1로 만들고, seq 번호를 보내면 fin 번호로 사용됩니다.

2) 왜 ISN(Initial Sequence Number)는 난수로 생성될까요?

맨 처음 연결을 위해 보내는 syn 번호를 ISN이라고 부릅니다.

rfc793에 따르면 시퀀스 번호는 난수이며 32 bit입니다. 이는 이전 연결의 seq와 겹치지 않기 위함입니다.

만약 매번 0부터 시작한다면, 이전 연결에서의 시퀀스와 겹쳐 구분이 되지 않을 수 있기 때문입니다.

참고

하나의 bit가 약 4마이크로세컨드마다 증가하기 때문에 ISN의 사이클은 약 4.55시간입니다.

이에 따라 seq 번호의 수명은 최대 4.55시간입니다. 이를 통해 ISN이 유니크함을 보장할 수 있습니다.

파이썬으로 계산하면 약 4.77시간 나옵니다. 약간 다를 수 있지뭐

# 1. 총 경우의 수 2의 32제곱 - 약 42억
total = 2 ** 32

# 2. 수명 계산 - 1 마이크로세컨드는 백만분의 1초, 4 마이크로 세컨드마다 증가함
# 15 곱한 이유는 60분 만들기 위함
# 60 곱한 이유는 1시간 만들기 위함
t = 1000000 * 15 * 60

# 3. 출력 - 약 4.77
print(total / t)

profile
callmeskye
post-custom-banner

0개의 댓글