Linux Namespace : Network

Network namespace 在逻辑上是网络堆栈的一个副本,它有本身的路由、防火墙规则和网络设备。默认状况下,子进程继承其父进程的 network namespace。也就是说,若是不显式建立新的 network namespace,全部进程都从 init 进程继承相同的默认 network namespace。html

每一个新建立的 network namespace 默认有一个本地环回接口 lo,除此以外,全部的其余网络设备(物理/虚拟网络接口,网桥等)只能属于一个 network namespace。每一个 socket 也只能属于一个 network namespace。linux

说明:本文的演示环境为 ubuntu 16.04。docker

ip netns 命令
ip netns 命令用来管理 network namespace。本文将使用 ip netns 命令来建立和操做 network namespace。有关 ip netns 命令的详细介绍请参考笔者的博文《Linux ip netns 命令》。ubuntu

建立 network namespace

咱们先查一下看默认的 network namespace 的 ID:segmentfault

$ readlink /proc/$$/ns/net

而后经过 ip netns add 命令建立名为 mynet 的 network namespace:bash

$ sudo ip netns add mynet

从上图能够看出,在名为 mynet 的 network namespace 建立成功后,/var/run/netns 目录下多了一个名为 mynet 文件。ip netns exec 子命令能够在对应的 network namespace 中执行命令,下面咱们就经过它在 mynet network namespace 中建立一个 bash 进程,并查看 network namespace 的 ID:网络

$ sudo ip netns exec mynet bash
# readlink /proc/$$/ns/net

这是一个彻底不一样的 network namespace ID,说明当前的 bash 进程运行在一个隔离的 network 环境中。接下来让咱们看看新的 network namespace 中都有什么:socket

# ip addr

每一个新建立的 network namespace 默认有一个本地环回接口 lo,而且这个接口是处于关闭状态的。下面咱们就启动这个接口:spa

# ip link set lo up

启动 lo 接口后咱们能够看到其 IP 地址,而且可以正确的响应 ping 命令。3d

在两个 network namespace 之间通讯

network namespace 之间是相互隔离的,咱们可使用 veth 设备把两个 network namespace 链接起来进行通讯。veth 设备是虚拟的以太网设备。它们能够充当 network namespace 之间的通道,也能够做为独立的网络设备使用。veth 设备老是被成对的建立,而且这一对设备老是链接在一块儿的,因此通常把称之为 veth pair。须要注意的是,veth pair 没法单独存在,删除其中一个,另外一个也会自动消失。接下来的示例咱们就演示如何使用 veth pair 在两个 network namespace 直接通讯。示例中咱们使用 ip link 命令来建立和管理 veth pair。

第一步,先建立两个 network namespace net0 和 net1

$ sudo ip netns add net0
$ sudo ip netns add net1

第二步,建立一对命名的 veth 设备
默认状况下会自动为 veth pair 生成名称,这里为了易于辨识,咱们在建立时指定 veth pair 的名称:

$ sudo ip link add vethmother type veth peer name vethfather

如图所示,veth pair 在主机上表现为两个网卡。

第三步,把这一对 veth pair 分别放到 network namespace net0 和 net1中

$ sudo ip link set vethmother netns net0
$ sudo ip link set vethfather netns net1
$ sudo ip netns exec net0 ip addr
$ sudo ip netns exec net1 ip addr

查看 net0 和 net1 中的网络资源,发现各自多了一个网卡,也就是 veth 设备的两个端点。注意,当咱们把 veth pair 分配到 network namespace 中后,在主机上就看不到它们了:

此时主机的网卡中已经看不到刚才的 veth pair 身影了。

第四步,给这些 veth pair 分配 IP 并启用它们

$ sudo ip netns exec net0 ip link set vethmother up
$ sudo ip netns exec net0 ip addr add 10.0.1.1/24 dev vethmother
$ sudo ip netns exec net0 ip route

$ sudo ip netns exec net1 ip link set vethfather up
$ sudo ip netns exec net1 ip addr add 10.0.1.2/24 dev vethfather
$ sudo ip netns exec net1 ip route

下面经过 ping 命令来验证两个 network namespace 是否能够通讯:

$ sudo ip netns exec net0 ping -c 3 10.0.1.2

至此,咱们构建了一个以下结构的虚拟网络:

经过 bridge 链接 network namespace

虽然 veth pair 能够实现两个 network namespace 之间的通讯,可是当须要在多个 network namespace 之间通讯的时候,光靠 veth pair 就不行了。咱们可使用 Linux 提供的虚拟交换机,来完成这样的功能。下面的示例演示如何经过虚拟交换机(这里就是一个虚拟网桥)链接多个 network namespace。

第一步,先添加一个叫 mybridge0 的网桥

$ sudo ip link add mybridge0 type bridge
$ sudo ip link set dev mybridge0 up
$ sudo ip addr

对主机来讲其实就是新添加了一个网络接口(network interface):

第二步,建立 network namespace 和 veth 设备
建立 network namespace net0:

$ sudo ip netns add net0

建立 veth 设备:

$ sudo ip link add veth0 type veth peer name veth0p 

把其中的一个 veth 放置到 net0 中,设置 IP 并启动它:

$ sudo ip link set dev veth0p netns net0
$ sudo ip netns exec net0 ip link set dev veth0p name eth0
$ sudo ip netns exec net0 ip addr add 10.0.1.1/24 dev eth0
$ sudo ip netns exec net0 ip link set dev eth0 up
$ sudo ip netns exec net0 ip addr

上图显示 network namespace net0 中的 eth0 网卡已经启动了。下面把 veth 设备的另外一端链接到网桥 mybridge0 上:

$ sudo ip link set dev veth0 master mybridge0
$ sudo ip link set dev veth0 up

第三步,重复第二步建立 net1 和 net2,并链接到网桥
给 mybridge0 设置 IP:

$ sudo ip link set dev mybridge0 down
$ sudo ip addr add 10.0.1.0/24 dev mybridge0
$ sudo ip link set dev mybridge0 up
$ ip addr

经过 bridge link 命令查看网桥的信息以下:

这时就能够在不一样的 network namespace 之间通讯了:

$ sudo ip netns exec net0 ping -c 3 10.0.1.3

咱们建立的网络拓扑结构以下所示:

总结

经过 network namespace 能够建立相互独立的网络栈,从而实现网络的隔离。本文只是简单的介绍了 network namespace 的建立以及如何在 network namespace 之间通讯,其中 network namespace 之间经过 bridge 通讯的方式已经与 docker 网络的 bridge 模式很是相似了。

参考:
Network namespace man page
Linux Namespace系列(06):network namespace (CLONE_NEWNET)
Network namespace 简介

相关文章
相关标签/搜索