Linux Namespace

Linux通过命名空间这种概念来把进程或者网络区分开来,让他们之间彼此感受不到对方的存在,Docker里面也使用了这种技术,之前一直不理解Docker的鲸鱼有什么意义,现在稍微理解了一些:鲸鱼就是共享的资源,操作系统,而上面的箱子则代表了各个Docker或者namespace。我们可以把一个独立的namespace看做一台计算机。

Network Namespace

不同的network namespace 里面有着自己的路由表,自己的设备,自己的iptables等规则。不同的network namespace里面是不能看到其他namespace里面的设备的【就相当于两台电脑如果没有线缆之类的物理介质连接,是不能相互通讯的】,我们可以使用下面的命令来创建一个network namespace

创建network namespace

sudo ip netns add nstest

现在我们就有了一台“独立的”机器,那么如何让两个不同的namespace之间通讯呢?那就需要下面说的veth pair。

veth pair

Linux里面有几种虚拟网络:veth pair 相当于虚拟网卡对,跟IPC里面的管道类似。bridge:相当于虚拟交换机。现在我的环境是这样的:
这里写图片描述

可以看到现在两个namespace还是不通的,我们需要“买”两张网卡来让这两台机器互通:

创建veth pair

sudo ip link add veth-a type veth peer name veth-b

这样我们就获得了两块虚拟的网卡:

这里写图片描述

接着我们把veth-b加入到我们新创建的network namespace里面:

把veth-b加入到 nstest namespace

sudo ip link set veth-b netns nstest

这里写图片描述

现在还是不能ping通两块虚拟网卡:因为我们没有加上IP :

给两块虚拟网卡加IP,并且启动两块网卡

sudo ip addr add 10.0.0.2 dev veth-a && sudo ip link set veth-a up
sudo ip netns exec nstest ip addr add 10.0.0.3 dev veth-b && sudo ip netns exec nstest ip link set veth-b up

两块网卡必须要在同一个网段里面

现在还是不能ping通:因为nstest namespace里面的路由表没有设置。

添加路由

sudo ip netns exec nstest route add -net default gw 10.0.0.2 dev veth-b
sudo route add -host 10.0.0.3 dev veth-a

现在两张网卡就能ping通了,并且veth-b也可以ping通eth0

那么现在veth-b如何访问外网呢?那么就需要在host这边做nat转发,需要用到iptables这个工具。

开启host的路由转发功能

cat 1 > /proc/sys/net/ipv4/ip_forward

让eth0 转发 veth-a的包

sudo iptables -A FORWARD -t filter --out-interface eth0 --in-interface veth-a
sudo iptables -A FORWARD -t filter --in-interface eth0 --out-interface veth-a

添加nat转发功能

sudo iptables -t nat -A POSTROUTING --source 10.0.0.0/24 --out-interface eth0 -j MASQUERADE

这一句的意思是:让源目的IP为10.0.0.0/24的包都经过eth0这个接口nat出去,MASQUERADE是伪装的意思,意味着eth0会修改包的src IP(SNAT)。

现在就能使用veth-b这块虚拟网卡来访问外网了:

sudo ip netns exec nstest curl www.baidu.com

这里写图片描述

主要的知识点

1.虚拟网卡
2.nat
3.iptables
4.路由表
5.虚拟网络
6.docker

额外链接

1.iptables
2.另外一篇类似文章

Logo

更多推荐