보안 / AI / 프로그래밍

[0x432-0x433] [보충] TCP 3 Way-HandShake 본문

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

[0x432-0x433] [보충] TCP 3 Way-HandShake

DevKTW 2021. 2. 13. 12:35

[0x432-0x433] [보충] TCP 3-Way-HandShake 란?

In telecommunications, a handshake is an automated process of negotiation between two participants through the exchange of information that establishes the protocols of a communication link at the start of the communication, before full communication begins. The handshaking process usually takes place in order to establish rules for communication when a computer attempts to communicate with another device. Signals are usually exchanged between two devices to establish a communication link. (출처 : Wikipedia)

통신에서, HandShake는 완전한 통신이 시작되기 전, 통신의 시작부분에서 통신의 프로토콜을 약속하는 정보를 서로 주고 받는, 일련의 자동화된 합의(=협상) 과정입니다. (즉, 두 통신자가 서로 통신하기 전에, 어떤 방식으로 상대방에게 통신을 전달할 것인지 결정하는 과정입니다.)

HandShaking 과정은 보통 "하나의 컴퓨터가 다른 기기에 통신을 시도할때, 통신 규칙을 정하기 위해서" 진행됩니다. 통신 연결을 하기 위해서 두 사이에서 신호 교환 (= 정보 교환) 이 이루어집니다.

TCP 에서는 3번의 과정을 통해 이루어지므로, TCP 3 Way HandShake 라고 칭합니다.

[0x432-0x433] [보충] TCP 3-Way-HandShake 과정

- 예를 들어 Client 와 Server 가 HandShake를 한다고 가정하겠습니다.

클라이언트와 서버의 통신 초반부 TCP 3 Way HandShake 과정이다

- 클라이언트가 서버와 연결하려면 SYN 비트는 켜져있고, ACK 비트는 꺼져있는 패킷을 서버에게 보냅니다.

  그러면 서버는 SYN 과 ACK 비트가 모두 켜져 있는 패킷으로 응답합니다.

  마지막으로 클라이언트가 SYN 비트는 꺼져있고 ACK 비트는 켜져 있는 패킷을 서버에게 보내면 연결이 맺어집니다.

 

- 이 이후에 전송되는 모튼 패킷은 ACK 비트가 켜져 있고 SYN 비트는 꺼져있습니다. 그러므로 SYN 비트가 켜져 있는

  패킷은 HandShake 과정" 처음 두 패킷 " 밖에 없습니다.

 

- SYN 비트가 켜져 있는 패킷의 역할은 순서번호를 동기화 (=초기화=초기값설정) 하는 것입니다.

 

- 그림을 보시면, 클라이언트가 SYN 패킷과 함께 Random 으로 생성된 Seq값 (승인번호) 를 넘깁니다.

  그 후 서버는 이를 확인하고, 확인했다는 의미로 Seq + 1 의 값을 Ack (승인번호) 에 저장하고, 클라이언트와 마찬가지로

  Random 으로 생성된 Seq값 (순서번호) 를 넘깁니다.

  마지막으로 클라이언트 또한 이를 확인하고, 확인했다는 의미로 Seq + 1 의 값을 Ack(승인 번호) 에 저장하고, 서버가 마지막으로 보낸 Ack 값 (승인 번호)을 Seq값 (순서번호)에 담아서 보냅니다.

 

- Seq 값과 Ack 값이 서로 주고받는 모습이, "너 어디까지 확인했어? 나는 너가 준 여기까지 확인했어" 같은 느낌입니다.

  자세하게 묘사하면,

  "나 324808530부터 시작할게" (SYN)

  "그래 324808531 까지 확인했어, 나는 288666267부터 시작할게" (SYN/ACK)

  "그래 288666268 까지 확인했어, 324808531 확인해줘"

  입니다만, "까지"라는 표현은 부적절한 듯 합니다. 어디까지나 느낌적인 이해용으로 봐주세요.


[0x432-0x433] [보충] TCP 3-Way-HandShake 과정 - WireShark Filter 설정하는법

- 결론적으로 말씀드리면, TCP 3 Way HandShake 만 캡쳐하는 필터 식은 아래와 같습니다.

  왜 이런 식이 나왔는지 궁금하시다면 아래의 번역본을 살펴주세요.

tcp.flags.syn==1 or (tcp.seq==1 and tcp.ack==1 and tcp.len==0 and tcp.analysis.initial_rtt)

- 직접 캡쳐 / 분석한 결과입니다.

