보안 / AI / 프로그래밍

[0x432-0x433] [보충] TCP HEADER Window Size 본문

Hacking :: The Art Of Exploitation/0x400 :: 네트워킹

[0x432-0x433] [보충] TCP HEADER Window Size

DevKTW 2021. 2. 7. 01:55

[0x433] TCP HEADER Window Size

- Window Size 필드는 송신자에게 응답( Ack )을 보내기 전에, 얼마나 많은 데이터를 수신자가 더 받을 수 있는지 알려줍니다.

- 만약 수신자가 데이터 ( =패킷 ) 를 받는대로 빠르게 처리할 수 없다면, 수신 받은 버퍼는 점점 증가하고, Ack 패킷 안의

   Window Size 값은 점점 감소합니다.

- 이 Window Size 필드는 "보내는 데이터를 좀 줄여야 함" "수신자에게 수신자가 받은 데이터 버퍼를 처리할 시간을 줘야 함"을 송신자에게 알려주는 역할을 합니다.

       왼쪽은 수신자가 송신자로부터 데이터가 오는대로 처리하는 반면, 오른쪽은 오는대로 처리하지 못해서 Window Size가 증가하는 모습이다.         (출처 : https://accedian.com/blog/tcp-receive-window-everything-need-know/)

- 위 사진을 보시면, 클라이언트와 서버가 자신들의 Window Size값을 알려주고 있습니다.

- 각 TCP HEADER는 가장 최근의 Window Size값을 나타내는데, 이는 통신과정에서 증가하고 감소할 수 있습니다.

 

- 예를 들어 클라이언트는 65,535 Bytes 만큼의, 서버는 5840 Bytes 만큼의 수신 버퍼의 여유 용량을 가지고 있습니다.

- 대부분의 프로그램들은 클라이언트가 서버보다 데이터를 주기보단, 받는 것이 더 많기 때문에, 클라이언트가 서버보다

  더 많은 Window Size값을 가집니다.

 

- <왼쪽 사진을 보시면> 3 Ways HandShake 이후에, 클라이언트는 HTTP GET 요청을 서버에 보냅니다.

  그 후에 서버로부터 Ack가 담긴 패킷과 데이터가 클라이언트에게 옵니다.

  클라이언트는 데이터들이 오는대로 빠르게 처리할 수 있기때문에, 마지막 통신을 보시면 Ack 와 함께

  Window Size 값이 줄지 않았음을 알 수 있습니다.

 

- <오른쪽 사진을 보시면> 클라이언트가 서버로부터 요청한 데이터를 받는, 아까와 비슷한 상황이 벌어지나, 이번에는

 클라이언트가 들어오는 데이터를 오는대로 빠르게 처리하지 못하여, TCP 버퍼는 계속 차고, Window Size값은

 줄어듦을 알 수 있습니다. 서버는 클라이언트의 Ack 가 담긴 패킷으로 부터 Window Size 값이 줄어듦을 인지하는거죠.

 

- 대부분의 경우는, Window Size값이 줄어든다 하더라도, 영향이 거의 미치지 않을 정도로 작고, 아직 Window Size값에 해당하는 버퍼가 충분히 남았기 때문에, 클라이언트는 이 차이를 빠르게 따라잡고, Window Size 값을 증가시킵니다.

 

- 그러나 Window Size값이 0으로 줄어들 경우, 프로그램이 오류가 발생할 수 있습니다.

 


[0x433] TCP HEADER Window Size의 확장

- TCP Header의 크기는 2 Bytes 입니다. 이말은 즉, "수신 버퍼의 여유 용량이 65,535 Bytes (2^16 - 1 = 65,535)" 임

  의미합니다. 즉 한번에 최대로 보낼 수 있는 패킷의 크기는 65,535 Bytes 입니다.

- 하지만 요즘 인터넷 속도에 비하면 턱없이 부족한 패킷 크기입니다. 이대로라면 TCP의 고성능 연결의 장점을 취할 수 없죠.

 

- 이러한 이유때문에 TCP Options 가 RFC1323에 소개되었는데, 이는 TCP Window Size 를 기하급수적으로 늘릴 수 있게

  해주는 것이었습니다.이 특별한 기능은 TCP Window Scaling 이라고 불리는데, 이는 3 Way HandShake 과정에서"만" 클라이언트나 서버가 Window Size 값과 함께 scale 값을 같이 주게 됩니다. 그리고 이 값들은 연결 내내 지속됩니다.

 

- 다음은 WireShark 를 이용해서 하나의 패킷을 캡쳐한 것입니다.

WireShark 를 통해 Window Size Scaling factor 를 살펴본 모습이다.

- 위 사진 패킷은 3 Ways HandShake 과정의 패킷이 아니므로 Window Size Scaling factor 를 패킷에서 볼 수 없습니다.

- 그래도 3 Ways HandShake 과정에서 약속한 Window Size Scaling Factor 값이 256 으로 유지되서 총 확장된 Window Size 값은 262656, 즉 262656 Bytes 로 수신 여유 공간 용량을 가지고 있음을 나타냅니다.

 

- 참고로 WireShark 가 3 Ways HandShake 과정을 캡쳐하지 못했다면, WireShark 가 Window Size Scaling Factor 를 찾을 수 없기 때문에 오른쪽 사진과 같은 상황이 벌어지니, 삽질하지 마시기 바랍니다.

 

- WireShark 로 3 Ways HandShake 과정의 Window Size Scaling Factor값을 직접 보고싶으시다면, 아래와 같은 방법을 사용하셔야 합니다.

Window Size Scaling Factor 값은 TCP HEADER 의 Option 필드에 들어갑니다. TCP Options에 대해서는 다음에 다루겠습니다.
tcp.option_kind == 3 으로 살펴본 WireShark 화면. 대부분이 자명하게도 SYN , SYN+ACK 패킷이다.

- 잘 보시면, TCP HEADER Option 필드에 파란색으로 표시된 "00001000" 이 보이실텐데요. 이 값이 위에 분석창에 Shift Count 값을 의미합니다. 10진수로 8이죠. 이는 Window Size 값에 2의 8제곱을 곱한 값만큼 Window Size를 늘리겠다는 의미입니다.

 

- 즉 확장된 Window Size는 아래와 같습니다. (사실 쉬프트 연산을 통해 나오나, 아래과정은 10진수로 계산하는 법입니다. 쉬프트 연산 과정은 맨 아래 참조자료 링크의 2번쨰 링크에서 4번째 사진을 참고하세요.)

  Window Size 필드 값 * ( 2의 Window Size Scaling Factor 값만큼의 제곱 ) = 확장된 Window Size 크기 // 쉬프트 연산

- 사실, 이를 알아보려면 TCP HEADER 의 옵션을 알아볼 수 있어야 하는데요, 간략하게 이번 글과 관련된 옵션만 살펴보겠습니다. 다음은 < RFC 1323 > 에 명시된 Window Scale Option 입니다.

 

RFC 1323

 

- 위에서 tcp.option_kind == 3 의 명령어를 왜 사용했는지 이해가 가실 것입니다. 옵션의 종류 (=kind) 값이 3이기 때문입니다.

- 옵션의 구조를 보면 Kind -> Length -> shift.cnt 구조를 가지는데요. 위의 패킷 덤프를 맨끝부터 조금 가져오겠습니다.

 

00000001 "00000011 00000011 00001000" 00000001 00000001 00000100 00000010

 

- 해당 부분을 보시면 RFC 1323 에 명시된 내용과 같이 3 (=00000011) -> 3 (=00000011) -> 8 (00001000) 구조를 가진것을 알 수 있습니다.

 

Since the max window is 2**S (where S is the scaling shift count) times at most 2**16 - 1 (the maximum unscaled window), the maximum window is guaranteed to be < 2*30 if S <= 14. Thus, the shift count must be limited to 14 If a Window Scale option is received with a shift.cnt value exceeding 14, the TCP should log the error but use 14 instead of the specified value.

< RFC 1323 > 에서 명시하듯, shift count 의 값은 14 이하이어야 하며, 이를 초과할 경우 값을 14로 사용해버립니다.


참조자료

tools.ietf.org/html/rfc1323

packetlife.net/blog/2010/aug/4/tcp-windows-and-window-scaling/

accedian.com/blog/tcp-receive-window-everything-need-know/

www.ktword.co.kr/abbr_view.php?nav=&m_temp1=1469&id=746

ask.wireshark.org/question/562/what-does-a-window-size-scaling-factor-of-1-mean/

Comments