WEBVTT

00:00.090 --> 00:01.940
Hello. Welcome to this video. 

00:02.260 --> 00:06.740
In this video, we get introduced 
to Network Namespaces in Linux. 

00:07.290 --> 00:10.110
Network namespaces are used by containers 

00:10.260 --> 00:13.780
like Docker to implement 
network isolation. 

00:13.880 --> 00:15.790
We'll start with a simple host. 

00:15.890 --> 00:18.780
As we know already, 
containers are separated

00:18.840 --> 00:21.780
 from the underlying host
 using namespaces.

00:22.010 --> 00:23.800
What are namespaces? 

00:23.850 --> 00:25.730
If your host was your house, 

00:25.800 --> 00:29.030
then namespaces are the rooms
 within the house

00:29.150 --> 00:31.230
 that you assign to each of your children.

00:31.350 --> 00:34.800
The room helps in providing privacy 
to each child.

00:35.110 --> 00:39.030
 Each child can only see
 what's within his or her room. 

00:39.460 --> 00:42.100
They cannot see what happens 
outside their room.

00:42.230 --> 00:45.780
 As far as they're concerned, they're
 the only person living in the house.

00:46.000 --> 00:50.740
However, as a parent, you have 
visibility into all the rooms in the house

00:50.810 --> 00:53.120
as well as other areas of the house. 

00:53.350 --> 00:55.990
If you wish, 
you can establish connectivity

00:56.040 --> 00:57.860
between two rooms in the house.

00:57.920 --> 00:59.590
When you create a container,

00:59.790 --> 01:02.030
 you want to make sure
 that it is isolated,

01:02.170 --> 01:04.950
that it does not see any other processes 

01:05.140 --> 01:07.280
on the host or any other containers. 

01:07.380 --> 01:09.400
We create a special room for it 

01:09.720 --> 01:11.980
on our host using a namespace.

01:12.200 --> 01:14.470
 As far as the container is concerned, 

01:14.580 --> 01:17.380
it only sees the processes run by it 

01:17.490 --> 01:20.110
and thinks that it is on its own host. 

01:20.260 --> 01:23.020
The underlying host, however, 
has visibility 

01:23.060 --> 01:27.020
into all of the processes including 
those running inside the containers.

01:27.180 --> 01:31.170
This can be seen when you list 
the processes from within the container. 

01:31.390 --> 01:34.460
You see a single process 
with the process ID of one. 

01:34.650 --> 01:39.220
When you list the same processes
 as a root user from the underlying host, 

01:39.410 --> 01:42.480
you see all the other processes
 along with the process

01:42.530 --> 01:46.010
 running inside the container,
 this time with a different process ID. 

01:46.070 --> 01:49.630
It's the same process running
 with different process IDs 

01:49.710 --> 01:51.530
inside and outside the container. 

01:51.720 --> 01:53.580
That's how namespaces work.

01:55.200 --> 01:56.950
When it comes to networking, 

01:57.050 --> 02:01.310
our host has its own interfaces 
that connect to the local area network. 

02:01.390 --> 02:05.330
Our host has its own routing 
and ARP tables with information

02:05.410 --> 02:06.720
 about the rest of the network. 

02:06.800 --> 02:09.990
We want to seal all of those details 
from the container.

02:11.240 --> 02:12.900
 When the container is created, 

02:12.970 --> 02:15.280
we create a network namespace for it, 

02:15.390 --> 02:17.320
that way, it has no visibility 

02:17.400 --> 02:20.750
to any network-related information
 on the host.

02:21.560 --> 02:26.460
Within its namespace, the container
 can have its own virtual interfaces 

02:26.500 --> 02:27.970
routing and ARP tables.

02:28.310 --> 02:30.750
 The container has its own interface.

02:31.950 --> 02:35.080
 To create a new network namespace 
on a Linux host, 

02:35.590 --> 02:38.280
run the ip netns add command. 

02:38.780 --> 02:42.320
In this case, we create 
two network namespaces. 

