TCP handshake
Tags: linux, python, networking, tutorial
Published: 2021-05-11 18:11:19

# 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

2. 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.

```python
# 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()

```

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`:

```python
# 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()

```

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**](https://askubuntu.com/questions/247625/what-is-the-loopback-device-and-how-do-i-use-it#:~:text=The%20loopback%20device%20is%20a,running%20on%20the%20local%20machine) interface, here is a photo just in case.
  ![Wireshark loopback interface](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lkkkw8gymd7ffjtxkg92.png)
* 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/esvgh6odn7zxog1idzdt.png)
* 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.
   ```bash
   python server.py
   ```
* Run the client script, 
   ```bash
   python client.py
   ```
   Now you should see something like this,
   ![Wireshark traffic](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l45n4veqercfiz17rcx4.png)

### 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dou9jf932vqqzq47ohkc.png)


**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](https://networkengineering.stackexchange.com/questions/12485/window-size-and-ack-number?newreg=b2fb52d5b29844ef8c6ad2f2226cf3a6)

> 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/teex02kro237rtruy45a.png)

### 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/89d39rmjv7o29shfw8zk.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t2zr5b0ou1n2qmckuqyy.png)

### 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nkqsh54f85p6yfe06pwo.png)
 ![ACK](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3vb5lizsxvasaiyx394t.png)

## 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 :wave:.

## 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](https://networkengineering.stackexchange.com/questions/12485/window-size-and-ack-number?newreg=b2fb52d5b29844ef8c6ad2f2226cf3a6).
5. [Loopback Ubuntu](https://askubuntu.com/questions/247625/what-is-the-loopback-device-and-how-do-i-use-it#:~:text=The%20loopback%20device%20is%20a,running%20on%20the%20local%20machine).
6. [TCP in a nutshell](https://www.cs.miami.edu/home/burt/learning/Csc524.032/notes/tcp_nutshell.html#:~:text=The%20sequence%20number%20is%20the,the%20receiver%20expects%20to%20receive).