TCP 3 Way HandShake 과정을 WireShark 필터링 식을 통해서 직접 보고 확인한 결과이다.


[0x432-0x433] [보충] [번역] TCP 3-Way-HandShake 과정 - WireShark Filter 설정하는법

제가 직역, 의역, 첨삭 한것이라서, 번역에 오류가 있을 경우, 매끄럽지 않을 경우, 혹은 더 좋은 표현 알려주시면 감사 드리겠습니다.
원본 출처 : Advanced display filtering | Packet-Foo | Network Packet Capture and Analysis (packet-foo.com

 

 

Filtering for the packets of a TCP three way handshake may sound like a simple task, but it isn’t.  The first two packets are easy, because those are the only two that have the SYN flag set.To find these, simply filter on “tcp.flags.syn==1“.

 

- TCP 3 WAY HandShake 과정의 패킷을 캡쳐하는 필터링을 만드는건 간단한 것 같으나, 그렇지 않습니다.

  처음 2개의 패킷 (SYN 패킷 / SYN+ACK 패킷) 은 (통신 전체과정에서) 오직 그 두개의 패킷만 SYN가 켜져있으니,

  캡쳐하기 쉽습니다. 이 두개의 패킷을 캡쳐하기 위해서는, 간단하게 "tcp.flags.syn == 1"을 사용하면 됩니다.

 

But what about the third packet? It has only the ACK flag, but that’s also true for all other packets following the handshake, so we can’t just use that flag (at least not alone).

 

- 그러나 3번째 패킷은 어떨까요? 3번째 패킷은 오직 ACK 만 켜져있습니다만, HandShake 과정 이후의 모든 패킷들도 ACK 가 켜져있는건 마찬가지 입니다. 그래서 "tcp.flags.syn == 1" 필터링만 가지고 3번째 패킷까지만 캡쳐하는 것은 무리입니다.

 

Now, Wireshark beginners often try to find a filter expression that looks at packet dependencies, e.g. like “filter a packet that has a sequence number equal to the sequence of the previous SYN packet of the same connection plus one.” – and such a filter does not exist.You simply cannot filter on things in two different packets at the same time. Filters always look at a single packet at a time.

 

- 보통 이런 상황라면, 와이어 샤크 입문자들은 "실제 패킷에 의존하는 필터식"을 찾을 것입니다. 예를 들어서 (아까전에, 위의 사  진을 참고 해주세요.) 처음 SYN 패킷의 Seq 값인 324808530에 +1을 더한 324808531 값을 Seq 값으로 가지는 패킷을 필터링 해라! 같은 필터링 식을 말이죠.

 이러한 필터링 식은 존재하지 않습니다. 왜냐하면 324808530 라는 값을 "tcp.flags.syn == 1" 필터링으로 찾은 순간에, 이미 3번째 패킷은 필터링에 걸러져서 지나갔으므로, 그 이후 324808531 값을 Seq 값으로 가지는 패킷을 필터링 해라! 한들 이미 지나간 패킷을 캡쳐할 수 없기 때문입니다.

 

The workaround for filtering for the packet we want is to filter on values that can only be found in a packet that is the third packet of a three way handshake:

 

- 우리가 원하는 패킷을 필터링하는 방법은 3 Way HandShake 과정의 3번째 패킷에서만 발견될 수 있는 값을 필터링 하는 것입니다.

 

1) We know that the sequence number is one higher than in the SYN packet. Since the initial sequence number is random we would have a problem, but fortunately, Wireshark offers relative sequence numbers (turned on by default). This means that every SYN has a relative sequence number of zero, and the third packet will have a sequence number of one. So we filter on “tcp.seq==1“. And since we must have acknowledged the SYN/ACK from the server we know that the ACK number must also be one, which leads to a better filter: “tcp.seq==1 and tcp.ack==1“.Unfortunately, many packets can have a relative sequence number of one, because if the client (which initiated the connection, thus being the sender of the first and third packet) does not send any data (e.g. when receiving FTP-Data), the sequence will stay at one for the whole connection. So we need more fields to filter on that only appear in the third handshake packet.

 