02:42.460 --> 02:46.590
To list the network namespaces, 
run the ip netns command. 

02:47.990 --> 02:50.150
To list the interfaces on my host,

02:50.240 --> 02:52.360
 I run the ip link command. 

02:52.420 --> 02:56.350
I see that my host has the loopback 
interface and the eth0 interface.

02:56.490 --> 02:59.510
Now, how do we view the same 
within the network namespace

02:59.570 --> 03:00.650
 that we created? 

03:00.740 --> 03:04.280
How do we run the same command
 within the red or blue namespace? 

03:04.370 --> 03:08.760
Prefix the command 
with the command ip netns exec 

03:08.890 --> 03:11.300
followed by the namespace name, 
which is red.

03:11.440 --> 03:16.190
 Now the ip link command will be executed
 inside the red namespace. 

03:16.310 --> 03:19.550
Another way to do it
 is to add the -n option

03:19.650 --> 03:21.710
to the original ip link command. 

03:21.860 --> 03:23.320
Both of these are the same.

03:23.460 --> 03:25.600
The second one is similar but remember, 

03:25.680 --> 03:28.700
this only works if you 
intend to run the ip command

03:28.760 --> 03:30.140
 inside the namespace. 

03:30.290 --> 03:33.370
As you can see,
 it only lists the loopback interface.

03:33.420 --> 03:36.150
 You cannot see the eth0 interface 
on the host.

03:36.340 --> 03:39.810
 With namespaces, we have
 successfully prevented the container

03:39.920 --> 03:41.850
 from seeing the host's interface. 

03:42.130 --> 03:44.080
The same is true with the ARP table. 

03:44.190 --> 03:46.330
If you run the arp command on the host, 

03:46.380 --> 03:50.060
you see a list of entries, 
but if you run it inside the container,

03:50.240 --> 03:52.000
 you see no entries. 

03:55.230 --> 03:57.440
The same for routing table.

03:58.630 --> 04:01.230
Now, as of now, these network namespaces 

04:01.280 --> 04:03.210
have no network connectivity.

04:03.310 --> 04:05.320
 They have no interfaces of their own, 

04:05.420 --> 04:07.890
and they cannot see
 the underlying host network. 

04:07.990 --> 04:10.310
Let's first look at establishing 
connectivity

04:10.380 --> 04:12.500
 between the namespaces themselves. 

04:12.590 --> 04:15.580
Just like how we would connect 
two physical machines together

04:15.620 --> 04:19.170
 using a cable to an internet interface
 on each machine, 

04:19.250 --> 04:23.410
you can connect two namespaces 
together using a virtual ethernet pair

04:23.480 --> 04:24.640
 or a virtual cable.

04:24.680 --> 04:26.570
It's often referred to as a pipe, 

04:26.800 --> 04:31.370
but I like to call it a virtual cable
 with two interfaces on either ends. 

04:31.470 --> 04:33.660
To create the cable, run the ip link 

04:33.750 --> 04:36.210
add command with a type set to veth

04:36.450 --> 04:40.230
 and specify the two ends, 
veth red and veth blue. 

04:40.390 --> 04:44.410
The next step is to attach each interface
 to the appropriate namespace. 

04:44.680 --> 04:48.130
Use the command ip link set veth red, 

04:48.300 --> 04:50.470
netns red to do that. 

04:50.720 --> 04:54.440
Similarly, attach the blue interface
 to the blue namespace.

04:54.520 --> 04:58.460
We can then assign IP addresses 
to each of these namespaces. 

04:58.570 --> 05:02.750
We will use the usual ip addr command
 to assign the IP address

05:02.810 --> 05:04.850
 but within each namespace. 

05:04.950 --> 05:09.790
We will assign the red namespace 
an IP 192.168.15.1. 

05:09.900 --> 05:14.660
We then assign the blue namespace 
an IP 192.168.15.2.

05:14.800 --> 05:17.160
 We then bring up the interface 
using the ip link

05:17.350 --> 05:21.300
 set up command for each device 
within their respective namespaces.

