Connect to an HTTP Server Residing on a Separate Namespace
Tags: linux, devops, networking, sre
Published: 2022-11-20 17:42:52

To understand the Linux network namespaces a bit better, we'll try to spin up an HTTP server using python in one namespace and connect with it using another namespace.

We'll start by creating two namespaces and connecting them using a virtual ethernet (veth). The [previous tutorial](https://dev.to/umarfchy/connecting-linux-network-namespaces-with-veth-4cfk) covers this in a step-by-step process. This tutorial is a part of [personal project](https://github.com/umarfchy/playing-with-linux-network-namespaces) where we can find a `docker-compose` file that spins up the environment with a single command `docker compose up -d`. This will start a docker container named `network-companion`. We can enter into the container using `docker exec -it network-companion bash` from the terminal (let's call it `terminal 1`). There we'll find `prepare_env.sh` script inside the `libs/connect_to_python_server/` directory. The script can be used to generate and connect the namespaces quickly. This essentially automates the process entailed [here](https://dev.to/umarfchy/connecting-linux-network-namespaces-with-veth-4cfk). Once we run the script, we'll have two namespaces with the following specifications -

| Namespace | veth Interface | Gateway IP |
| :-------: | :------------: | :--------: |
|    ns1    |      n1e       | 10.10.1.1  |
|    ns2    |      n2e       | 10.10.2.1  |

<h3 align="center"> Table 1 - Specifications of Created Network Namespaces</h3>

Now, we'll spin up the python server on `ns1` namespace and bind the gateway IP with the server using 👉 `python -m http.server <PORT> --bind <GATEWAY_IP>` in the current terminal (let's call it `terminal 1`). As the gateway IP for `n1e` is `10.10.1.1` we'll use the command 👇 to spin up the server

```bash
ip netns exec "ns1" python3 -m http.server 9000 --bind 10.10.1.1
```


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/469wxhyk23bh9c0w2gm8.png)

Fig.1 - Starting the python server

Now, let's open up another terminal and access the docker env `docker run exec -it network-companion bash`. Now, connect to the python server using `telnet` as follows

```bash
ip netns exec "ns2" telnet 10.10.1.1 9000
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oii10d46g1srn0wl8oc6.png)
Fig.2 - Making request using telnet

If we can see similar to Fig.2 in our terminal then we're connected to the server.

Now, let's make an HTTP request to the python server by typing the following to the cli -

```bash
GET / HTTP/1.0
Host: 10.10.1.1
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vlzpuoa641sf2sangrzt.png)
Fig.3 - Requesting using HTTP protocol

Once we request by pressing the enter key, we can see that the server responds with HTML which essentially lists out the contents in the directory -


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wkkn6kg4mqffvhrib4xv.png)
Fig.4 - Response on HTTP request

We can also see the logs of the python server on `terminal 1` -

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ghwalave78st7wt1l6oy.png)
Fig.5 - Logs of Python Server (1) 

Let's create the telnet connection again and make a request to the python server that does not comply with the HTTP protocol. This will result in an error response with HTML as follows -


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/idgmyoc6gdhwtwhnw1tf.png)
Fig.6 - Error response on improper request

We can again check the logs in `terminal 1` -


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ht008vg0twprwum6mcmg.png)
Fig.7 - Logs of Python Server (2) 

This marks the end of our experiment! Keep exploring the network namespaces and thanks for reading.