보안 / AI / 프로그래밍
[0x432-0x433] [보충] TCP HEADER Window Size 본문
[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값을 알려주고 있습니다.
- 각 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 를 이용해서 하나의 패킷을 캡쳐한 것입니다.
- 위 사진 패킷은 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값을 직접 보고싶으시다면, 아래와 같은 방법을 사용하셔야 합니다.
- 잘 보시면, 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 입니다.
- 위에서 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로 사용해버립니다.
참조자료
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/
'Hacking :: The Art Of Exploitation > 0x400 :: 네트워킹' 카테고리의 다른 글
[0x432-0x433] [보충] TCP HEADER CheckSum 구하기 (0) | 2021.02.12 |
---|---|
[0x432-0x433] [보충] TCP HEADER Urgent Pointer (0) | 2021.02.07 |
[0x432-0x433] [보충] IP HEADER CheckSum 구하기 (0) | 2021.02.05 |
[0x433] 전송계층 ( OSI 4계층 ) - TCP (0) | 2021.02.05 |
[0x432] 네트워크 계층 (OSI 3계층) / IP HEADER (0) | 2021.02.03 |