05:21.640 --> 05:25.050
 The links are up and the namespaces 
can now reach each other. 

05:25.130 --> 05:28.640
Try a ping from the red namespace
 to reach the IP of the blue.

05:28.750 --> 05:31.280
If you look at the ARP table 
on the red namespace,

05:31.320 --> 05:36.600
you see it's identified its blue neighbor
 at 192.168.15.2 

05:36.670 --> 05:37.800
with the MAC address. 

05:37.840 --> 05:40.770
Similarly, if you list the ARP table 
on the blue namespace, 

05:40.870 --> 05:43.240
you'll see it's identified 
its red neighbor. 

05:43.480 --> 05:45.970
If you compare this 
with the ARP table of the host,

05:46.020 --> 05:48.770
 you'll see that the host ARP table
 has no idea 

05:48.850 --> 05:51.150
about these new namespaces we have created

05:51.260 --> 05:54.500
 and no idea about the interfaces 
we created in them.

05:55.500 --> 05:57.880
Now, that worked when 
you had just two namespaces. 

05:57.980 --> 05:59.640
What do you do when you have more of them?

05:59.800 --> 06:02.570
 How do you enable all of them 
to communicate with each other? 

06:02.620 --> 06:04.120
Just like in the physical world, 

06:04.330 --> 06:07.000
you create a virtual network 
inside your host. 

06:07.070 --> 06:09.050
To create a network, you need a switch. 

06:09.230 --> 06:12.430
To create a virtual network,
 you need a virtual switch. 

06:12.570 --> 06:17.190
You create a virtual switch within 
a host and connect the namespaces to it.

06:17.280 --> 06:19.540
How do you create 
a virtual switch within a host?

06:19.580 --> 06:22.590
 There are multiple solutions available
 such as the native solution 

06:22.750 --> 06:24.480
called as Linux Bridge 

06:24.620 --> 06:26.960
and the open vSwitch, et cetera. 

06:27.060 --> 06:29.890
In this example, 
we will use the Linux Bridge option. 

06:29.970 --> 06:32.000
To create an internal bridge network,

06:32.120 --> 06:36.400
 we add a new interface to the host 
using the ip link add command 

06:36.630 --> 06:38.470
with the type set to bridge.

06:38.840 --> 06:40.580
 We will name it v-net-0.

06:40.730 --> 06:42.750
As far as our host is concerned,

06:42.860 --> 06:44.840
 it is just another interface

06:45.070 --> 06:46.940
 just like the eth0 interface. 

06:47.230 --> 06:50.150
It appears
 in the output of the ip link command 

06:50.320 --> 06:52.220
along with the other interfaces. 

06:52.360 --> 06:54.500
It's currently down
 so you need to turn it up. 

06:54.550 --> 06:57.500
Use the ip link set dev up command
 to bring it up.

06:57.680 --> 07:01.080
Now, for the namespaces, 
this interface is like a switch

07:01.150 --> 07:02.380
 that it can connect to. 

07:02.420 --> 07:04.960
Think of it as an interface 
for the host 

07:05.050 --> 07:06.790
and a switch for the namespaces.

07:06.840 --> 07:09.890
The next step is to connect 
the namespaces 

07:09.950 --> 07:11.830
to this new virtual network switch. 

07:11.900 --> 07:14.720
Earlier, we created the cable 
or the eth pair 

07:14.800 --> 07:18.290
with the veth-red interface on one end
 and blue interface

07:18.380 --> 07:22.010
 on the other because we wanted 
to connect the two namespaces directly. 

07:22.260 --> 07:25.920
Now, we will be connecting all namespaces
 to the bridge network. 

07:26.220 --> 07:28.390
We need new cables for that purpose. 

07:28.640 --> 07:30.690
This cable doesn't make sense anymore, 

07:30.730 --> 07:31.770
so we will get rid of it.

07:31.860 --> 07:34.940
Use the ip link delete command
 to delete the cable. 

07:35.030 --> 07:37.540
When you delete the link with one end, 

