bridge + veth + namespace 模拟docker 容器通信

63 阅读3分钟

前置知识

网络命名空间:

1: 创建一个网络命名空间

ip netns add 网络空间名

2: 查看网络命名空间列表

ip netns list  

3: 删除一个网络命名空间

ip netns delete 网络空间名

4: 切换到某个网络命名空间

ip netns exec 网络命名空间名 bash 

5: 退出某个网络命名空间

exit

需求:

用虚拟网桥 + veth pair 实现同一主机上,两个不同的网络空间之间的互通,虚拟网桥配置ip地址

目的:

自己动手模拟下docker网络的实现方式。

实验步骤:

1: 创建命名空间 nst1 nst2

  ip netns add nst1 

  ip netns add nst2 

2: 创建两组 veth pair 虚拟网络设备 vetht1_br vetht1 vetht2_br vetht2

 ip link add vetht1_br type veth peer name vetht1 

 ip link add vetht2_br type veth peer name vetht2

3: 将 vetht1 放入 nst1 网络命名空间。将vetht2 放入 nst2 网络命名空间

ip link set vetht1 netns nst1 

ip link set vetht2 netns nst2 

4: 创建 br_tes 网桥设备

ip link add br_tes type bridge 

5: 将 vetht1_br,vetht2_br 连接到 网桥设备 br_tes 之上

ip link set vetht1_br master br_tes

ip link set vetht2_br master br_tes

6: 设置 vetht1的ip地址 为 192.168.0.14/24,vetht2的ip地址为 192.168.0.15/24, br_tes的ip地址 为 192.168.0.16/24

ip netns exec nst1 bash

ip addr add 192.168.0.14/24 dev  vetht1 

exit

ip netns exec nst2 bash

ip addr add 192.168.0.15/24 dev vetht2

exit

ip addr add 192.168.0.16/24 dev br_tes

7: 启动 vetht1 vetht1_br vetht2 vetht2_br br_tes 设备

ip netns exec nst1 bash

ip link set vetht1 up

exit 

ip link set vetht1_br up 

ip netns exec nst2 bash

ip link set vetht2 up 

exit

ip link set  vetht2_br up 

ip link set br_tes up

8: 增加iptables 转发规则

iptables -A FORWARD -i br_tes -o br_tes -j ACCEPT

9: 进入 nst1 网络命名空间,ping 192.168.0.15

ip netns exec nst1 bash

ping 192.168.0.15 

对于实验步骤的疑惑:

为什么要进行第8步,设置iptables的转发规则? 因为数据包从网络空间的vetht1 到达 本机的br_tes网桥时,实质是外部的数据包发向本机的进程,所以数据包会经过 iptables设置的规则的过滤。

因为数据包的mac地址不是 br_tes,所以数据包会被转发。所以,数据包会被 PREROUTING FORWARD POSTROUTING 三条链之上的规则进行处理。而FORWARD链的数据包的默认处理策略是 DROP,所以需 要增加 这样的转发策略。

需求:

用虚拟网桥 + veth pair 实现同一主机上,两个不同的网络空间之间的互通, 虚拟网桥不配置ip地址

目的

想看下作为二层网络设备时的虚拟网桥的工作原理

实验步骤:

1: 创建命名空间 nst1 nst2

  ip netns add nst1 

  ip netns add nst2 

2: 创建两组 veth pair 虚拟网络设备 vetht1_br vetht1 vetht2_br vetht2

 ip link add vetht1_br type veth peer name vetht1 

 ip link add vetht2_br type veth peer name vetht2

3: 将 vetht1 放入 nst1 网络命名空间。将vetht2 放入 nst2 网络命名空间

ip link set vetht1 netns nst1 

ip link set vetht2 netns nst2 

4: 创建 br_tes 网桥设备

ip link add br_tes type bridge 

5: 将 vetht1_br,vetht2_br 连接到 网桥设备 br_tes 之上

ip link set vetht1_br master br_tes

ip link set vetht2_br master br_tes

6: 设置 vetht1的ip地址 为 192.168.0.14/24,vetht2的ip地址为 192.168.0.15/24, br_tes的ip地址 为 192.168.0.16/24

ip netns exec nst1 bash

ip addr add 192.168.0.14/24 dev  vetht1 

exit

ip netns exec nst2 bash

ip addr add 192.168.0.15/24 dev vetht2

exit

7: 启动 vetht1 vetht1_br vetht2 vetht2_br br_tes 设备

ip netns exec nst1 bash

ip link set vetht1 up

exit 

ip link set vetht1_br up 

ip netns exec nst2 bash

ip link set vetht2 up 

exit

ip link set  vetht2_br up 

ip link set br_tes up

8: 增加iptables 转发规则

iptables -A FORWARD -i br_tes -o br_tes -j ACCEPT

9: 进入 nst1 网络命名空间,ping 192.168.0.15

 ip netns exec nst1 bash

 ping 192.168.0.15 

问题:

既然 bridge 是模拟交换机的功能,根据mac地址转发以太网包,为啥如果不设置iptables转发规则,数据包就到不了 网络层? 自己的理解:因为 /proc/sys/net/bridge/bridge-nf-call-iptables 这个参数的作用。当这个参数为1的时候,Linux之中的bridge网桥会显示地调用iptables的链,所以需要增加iptables转发规则。