<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Umar Chowdhury</title>
    <description>The latest articles on DEV Community by Umar Chowdhury (@umarfchy).</description>
    <link>https://dev.to/umarfchy</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F966026%2Fdded198b-63c9-4eba-91f5-cb90108872d1.jpeg</url>
      <title>DEV Community: Umar Chowdhury</title>
      <link>https://dev.to/umarfchy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/umarfchy"/>
    <language>en</language>
    <item>
      <title>Connect to an HTTP Server Residing on a Separate Namespace</title>
      <dc:creator>Umar Chowdhury</dc:creator>
      <pubDate>Sun, 20 Nov 2022 17:42:52 +0000</pubDate>
      <link>https://dev.to/umarfchy/connect-to-a-http-server-residing-on-separate-namespace-168f</link>
      <guid>https://dev.to/umarfchy/connect-to-a-http-server-residing-on-separate-namespace-168f</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Namespace&lt;/th&gt;
&lt;th&gt;veth Interface&lt;/th&gt;
&lt;th&gt;Gateway IP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ns1&lt;/td&gt;
&lt;td&gt;n1e&lt;/td&gt;
&lt;td&gt;10.10.1.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ns2&lt;/td&gt;
&lt;td&gt;n2e&lt;/td&gt;
&lt;td&gt;10.10.2.1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt; Table 1 - Specifications of Created Network Namespaces&lt;/h3&gt;

&lt;p&gt;Now, we'll spin up the python server on &lt;code&gt;ns1&lt;/code&gt; namespace and bind the gateway IP with the server using 👉 &lt;code&gt;python -m http.server &amp;lt;PORT&amp;gt; --bind &amp;lt;GATEWAY_IP&amp;gt;&lt;/code&gt; in the current terminal (let's call it &lt;code&gt;terminal 1&lt;/code&gt;). As the gateway IP for &lt;code&gt;n1e&lt;/code&gt; is &lt;code&gt;10.10.1.1&lt;/code&gt; we'll use the command 👇 to spin up the server&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip netns &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="s2"&gt;"ns1"&lt;/span&gt; python3 &lt;span class="nt"&gt;-m&lt;/span&gt; http.server 9000 &lt;span class="nt"&gt;--bind&lt;/span&gt; 10.10.1.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PYYEa7RN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/469wxhyk23bh9c0w2gm8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PYYEa7RN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/469wxhyk23bh9c0w2gm8.png" alt="Image description" width="880" height="81"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fig.1 - Starting the python server&lt;/p&gt;

&lt;p&gt;Now, let's open up another terminal and access the docker env &lt;code&gt;docker run exec -it network-companion bash&lt;/code&gt;. Now, connect to the python server using &lt;code&gt;telnet&lt;/code&gt; as follows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip netns &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="s2"&gt;"ns2"&lt;/span&gt; telnet 10.10.1.1 9000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xa24T2Ky--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oii10d46g1srn0wl8oc6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xa24T2Ky--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oii10d46g1srn0wl8oc6.png" alt="Image description" width="845" height="139"&gt;&lt;/a&gt;&lt;br&gt;
Fig.2 - Making request using telnet&lt;/p&gt;

&lt;p&gt;If we can see similar to Fig.2 in our terminal then we're connected to the server.&lt;/p&gt;

&lt;p&gt;Now, let's make an HTTP request to the python server by typing the following to the cli -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;GET / HTTP/1.0
Host: 10.10.1.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y9k47F_G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vlzpuoa641sf2sangrzt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y9k47F_G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vlzpuoa641sf2sangrzt.png" alt="Image description" width="880" height="175"&gt;&lt;/a&gt;&lt;br&gt;
Fig.3 - Requesting using HTTP protocol&lt;/p&gt;

&lt;p&gt;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 -&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VpFLKKb8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wkkn6kg4mqffvhrib4xv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VpFLKKb8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wkkn6kg4mqffvhrib4xv.png" alt="Image description" width="839" height="614"&gt;&lt;/a&gt;&lt;br&gt;
Fig.4 - Response on HTTP request&lt;/p&gt;