07:37.640 --> 07:40.670
the other end gets deleted automatically
 since they are a pair. 

07:40.820 --> 07:42.950
This does now create new cables 

07:43.030 --> 07:44.950
to connect the namespaces to the bridge. 

07:45.160 --> 07:48.560
Run the ip link add command 
and create a pair

07:48.640 --> 07:51.770
 with veth-red on one end
 like before, but this time 

07:51.940 --> 07:55.340
the other end will be named veth-red-br 

07:55.540 --> 07:57.470
as it connects to the bridge network. 

07:57.630 --> 08:01.440
This naming convention will help us
 easily identify the interfaces

08:01.520 --> 08:03.780
 that associate to the red namespace. 

08:03.830 --> 08:06.680
Similarly, create a cable 
to connect the blue namespace

08:06.790 --> 08:08.030
 to the bridge network.

08:08.110 --> 08:09.760
Now that we have the cables ready,

08:09.830 --> 08:12.040
 it's time to get them connected
 to the namespaces. 

08:12.180 --> 08:15.570
To attach one end of the interface
 to the red namespace,

08:15.680 --> 08:19.640
 run the IP link set veth-red 
netns red command. 

08:19.750 --> 08:22.480
To attach the other end 
to the bridge network,

08:22.720 --> 08:26.700
 run the IP link set command 
on the veth-red-br end 

08:26.770 --> 08:30.790
and specify the master for it 
as the v-net-0 network.

08:32.980 --> 08:35.290
 Follow the same procedure
 to attach the blue cable 

08:35.330 --> 08:37.950
to the blue namespace 
and the bridge network.

08:38.120 --> 08:41.810
Let us now set IP addresses 
for these links and turn them up.

08:42.010 --> 08:45.380
 We will use the same IP addresses
 that we used before, 

08:45.520 --> 08:50.510
192.168.15.1 and 192.168.15.2. 

08:50.580 --> 08:52.450
Finally, turn the devices up. 

08:52.560 --> 08:55.680
The containers can now 
reach each other over the network.

08:55.770 --> 08:59.090
 We follow the same procedure 
to connect the remaining two namespaces

08:59.160 --> 09:00.480
 to the same network.

09:00.770 --> 09:05.030
 We now have all four namespaces 
connected to our internal bridge network

09:05.130 --> 09:07.070
 and they can all communicate 
with each other.

09:07.360 --> 09:12.310
They have all IP addresses, 
192.168.15.1, 2, 3, and 4. 

09:12.350 --> 09:16.650
Remember, we assigned our host, 
the IP 192.168.1.2

09:16.740 --> 09:20.130
 From my host, what if I tried
 to reach one of these interfaces 

09:20.270 --> 09:21.720
in these namespaces? 

09:21.780 --> 09:22.700
Would it work? 

09:22.830 --> 09:26.890
No. My host is on one network 
and the namespaces are on another. 

09:26.910 --> 09:29.300
What if I really want to establish
 connectivity 

09:29.360 --> 09:31.670
between my host and these namespaces? 

09:32.110 --> 09:35.960
Remember, we said that the bridge switch
 is actually a network interface 

09:36.020 --> 09:36.950
for the host.

09:37.000 --> 09:41.500
We do have an interface 
on the 192.168.15 network on our host.

09:41.770 --> 09:44.400
 Since it's just another interface,
 all we need to do 

09:44.520 --> 09:46.290
is assign an IP address to it 

09:46.420 --> 09:48.710
so we can reach the namespaces through it.

09:48.780 --> 09:55.200
Run the ip addr command to set 
the IP 192.168.15.5 to this interface.

09:55.650 --> 09:58.900
 We can now ping the red namespace
 from our localhost.

09:59.210 --> 10:02.680
Now, remember, this entire network 
is still private 

10:02.810 --> 10:04.670
and restricted within the host.

10:05.140 --> 10:08.020
From within the namespaces, 
you can't reach the outside world, 

10:08.100 --> 10:09.970
nor can anyone from the outside world 

