网络命名空间
在 Linux 中,网络名字空间可以被认为是隔离的拥有单独网络栈(网卡、路由转发表、iptables)的环境。网络名字空间经常用来隔离网络设备和服务,只有拥有同样网络名字空间的设备,才能看到彼此。
●Bridge
Bridge和现实世界中的二层交换机有一个区别:数据被直接发到Bridge上,而不是从一个端口接受。这种情况可以看做Bridge自己有一个MAC可以主动发送报文,或者说Bridge自带了一个隐藏端口和寄主 Linux 系统自动连接,Linux 上的程序可以直接从这个端口向 Bridge 上的其他端口发数据。所以当一个 Bridge 拥有一个网络设备时,如 bridge0 加入了 eth0 时,实际上 bridge0 拥有两个有效 MAC 地址,一个是 bridge0 的,一个是 eth0 的,他们之间可以通讯。
由此带来一个有意思的事情是,Bridge 可以设置 IP 地址。通常来说 IP 地址是三层协议的内容,不应该出现在二层设备 Bridge 上。但是 Linux 里 Bridge 是通用网络设备抽象的一种,只要是网络设备就能够设定 IP 地址。当一个 bridge0 拥有 IP 后,Linux 便可以通过路由表或者IP表规则在三层定位bridge0,此时相当于Linux拥有了另外一个隐藏的虚拟网卡和 Bridge 的隐藏端口相连,这个网卡就是名为bridge0的通用网络设备,IP可以看成是这个网卡的。当有符合此 IP 的数据到达bridge0 时,内核协议栈认为收到了一包目标为本机的数据,此时应用程序可以通过 Socket接收到它。
一个更好的对比例子是:现实世界中的带路由的交换机设备,它也拥有一个隐藏的 MAC 地址,供设备中的三层协议处理程序和管理程序使用。设备里的三层协议处理程序,对应名为 bridge0 的通用网络设备的三层协议处理程序,即寄主Linux系统内核协议栈程序。设备里的管理程序,对应bridge0寄主Linux系统里的应用程序。
Bridge 的实现当前有一个限制:当一个设备被 attach 到 Bridge 上时,那个设备的 IP 会变的无效,Linux 不再使用那个 IP 在三层接受数据。举例如下:如果 eth0 本来的 IP 是 192.168.1.2,此时如果收到一个目标地址是 192.168.1.2 的数据,Linux 的应用程序能通过 Socket 操作接受到它。而当 eth0 被 attach 到一个 bridge0 时,尽管 eth0 的 IP 还在,但应用程序是无法接受到上述数据的。此时应该把 IP 192.168.1.2 赋予 bridge0。
另外需要注意的是:数据流的方向。对于一个被attach到Bridge上的设备来说,只有它收到数据时,此包数据才会被转发到Bridge上,进而完成查表广播等后续操作。当请求是发送类型时,数据是不会被转发到 Bridge 上的,它会寻找下一个发送出口。用户在配置网络时经常忽略这一点从而造成网络故障。
●TAP 设备与 VETH 设备
TUN/TAP 设备是一种让用户态程序向内核协议栈注入数据的设备,一个工作在三层,一个工作在二层,使用较多的是 TAP 设备。VETH设备出现较早,它的作用是反转通讯数据的方向,需要发送的数据会被转换成需要收到的数据重新送入内核网络层进行处理,从而间接的完成数据的注入。
当一个TAP设备被创建时,在Linux设备文件目录下将会生成一个对应char设备,用户程序可以像打开普通文件一样打开这个文件进行读写。当执行 write()操作时,数据进入 TAP 设备,此时对于 Linux 网络层来说,相当于 TAP 设备收到了一包数据,请求内核接受它,
如同普通的物理网卡从外界收到一包数据一样,不同的是其实数据来自Linux上的一个用户程序。Linux收到此数据后将根据网络配置进行后续处理,从而完成了用户程序向Linux内核网络层注入数据的功能。当用户程序执行read()请求时,相当于向内核查询 TAP 设备上是否有需要被发送出去的数据,有的话取出到用户程序里,完成 TAP 设备的发送数据功能。
针对 TAP 设备的一个形象的比喻是:使用 TAP 设备的应用程序相当于另外一台计算机,
TAP 设备是本机的一个网卡,他们之间相互连接。应用程序通过 read()/write()操作,
和本机网络核心进行通讯。
VETH 设备总是成对出现,送到一端请求发送的数据总是从另一端以请求接受的形式出现。
该设备不能被用户程序直接操作,但使用起来比较简单。创建并配置正确后,向其一端输入数据,VETH 会改变数据的方向并将其送入内核网络核心,完成数据的注入。在另一端能读到此数据。
●netns
netns是在linux中提供网络虚拟化的一个项目,使用netns网络空间虚拟化可以在本地虚拟化出多个网络环境,目前netns在lxc容器中被用来为容器提供网络。
使用netns创建的网络空间独立于当前系统的网络空间,其中的网络设备以及iptables规则等都是独立的,就好像进入了另外一个网络一样。不同网络命名空间中的设备是不同的,之间不能互相直接通讯。
//下述创建的网络命名空间,重启后,失效。
linux默认的网络命名空间时root 命名空间。创建新命名空间nstest的步骤如下:
1,创建命名空间
ip netns add nstest
2,查看命名空间
ip netns OR ip netns list
3,在此命名空间中,执行命令查看网卡
ip netns exec nstest ip a
4,如果网卡未被启用,就启用。
ip netns exec nstest ip link set lo up
5,查看netns命名空间下的route表。
ip netns exec nstest route //路由表是空的
6,查看netns命名空间下的防火墙规则。
ip netns exec nstest iptables -nL //如下没有任何规则
7,netns网络命名空间下执行ping命令。
ip netns exec nstest ping 10.20.0.250 //此时网络不通。
●建立虚拟网卡对(virtual ethernet peer),使命名空间netns和root命名空间联通。
1,创建一个虚拟网卡对vethp。(两个接头:tap-nstest,tap-root),默认是在root命名空间中创建的,在nstest空间中是看不到的。
ip link add tap-nstest type veth peer name tap-root // tap设备,类型为veth
2, 在root命名空间中查看网卡,可以看到新增了创建的虚拟网卡对的tap设备tap-nstest和tap-root。
ip a
3,查看两个tap设备是否是成对的关系。如果是成对的,它们的peer_ifindex应该是连续的。
ethtool -S tap-root
ethtool -S tap-nstest
●将tap设备分别分配到两个网络命名空间,达到联通的作用。
4,将tap-nstest分配到nstest命名空间中。分配后,在root命名空间中就看不到了。
ip link set tap-nstest netns nstest //可以查看ip netns exec nstest ip a
5,为tap-nstest添加一个ip地址
ip netns exec nstest ip addr add 192.168.10.2/24 dev tap-nstest
ip netns exec nstest ip link set tap-nstest up
6,查看nstest空间中的网卡信息
ip netns exec nstest ip a
7,为root命名空间中的tap-root添加ip
ip addr add 192.168.10.1/24 dev tap-root //删除命令:ip del add 192.168.10.1/24 dev tap-root
ip link set tap-root up
8,查看网络是否联通。
ping 192.168.10.2
ip netns exec nstest ping 192.168.10.1
●一个带网桥的配置例:
创建虚拟网络环境并且连接网线
ip netns add net0
ip netns add net1
ip netns add bridge
ip link add type veth
ip link set dev veth0 name net0-bridge netns net0
ip link set dev veth1 name bridge-net0 netns bridge
ip link add type veth
ip link set dev veth0 name net1-bridge netns net1
ip link set dev veth1 name bridge-net1 netns bridge
在bridge中创建并且设置br设备
ip netns exec bridge brctl addbr br
ip netns exec bridge ip link set dev br up
ip netns exec bridge ip link set dev bridge-net0 up
ip netns exec bridge ip link set dev bridge-net1 up
ip netns exec bridge brctl addif br bridge-net0
ip netns exec bridge brctl addif br bridge-net1
•然后配置两个虚拟环境的网卡
ip netns exec net0 ip link set dev net0-bridge up
ip netns exec net0 ip address add 10.0.1.1/24 dev net0-bridge
ip netns exec net1 ip link set dev net1-bridge up
ip netns exec net1 ip address add 10.0.1.2/24 dev net1-bridge
可参看:
https://blog.csdn.net/zhanglidn013/article/details/70241732
https://blog.csdn.net/qq_21127151/article/details/79370736