- 우리는 3번째 패킷의 Seq 값이 SYN 패킷보다 1 크다는 것을 알고 있습니다. SYN 패킷의 Seq 값이 Random 이라서 문제가 있었지만, 다행히 Wireshark는 "상대 Seq값"을 제공합니다.(이는 기본적으로 제공됩니다.) 이는 "모든 SYN 패킷은 상대 Seq 값인 0을 가지게 됨"을 의미하고, "3번째 패킷은 상대 Seq값인 1을 가지게 됨"을 의미합니다. 그러므로 우리는 tcp.seq==1“ 필터를 사용하고, 또한 3번째 패킷은 SYN+ACK 패킷 후에 오므로, 즉 상대적 Seq 값과 더불어 Ack 값도 1 일것이므로,

결론적으로 tcp.seq==1 and tcp.ack==1“ 필터를 사용하게 됩니다. 그러나, FTP-Data 를 받는 경우와 같이,

3 Way HandShake 이후 클라이언트 측에서 아무런 데이터를 보내지 않는 경우 Seq 값이 1로 전체 통신 과정에서 머물러 있는 경우가 존재하므로, 우리는 HandShake 과정의 패킷만 캡쳐하기 위해, 이보다 더 많은 필터를 필요하게 됩니다.

 

2) We can exclude all packets that contain a TCP payload, because the third packet is empty (this may change with new rapid connection setup implementations in the future, but for the time being, it is empty). So we add the zero payload length to our filter: “tcp.seq==1 and tcp.ack==1 and tcp.len==0

 

- 3번째 패킷은 TCP Payload가 없으므로, 우리는 TCP Payload (=TCP Data=헤더 뒷부분)를 포함한 모든 패킷을 제외할 수 있습니다. (그러나 이는 나중에 바뀔 수 있으나, 현재로서는 3번째 패킷은 TCP Payload가 없습니다.)

그래서 우리는 TCP Payload 길이가 0인 것을 찾는 필터를 추가해 tcp.seq==1 and tcp.ack==1 and tcp.len==0“ 를 사용하면 됩니다.

 

3) The next problem is that this filter will also show all empty ACK packets where we haven’t seen the SYN and SYN/ACK packet in the trace (because they weren’t captured early enough), so we need to find a way to make sure we only accept ACK packets where we have the SYN and SYN/ACK in the trace. There is an easy trick to do this, but it only works since Wireshark version 1.12 and later: Wireshark 1.12 is the first version to calculate initial RTT for all TCP conversations when it has the full three way handshake. So if the iRTT field is available, we know that we have seen the SYN and SYN/ACK packet. The final filter for the third handshake packet is: “tcp.seq==1 and tcp.ack==1 and tcp.len==0 and tcp.analysis.initial_rtt“.

 

- 다음 문제는, 이 필터가 SYN 패킷과 SYN/ACK 패킷을 캡쳐하지 못한 곳에서, "비어있는 (TCP Data 가 없는) Ack 패킷들"을 보여준다는 것입니다. 그래서 우리는 "SYN-SYN/ACK-ACK" 이 형태로 캡쳐하기 위해서, 방법을 찾아야합니다. 저런 형태를 가지기 위해서는 WireShark 1.12 이후 버전이 필요합니다. WireShark 1.12 이후 버전은 3 Way HandShake가 끝나면 initial RTT 값을 계산하는 기능이 있습니다. 결론적으로 3 Way Handshake 과정의 "3번째 패킷"을 캡쳐하는 방법은

tcp.seq==1 and tcp.ack==1 and tcp.len==0 and tcp.analysis.initial_rtt“ 입니다.

 

To filter on all three way handshake packets: “tcp.flags.syn==1 or (tcp.seq==1 and tcp.ack==1 and tcp.len==0 and tcp.analysis.initial_rtt)” – keep in mind that this will show the handshake packets of any conversation, so there may be more than one set. If the filter doesn’t work for you, check if you have enable absolute sequence numbers.

 

- 3 Way HandShake 과정의 3개의 모든 패킷만을 캡쳐하는 필터는 아래과 같습니다. 이 필터는 무슨 연결이던 3 Way HandShake 라면 보여주는 필터이므로, 1개의 세트 (3 Way HandShake)보다 많이 캡쳐될 것이라는 사실을 기억하세요.

만약 이 필터가 작동하지 않을 경우, 설정에서 "절대 Seq 값"을 사용한다고 설정했는지 확인하세요.

 

tcp.flags.syn==1 or (tcp.seq==1 and tcp.ack==1 and tcp.len==0 and tcp.analysis.initial_rtt)

[참조자료]

Advanced display filtering | Packet-Foo | Network Packet Capture and Analysis (packet-foo.com)

blog.naver.com/popqser2/220911455064

Handshaking - Wikipedia

 

Comments