10:10.030 --> 10:12.830
reach the services or applications
 hosted inside. 

10:12.920 --> 10:17.180
The only door to the outside world
 is the internet port on the host. 

10:17.420 --> 10:20.540
How do we configure this bridge 
to reach the LAN network 

10:20.760 --> 10:22.060
through the ethernet port?

10:22.160 --> 10:24.510
 Say there is another host attached 
to our LAN network 

10:24.550 --> 10:27.220
with the address 192.168.1.3,

10:27.700 --> 10:30.860
 how can I reach this host 
from within my namespaces?

10:30.900 --> 10:34.360
What happens if I try to ping this host 
from my blue namespace?

10:34.410 --> 10:39.840
 The blue namespace sees that I'm trying
 to reach a network at 192.168.1, 

10:39.890 --> 10:44.590
which is different from my current network
 of 192.168.15. 

10:44.770 --> 10:48.080
It looks at its routing table
 to see how to find that network.

10:48.170 --> 10:51.210
 The routing table has no information 
about another network 

10:51.250 --> 10:54.120
so it comes back saying 
that the network is unreachable.

10:54.270 --> 10:56.710
We need to add an entry
 into the routing table

10:56.790 --> 11:00.270
 to provide a gateway 
or door to the outside world.

11:00.770 --> 11:02.400
How do we find in that gateway?

11:02.510 --> 11:05.280
 A door or a gateway, 
as we discussed before, 

11:05.370 --> 11:09.120
is a system on the local network 
that connects to the other network. 

11:09.280 --> 11:12.880
What is a system that has one interface
 on the network local 

11:12.950 --> 11:17.210
to the blue namespace,
 which is the 192.168.15 network, 

11:17.480 --> 11:20.260
and it's also connected
 to the outside LAN network? 

11:20.390 --> 11:21.540
Here's a logical view. 

11:21.650 --> 11:24.390
It's localhost that have 
all these namespaces on,

11:24.500 --> 11:26.430
so you can ping the namespaces.

11:26.500 --> 11:29.010
Remember our local host 
has an interface too

11:29.080 --> 11:32.190
 attached the private network 
so you can ping the namespaces. 

11:32.280 --> 11:36.190
Our local host is the gateway 
that connects the two networks together. 

11:36.370 --> 11:39.680
We can now add a route entry 
in the blue namespace 

11:39.770 --> 11:43.910
to say route all traffic
 to the 192.168.1 network 

11:44.030 --> 11:47.480
through the gateway at 192.168.15.5. 

11:47.620 --> 11:50.840
Now, remember, our host 
has two IP addresses, 

11:50.980 --> 11:54.680
one on the bridge network at 192.168.15.5 

11:54.770 --> 11:58.840
and another on the external network 
at 192.168.1.2.

11:58.950 --> 12:00.640
Can you use any in the route? 

12:00.770 --> 12:03.840
No, because the blue namespace 
can only reach the gateway 

12:03.980 --> 12:07.430
in its local network at 192.168.15.5. 

12:07.530 --> 12:10.950
The default gateway 
should be reachable from your namespace 

12:11.090 --> 12:12.390
when you add it to your route.

12:12.490 --> 12:13.930
 When you try to ping now, 

12:13.990 --> 12:16.390
you no longer get the network
 unreachable message,

12:16.470 --> 12:19.290
but you still don't get any response back 
from the ping. 

12:19.460 --> 12:20.970
What might be the problem?

12:21.010 --> 12:24.590
We talked about a similar situation
 in one of our earlier lectures, 

12:24.720 --> 12:28.650
were from our home network, 
we try to reach the external internet 

12:28.690 --> 12:29.570
through our router. 

12:29.650 --> 12:32.890
Our home network has
 our internal private IP addresses 

12:32.990 --> 12:35.190
that the destination network
 don't know about, 

12:35.250 --> 12:36.840
so they cannot reach back. 

12:36.880 --> 12:39.690
For this, we need NAT enabled on our host 

12:39.870 --> 12:41.420
acting as a gateway here

