TCP handshake

gealber

Gealber Morales

Posted on May 11, 2021

TCP handshake

TCP

Introduction

This articles will be about two important networking protocols; TCP and UDP. I will try to make it concise, given the amount of information that there is related to these two particular protocols. I will try to approach this subject in a graphical way, trying to appeal to your love for pretty sketches.

Prerequisite

  1. Python 3.
  2. Wireshark or any other packet sniffer, choose one that you know how to use it.

I will be using python for simplicity, but this can be achieved with any other programming language of your choice.

What is a protocol?

Well, a protocol is a standard set of rules that allow the communication between electronic devices. So at the end, TCP is just a set of rules that is used by electronic devices to communicate between each other. Let's see some of these rules.

Description of TCP handshake

Establishing connection

Suppose we have two parts, and one is trying to reach out the other one using the rules of TCP, how could we achieve that? If you've read some information about TCP, then I'm sure you've read that

A TCP connection uses a three-way handshake to introduce both parts on the conversation...

Or something similar to that, right? Let's call one part the client, which is the node or part that start the communication, while the other node will be called server. Now, when the client try to start the conversation, he first sends a SYN flag to the server. If you are a curious person I'm sure you wonder what information goes on this first packet, so let's find out.

In order to be able to reproduce this situation, a simple TCP connection, I'm going to create an extremely simple server and client with Python using the socket library, which is part of the Python Standard Library so just having Python is good enough.

# server.py
import socket

def main():
    # creating the socket
    sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # binding the socket to the port 7456
    # notice that bind() take a tuple as argument
    sck.bind(('localhost', 7456))

    # now is time to say, I'm ready for connection OS, could you let me please?
    # the 1 specified how many connection it will queue up, until
    # start rejecting attempts of connections.
    sck.listen(1)

    print("Hey you I'm listening on 7456...weird port by the way")

    # accepting the incoming connection
    (client_sock, address) = sck.accept()
    while True:
        # 1024 is a magic number used on every networking tutorial out there
        # so here I also make use of it. Also in this case means that the socket
        # will process up to 1024 bytes of the incoming message from the client
        msg = client_sock.recv(1024)
        if not msg:
            break
        print(f"FROM: {address} MSG: {msg}")
        print()

    # good bye socket
    client_sock.close()


if __name__ == "__main__":
    main()

Enter fullscreen mode Exit fullscreen mode

This is more comments than code itself, so don't freak out. This is the part corresponding to the server.py file, nothing fancy here, we create the socket, bind the socket, etc... read the comments. Now for the client.py:

# client.py
import socket

def main():
    # creating the socket
    sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # just connecting
    sck.connect(("localhost", 7456))

    print("Sending data...")
    sck.sendall(b"Hola server, are you bored?")
    # I don't care about your response server, I'm closing
    sck.close()

if __name__ == "__main__":
    main()

Enter fullscreen mode Exit fullscreen mode

Even simpler, the client just send one message to the server, a pretty silly message but a message we don't need to be serious now.

The idea is to reproduce the situation as follows:

  • Open Wireshark, you may need to use sudo command in order to be able to sniff a network interface.

  • Given that the traffic that we want to sniff it is only local, we will be sniffing the loopback interface, here is a photo just in case.
    Wireshark loopback interface

  • We need to filter the traffic, given that we are using TCP on port 7456, so tcp.port == 7456 would be an appropriate filter for our case.
    TCP filter Wireshark

  • Now we are good to go, start the script with the server code. If you take a look at Wireshark right now, it won't be any traffic given that the client haven't tried to connect.

   python server.py
Enter fullscreen mode Exit fullscreen mode
  • Run the client script,
   python client.py
Enter fullscreen mode Exit fullscreen mode

Now you should see something like this,
Wireshark traffic

First SYN packet

If you look back, all this was done with the idea of looking at the first SYN packet sent by the client, right? Now let's look at it. If you give click on this first packet, Wireshark will show you all the info related to it, and let me tell you it's a lot. In order to simplify the analysis let's focus on Sequence number, Acknowledge number, Flags and Window size value.

SYN Packet

Sequence number: Is a number identifying a TCP segment, this is used to ensure that part of the data is not missed. It is like a way to keep track of the order in which the packets were sent.

Acknowledge number: The sequence number that is expected in the next packet from the other device.

Flags: Used to identify the type of TCP packet that is been transmitted.

Window size: The size of the TCP receiver buffer in bytes. This is a really tricky one, I didn't get it at first, I actually had a hard time trying to understand it. So I use the master of knowledge(Google or any other search engine), and found this question, Window Size and ACK

The Window Size(that the Receiver sets) is a hard limit on how many bytes the Sender can send without being forced to stop to wait for an acknowledgement.

I recommend you to read the whole question, because it clarifies some misunderstanding related to the Window size.

All this is handled by the library that you are using, so you won't need to handle this by yourself. So this first SYN packet sent by the client to the server, act like a simple presentation

SYN Packet Sketch

SYN, ACK by the server

In response to this SYN the server respond with a SYN, ACK packet. If you take a look at the same info mentioned before, you will notice that in this case the Flags Syn and Acknowledgement were marked as set

SYN and ACK set

The server say, "ok I saw you, this is my Sequence number(Seq), and I expect this sequence number from you(Ack)"

SYN/ACK server

ACK from client

This is the last part of the handshake, in this part the client reply with its current Seq which is the previous plus one, and also include the expected sequence number from the server(Ack).

ACK Packet
ACK

Conclusion

Understanding a protocol is not an easy task, even here we try to simplify this task to the most, focusing only on the connection of the two parts and analyzing the packets involved on this connection. Still knowing the ins and outs of the protocol worth it. Next time I will try to to the same with UDP.

Until the next time folks 👋.

Bibliography

  1. Practical packet analysis, third edition by Chris Sanders.
  2. Network Programming with Go Learn to Code Secure and Reliable Network Services from Scratch by Adam Woodbeck.
  3. Socket Programming HOWTO. Release 3.7.3rc1. From the Python Standard Library documentation.
  4. Window size and ACK.
  5. Loopback Ubuntu.
  6. TCP in a nutshell.
💖 💪 🙅 🚩
gealber
Gealber Morales

Posted on May 11, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

TCP handshake
linux TCP handshake

May 11, 2021