&lt;p&gt;We can also see the logs of the python server on &lt;code&gt;terminal 1&lt;/code&gt; -&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vjekKlOL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ghwalave78st7wt1l6oy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vjekKlOL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ghwalave78st7wt1l6oy.png" alt="Image description" width="880" height="104"&gt;&lt;/a&gt;&lt;br&gt;
Fig.5 - Logs of Python Server (1) &lt;/p&gt;

&lt;p&gt;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 -&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zroKPgOh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/idgmyoc6gdhwtwhnw1tf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zroKPgOh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/idgmyoc6gdhwtwhnw1tf.png" alt="Image description" width="880" height="407"&gt;&lt;/a&gt;&lt;br&gt;
Fig.6 - Error response on improper request&lt;/p&gt;

&lt;p&gt;We can again check the logs in &lt;code&gt;terminal 1&lt;/code&gt; -&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--26rarJKQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ht008vg0twprwum6mcmg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--26rarJKQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ht008vg0twprwum6mcmg.png" alt="Image description" width="880" height="52"&gt;&lt;/a&gt;&lt;br&gt;
Fig.7 - Logs of Python Server (2) &lt;/p&gt;

&lt;p&gt;This marks the end of our experiment! Keep exploring the network namespaces and thanks for reading.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>devops</category>
      <category>networking</category>
      <category>sre</category>
    </item>
    <item>
      <title>Connecting Linux Network Namespaces with Virtual Ethernet (veth)</title>
      <dc:creator>Umar Chowdhury</dc:creator>
      <pubDate>Sat, 19 Nov 2022 18:50:55 +0000</pubDate>
      <link>https://dev.to/umarfchy/connecting-linux-network-namespaces-with-veth-4cfk</link>
      <guid>https://dev.to/umarfchy/connecting-linux-network-namespaces-with-veth-4cfk</guid>
      <description>&lt;p&gt;Linux network namespace is a kernel feature that provides isolation of the system resources associated with network. In this article I'll show you how to create and connect two network namespaces in Linux. This is article is part of a &lt;a href="https://github.com/umarfchy/playing-with-linux-network-namespaces"&gt;personal project&lt;/a&gt; where I tried to explore different aspects of network namespaces in Linux. Let's start. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Please prefix following commands with &lt;code&gt;sudo&lt;/code&gt; if we're not logged in as a root user.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's start by creating two new network namespaces using the terminal (let's call it &lt;code&gt;terminal 1&lt;/code&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip netns add &lt;span class="s2"&gt;"ns1"&lt;/span&gt;
ip netns add &lt;span class="s2"&gt;"ns2"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can use the following command to list the existing namespaces. Here, we should both &lt;code&gt;n1s&lt;/code&gt; &amp;amp; &lt;code&gt;n2s&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip netns list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Afterward, let's create a &lt;code&gt;veth&lt;/code&gt; cable with two interfaces &lt;code&gt;n1e&lt;/code&gt; and &lt;code&gt;n2e&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip &lt;span class="nb"&gt;link &lt;/span&gt;add &lt;span class="s2"&gt;"n1e"&lt;/span&gt; &lt;span class="nb"&gt;type &lt;/span&gt;veth peer name &lt;span class="s2"&gt;"n2e"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see details about the interfaces using the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip addr list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's connect the two namespaces with the &lt;code&gt;veth&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip &lt;span class="nb"&gt;link set&lt;/span&gt; &lt;span class="s2"&gt;"n1e"&lt;/span&gt; netns &lt;span class="s2"&gt;"ns1"&lt;/span&gt;
ip &lt;span class="nb"&gt;link set&lt;/span&gt; &lt;span class="s2"&gt;"n2e"&lt;/span&gt; netns &lt;span class="s2"&gt;"ns2"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Interestingly enough, if we now type &lt;code&gt;ip addr list&lt;/code&gt; in the terminal, the &lt;code&gt;n1e&lt;/code&gt; &amp;amp; &lt;code&gt;n2e&lt;/code&gt; will be missing! Where are they, we ask? The interfaces are now inside the respective namespaces they are assigned with. So, to see them again we are required to get inside a namespace. Let's start with &lt;code&gt;ns1&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;We can now enter inside the &lt;code&gt;ns1&lt;/code&gt; using the following command -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip netns &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="s2"&gt;"ns1"&lt;/span&gt; bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're in! Now, if we type &lt;code&gt;ip addr list&lt;/code&gt;, it will show two interfaces &lt;code&gt;lo&lt;/code&gt; and &lt;code&gt;n1e&lt;/code&gt;, both in the &lt;code&gt;DOWN&lt;/code&gt; state. Let's test the connection &lt;code&gt;ping localhost&lt;/code&gt;. This should give an error with the message &lt;code&gt;ping: connect: Cannot assign requested address&lt;/code&gt;. We need to set the state up as follows to make the ping connection work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip &lt;span class="nb"&gt;link set &lt;/span&gt;dev lo up 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ping localhost&lt;/code&gt; will start working. &lt;/p&gt;

&lt;p&gt;Now let's assign the IP address to the interface of each side of the &lt;code&gt;veth&lt;/code&gt; cable starting with &lt;code&gt;n1e&lt;/code&gt;. We're required to provide the CIDR notation for the address. Also, let's bring &lt;code&gt;UP&lt;/code&gt; the &lt;code&gt;n1e&lt;/code&gt; interface&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip addr add 10.10.1.1/32 dev &lt;span class="s2"&gt;"n1e"&lt;/span&gt;
ip &lt;span class="nb"&gt;link set &lt;/span&gt;dev &lt;span class="s2"&gt;"n1e"&lt;/span&gt; up 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's open up another terminal (&lt;code&gt;terminal 2&lt;/code&gt;) and enter the &lt;code&gt;ns2&lt;/code&gt; namespace as follows -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip netns &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="s2"&gt;"ns2"&lt;/span&gt; bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we bring up the &lt;code&gt;lo&lt;/code&gt; and &lt;code&gt;n2e&lt;/code&gt; interfaces and also assign IP to &lt;code&gt;n2e&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip &lt;span class="nb"&gt;link set &lt;/span&gt;dev lo up 
ip addr add 10.10.2.1/32 dev &lt;span class="s2"&gt;"n2e"&lt;/span&gt;
ip &lt;span class="nb"&gt;link set &lt;/span&gt;dev &lt;span class="s2"&gt;"n2e"&lt;/span&gt; up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, now if we try &lt;code&gt;ping -I n1e 10.10.2.1&lt;/code&gt; from &lt;code&gt;terminal 1&lt;/code&gt; and listen to the incoming request on &lt;code&gt;terminal 2&lt;/code&gt; using &lt;code&gt;tcpdump -v -i n2e&lt;/code&gt;, we will see message &lt;code&gt;IP 10.10.1.1 &amp;gt; 10.10.2.1: ICMP echo request&lt;/code&gt;. This ensures that the request is coming to &lt;code&gt;ns2&lt;/code&gt;. However, we do not see anything in &lt;code&gt;terminal 1&lt;/code&gt;. This suggests that no packet is getting out from &lt;code&gt;ns2&lt;/code&gt; namespace. This is because the &lt;code&gt;ns2&lt;/code&gt; doesn't know where to send the response to or, in other words, how to route the packets. We can fix this by adding an entry in the &lt;code&gt;route table&lt;/code&gt; on &lt;code&gt;ns2&lt;/code&gt;.    &lt;/p&gt;

&lt;p&gt;To specify the &lt;code&gt;route table&lt;/code&gt; we can do as follows -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip route add default via 10.10.2.1 dev &lt;span class="s2"&gt;"n2e"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll see a response in &lt;code&gt;terminal 1&lt;/code&gt; now. &lt;/p&gt;

&lt;p&gt;Here is a question, what would happen if we do not explicitly define the interface while making the ICMP request i.e. &lt;code&gt;ping 10.10.2.1&lt;/code&gt; this will show &lt;code&gt;ping: connect: Network is unreachable&lt;/code&gt;. This is also a routing problem. To fix this just add the following in &lt;code&gt;ns1&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip route add default via 10.10.1.1 dev &lt;span class="s2"&gt;"n1e"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can ping without explicitly defining the interface. Awesome, right?&lt;/p&gt;

&lt;p&gt;Keep playing with the network namespace and thanks for reading. &lt;/p&gt;

</description>
      <category>linux</category>
      <category>networking</category>
      <category>devops</category>
      <category>namespace</category>
    </item>
  </channel>
</rss>