12:41.530 --> 12:43.720
 so that it can send the messages
 to the LAN 

12:43.820 --> 12:45.900
in its own name with its own address.

12:46.110 --> 12:48.680
How do we add NAT functionality
 to our host?

12:48.950 --> 12:50.970
You should do that using iptables. 

12:51.030 --> 12:53.300
Add a new rule in the NAT iptable

12:53.570 --> 12:56.360
 in the post-routing chain to masquerade

12:56.440 --> 13:00.450
 or replace the front address on all 
packets coming from the source network, 

13:00.840 --> 13:05.050
192.168.15.0 with its own IP address.

13:05.160 --> 13:08.290
 That way, anyone receiving
 these packets outside the network

13:08.320 --> 13:10.320
 will think that they're coming
 from the host

13:10.350 --> 13:12.330
 and not from within the namespaces. 

13:12.370 --> 13:15.090
When we try to ping now, 
we see that we are able to reach

13:15.150 --> 13:16.640
 the outside world.

13:17.770 --> 13:21.020
Finally, say the LAN 
is connected to the internet, 

13:21.280 --> 13:23.800
we want the namespaces 
to reach the internet.

13:23.890 --> 13:26.100
 We try to ping a server on the internet 

13:26.260 --> 13:29.530
at 8.8.8.8 from the blue namespace.

13:29.580 --> 13:32.300
 We receive a familiar message 
that the network is unreachable, 

13:32.470 --> 13:33.910
by now we know why that is.

13:34.010 --> 13:37.480
 We look at the routing table and see
 that we have routes to the network, 

13:37.560 --> 13:40.400
192.168.1 but not to anything else. 

13:40.490 --> 13:44.230
Since these namespaces can reach
 any network our host can reach, 

13:44.310 --> 13:47.280
we can simply say that to reach
 any external network, 

13:47.690 --> 13:51.950
talk to our host so we add 
a default gateway specifying our host.

13:52.110 --> 13:54.570
 We should now be able 
to reach the outside world 

13:54.760 --> 13:56.800
from within these namespaces.

13:57.670 --> 14:00.930
Now, what about connectivity
 from the outside world

14:00.970 --> 14:02.630
 to inside the namespaces? 

14:02.730 --> 14:07.260
Say, for example, the blue namespace 
hosts a web application on port 80. 

14:07.330 --> 14:11.430
As of now, the namespaces are 
on an internal private network 

14:11.480 --> 14:14.100
and no one from the outside world
 knows about them. 

14:14.200 --> 14:16.650
You can only access these 
from the host itself. 

14:16.690 --> 14:19.140
If you try to ping the private
 IP of the namespace 

14:19.190 --> 14:21.530
from another host on another network, 

14:21.630 --> 14:23.310
you will see that it's not reachable. 

14:23.400 --> 14:27.300
Obviously, because that host 
doesn't know about this private network.

14:27.350 --> 14:29.670
In order to make 
that communication possible, 

14:29.800 --> 14:31.140
you have two options, 

14:31.200 --> 14:34.530
the two options that we saw
 in the previous lecture on NAT. 

14:34.610 --> 14:37.750
The first is to give away 
the identity of the private network 

14:37.850 --> 14:38.750
to the second host. 

14:38.830 --> 14:42.630
We basically add 
an ip route entry to the second host 

14:42.700 --> 14:46.060
telling the host that
 the network 192.168.15

14:46.330 --> 14:50.380
 can be reached 
through the host at 192.168.1.2

14:50.460 --> 14:51.720
 but we don't want to do that. 

14:51.790 --> 14:55.360
The other option is to add 
a port forwarding role 

14:55.430 --> 14:59.860
using iptables to say any traffic
 coming to port 80 

14:59.950 --> 15:03.060
on the local host 
is to be forwarded to port 80

15:03.410 --> 15:06.100
on the IP assigned to the blue namespace.

15:06.210 --> 15:07.890
 Well, that's it for this video. 

15:08.170 --> 15:09.310
Thank you for watching.

