Linux ipip隧道技术测试二,模拟calico网络(三主机、单网卡、多namespace)

olivee 3年前 ⋅ 176 阅读

本文实验环境基于: CentOS Linux release 7.6.1810 (Core)

参考:

1. 核心技术

1.1 路由

路由器的工作原理是这样的:路由器上有2到多个网络接口,每个网络接口处于不同的三层子网上。路由器会根据内部的路由转发表从一个网络接口中收到的数据包转发到另一个网络接口,这样就实现了不同三层子网之间的互通Linux内核提供了IP Forwarding功能,启用IP Forwarding后,就可以在不同的网络接口中转发IP数据包相当于实现了路由器的功能。 备注:Linux的IP Forwarding功能并不是默认开启的,可以采用下面的方法开启:

cat > /etc/sysctl.d/30-ipforward.conf<<EOL
net.ipv4.ip_forward=1
net.ipv6.conf.default.forwarding=1
net.ipv6.conf.all.forwarding=1
EOL
sysctl -p /etc/sysctl.d/30-ipforward.conf

1.2 桥接的namespace连接到外部网络

从网络角度上来说,bridge是一个二层设备,因此并不需要设置IP。但Linux bridge虚拟设备比较特殊:我们可以认为bridge自带了一张网卡,这张网卡在主机上显示的名称就是bridge的名称。这张网卡在bridge上,因此可以和其它连接在bridge上的网卡和namespace进行二层通信;同时从主机角度来看,虚拟bridge设备也是主机default network namespace上的一张网卡,在为该网卡设置了IP后,可以参与主机的路由转发

通过给bridge设置一个IP地址,并将该IP设置为namespace的缺省网关,可以让namespace和主机进行网络通信。如果在主机上再添加相应的路由,可以让namespace和外部网络进行通信

1.3 单点的局域网

/32 位主机地址,表示将这个地址作为一个单点的局域网。如下,表示将tun0设备的IP设置为10.42.1.0/32的单点局域网:

ip a a 10.42.1.0/32 dev tun0

1.4 默认网关169.254.1.1

设置namespace中的默认网关为169.254.1.1

default via 169.254.1.1 dev veth1

当一个数据包的目的地址不是本机时,就会查询路由表,从路由表中查到网关后,它首先会通过 ARP 获得网关的 MAC 地址,然后在发出的网络数据包中将目标 MAC 改为网关的 MAC,而网关的 IP 地址不会出现在任何网络包头中。也就是说,没有人在乎这个 IP 地址究竟是什么,只要能找到对应的 MAC 地址,能响应 ARP 就行了。

这里我们参考Calico的实现,我们设置的是固定的MAC地址。如在ns1的namespace中:

ip netns exec ns1 ip neigh add 169.254.1.1 dev veth1 lladdr ee:ee:ee:ee:ee:ee 

可以通过 ip neigh 命令查看一下的 ARP 表:

$ ip netns exec ns1 ip neigh
169.254.1.1 dev veth1 lladdr ee:ee:ee:ee:ee:ee PERMANENT

参考 Calico 利用了网卡的代理 ARP 功能。代理 ARP 是 ARP 协议的一个变种,当 ARP 请求目标跨网段时,网关设备收到此 ARP 请求,会用自己的 MAC 地址返回给请求者,这便是代理 ARP(Proxy ARP)

比如我们设置namespace中veth1网卡对端的接口VEth peer,开启代理 ARP:

echo 1 > /proc/sys/net/ipv4/conf/tap1/proxy_arp

同时设置它的Mac地址为ee:ee:ee:ee:ee:ee:

ip l set address ee:ee:ee:ee:ee:ee dev tap1
  • 这样namespace中veth1的流量就会引导到特殊的网关169.254.1.1,从而引流到主机的 tap1 网络设备上,最终将二三层流量全部转换成三层流量来转发

  • 由于我们开启了ip_forward,因此可以在主机中通过路由表,将二层的流程转换成三层流量发送到其它主机上

  • 同时,在主机上通过开启代理 ARP 功能来实现 ARP 应答,使得 ARP 广播被抑制在主机上,抑制了广播风暴,也不会有 ARP 表膨胀的问题。

2. 模拟组网一

准备好三台主机CentOS 7版本,比如我这里的三台机器IP地址是 A主机(192.168.154.11)、B主机(192.168.154.12)、C主机(192.168.154.13)

2.1 组网模型图

ipip3-1.png

2.2 A主机执行

# 开启IP Forwarding,开启后可以在主机的不同网络接口中转发IP数据包,相当于主机变成了路由器。转发的规则根据主机中的路由表来转发
cat > /etc/sysctl.d/30-ipforward.conf<<EOL
net.ipv4.ip_forward=1
net.ipv6.conf.default.forwarding=1
net.ipv6.conf.all.forwarding=1
EOL
sysctl -p /etc/sysctl.d/30-ipforward.conf

# 添加网桥,并设置IP地址为10.42.1.1,这个网桥就相对于10.42.1子网的网关了
ip link add name mybr0 type bridge
ip addr add 10.42.1.1/24 dev mybr0
ip link set dev mybr0 up

# 添加ns1、ns2、ns3三个namespace
ip netns add ns1
ip netns add ns2
ip netns add ns3

# 在主机中添加三对虚拟网络设备,tap1、tap2、tap3设备的另一端分别为ns1、ns2、ns3三个namespace中的veth1设备
ip link add tap1 type veth peer name veth1 netns ns1
ip link add tap2 type veth peer name veth1 netns ns2
ip link add tap3 type veth peer name veth1 netns ns3

# 启用tap1、tap2、tap3设备
ip link set tap1 up
ip link set tap2 up
ip link set tap3 up

# 将tap1、tap2、tap3设备接入到mybr0网桥
ip link set dev tap1 master mybr0
ip link set dev tap2 master mybr0
ip link set dev tap3 master mybr0

# 设置ns1、ns2、ns3三个namespace中veth1设备的IP地址
ip netns exec ns1 ip addr add 10.42.1.11/24 dev veth1
ip netns exec ns2 ip addr add 10.42.1.12/24 dev veth1
ip netns exec ns3 ip addr add 10.42.1.13/24 dev veth1

# 启用ns1、ns2、ns3三个namespace中veth1设备
ip netns exec ns1 ip link set veth1 up
ip netns exec ns2 ip link set veth1 up
ip netns exec ns3 ip link set veth1 up

# 启用ns1、ns2、ns3三个namespace中lo设备,启用后namespace内部的回路网络才是通的,不然不能再namespace中ping通veth1设备的IP地址
ip netns exec ns1 ip link set lo up
ip netns exec ns2 ip link set lo up
ip netns exec ns3 ip link set lo up

# 启用ns1、ns2、ns3三个namespace的默认路由,指定网关为10.42.1.1。由于三个namespace都连接到mybr0网桥,mybr0网桥的IP地址为10.42.1.1,因此三个namespace默认出去的流量就会到mybr0网桥设备。
# 由于开启的IP Forwarding,流量到达mybr0后,会根据主机的路由表走三层网络转发出去
ip netns exec ns1 ip route add default via 10.42.1.1
ip netns exec ns2 ip route add default via 10.42.1.1
ip netns exec ns3 ip route add default via 10.42.1.1

# 添加tun0隧道设备,指定本地地址为192.168.154.11,远端地址为0.0.0.0(即远端是一个广播的地址,具体某个数据包往哪里转发,由路由表决定)
modprobe ipip
ip tunnel add tun0 mode ipip remote 0.0.0.0 local 192.168.154.11
# 设置tun0的IP地址为10.42.1.0/32,表示一个单点的局域网。仅仅在IP转发的时候用作原始的IP Header的src IP地址。(具体为什么要设置这个IP地址才能转发,还不明白)
ip a a 10.42.1.0/32 dev tun0
ip link set tun0 up

# 设置IP隧道的转发路由表
# 10.42.2.0/24通过tun0设备转发,网关地址为192.168.154.12
ip route add 10.42.2.0/24 via 192.168.154.12 dev tun0 onlink
# 10.42.3.0/24通过tun0设备转发,网关地址为192.168.154.13
ip route add 10.42.3.0/24 via 192.168.154.13 dev tun0 onlink

iptables -F

2.3 B主机执行

cat > /etc/sysctl.d/30-ipforward.conf<<EOL
net.ipv4.ip_forward=1
net.ipv6.conf.default.forwarding=1
net.ipv6.conf.all.forwarding=1
EOL
sysctl -p /etc/sysctl.d/30-ipforward.conf

ip link add name mybr0 type bridge
ip addr add 10.42.2.1/24 dev mybr0
ip link set dev mybr0 up

ip netns add ns1
ip netns add ns2
ip netns add ns3

ip link add tap1 type veth peer name veth1 netns ns1
ip link add tap2 type veth peer name veth1 netns ns2
ip link add tap3 type veth peer name veth1 netns ns3

ip link set tap1 up
ip link set tap2 up
ip link set tap3 up

ip link set dev tap1 master mybr0
ip link set dev tap2 master mybr0
ip link set dev tap3 master mybr0

ip netns exec ns1 ip addr add 10.42.2.11/24 dev veth1
ip netns exec ns2 ip addr add 10.42.2.12/24 dev veth1
ip netns exec ns3 ip addr add 10.42.2.13/24 dev veth1


ip netns exec ns1 ip link set veth1 up
ip netns exec ns2 ip link set veth1 up
ip netns exec ns3 ip link set veth1 up

ip netns exec ns1 ip link set lo up
ip netns exec ns2 ip link set lo up
ip netns exec ns3 ip link set lo up

ip netns exec ns1 ip route add default via 10.42.2.1
ip netns exec ns2 ip route add default via 10.42.2.1
ip netns exec ns3 ip route add default via 10.42.2.1

modprobe ipip
ip tunnel add tun0 mode ipip remote 0.0.0.0 local 192.168.154.12
ip a a 10.42.2.0/32 dev tun0
ip link set tun0 up

ip route add 10.42.1.0/24 via 192.168.154.11 dev tun0 onlink
ip route add 10.42.3.0/24 via 192.168.154.13 dev tun0 onlink

iptables -F

2.4 C主机执行

cat > /etc/sysctl.d/30-ipforward.conf<<EOL
net.ipv4.ip_forward=1
net.ipv6.conf.default.forwarding=1
net.ipv6.conf.all.forwarding=1
EOL
sysctl -p /etc/sysctl.d/30-ipforward.conf

ip link add name mybr0 type bridge
ip addr add 10.42.3.1/24 dev mybr0
ip link set dev mybr0 up

ip netns add ns1
ip netns add ns2
ip netns add ns3

ip link add tap1 type veth peer name veth1 netns ns1
ip link add tap2 type veth peer name veth1 netns ns2
ip link add tap3 type veth peer name veth1 netns ns3

ip link set tap1 up
ip link set tap2 up
ip link set tap3 up

ip link set dev tap1 master mybr0
ip link set dev tap2 master mybr0
ip link set dev tap3 master mybr0

ip netns exec ns1 ip addr add 10.42.3.11/24 dev veth1
ip netns exec ns2 ip addr add 10.42.3.12/24 dev veth1
ip netns exec ns3 ip addr add 10.42.3.13/24 dev veth1


ip netns exec ns1 ip link set veth1 up
ip netns exec ns2 ip link set veth1 up
ip netns exec ns3 ip link set veth1 up

ip netns exec ns1 ip link set lo up
ip netns exec ns2 ip link set lo up
ip netns exec ns3 ip link set lo up

ip netns exec ns1 ip route add default via 10.42.3.1
ip netns exec ns2 ip route add default via 10.42.3.1
ip netns exec ns3 ip route add default via 10.42.3.1

modprobe ipip
ip tunnel add tun0 mode ipip remote 0.0.0.0 local 192.168.154.13
ip a a 10.42.3.0/32 dev tun0
ip link set tun0 up

ip route add 10.42.1.0/24 via 192.168.154.11 dev tun0 onlink
ip route add 10.42.2.0/24 via 192.168.154.12 dev tun0 onlink

iptables -F

2.5 连通性测试

在A主机的三个namespace测试ping B主机的三个namespace中的网卡:

ip netns exec ns1 ping 10.42.3.11
ip netns exec ns1 ping 10.42.3.12
ip netns exec ns1 ping 10.42.3.13

ip netns exec ns2 ping 10.42.3.11
ip netns exec ns2 ping 10.42.3.12
ip netns exec ns2 ping 10.42.3.13

ip netns exec ns3 ping 10.42.3.11
ip netns exec ns4 ping 10.42.3.12
ip netns exec ns5 ping 10.42.3.13

在任意节点的任意namespace测试ping其它的节点的任意namespace中的网卡,测试都是成功的。

2.6 数据流向分析

ipip3-2.png ipip3-3.png

  1. A主机发送ip netns exec ns1 ping 10.42.2.11命令,达到协议栈,协议栈解析到是ns1这个namespace,应用层协议为ICMP协议,构造ICMP request数据包。网络层解析到是10.42.2.11这个IP地址,通过ARP协议找到10.42.2.11的MAC
  2. 协议栈根据10.42.2.11的MAC将ping的ICMP request包发送到veth1网络设备
  3. 由于ns1配置的默认路由是default via 10.42.1.1,因此数据经协议栈网络层找到mybr0
  4. 二层网络数据经过tap1,流向mybr0,mybr0接收到数据此时数据包为10.42.1.11 > 10.42.2.11: ICMP echo request, id 3838, seq 1, length 64,即表示源地址为10.42.1.11,目的地址为10.42.2.11的ICMP请求数据
  5. 数据被发送到协议栈网络层
  6. 由于主机开启了IP forward,协议栈在网络层根据目的地址10.42.2.11找到路由表10.42.2.0/24 via 192.168.154.12 dev tun0 onlink。因此协议栈将数据发送到tun0设备
  7. tun0将数据发送到协议栈
  8. 由于tun0配置的隧道模式,且本地地址为192.168.154.11,远程地址为0.0.0.0。同时路由表10.42.2.0/24 via 192.168.154.12 dev tun0 onlink配置的网关是192.168.154.12。因此协议栈在原始报文中添加报文头192.168.154.11 > 192.168.154.12(表示新的报文原地址为192.168.154.11,目的地址为192.168.154.12),并将数据发送给enp0s8(192.168.154.11)网卡。最后enp0s8收到的数据为192.168.154.11 > 192.168.154.12: 10.42.1.11 > 10.42.2.11: ICMP echo request, id 3838, seq 1, length 64 (ipip-proto-4) ipip-header2.png
  9. 数据发送到二层物理链路
  10. 二层物理链路将数据发送到B机器的enp0s8(192.168.154.12)
  11. B机器的enp0s8将数据发送到协议栈
  12. B机器由于tun0配置的remote 0.0.0.0 local 192.168.154.12,因此协议栈根据IP隧道协议,找到本地地址是192.168.154.12找到tun0。同时去除IPIP协议新加的头,得到原始的数据包10.42.1.11 > 10.42.2.11: ICMP echo request, id 3838, seq 1, length 64
  13. B机器tun0将数据发到协议栈
  14. 由于主机开启了IP forward,B机器协议栈根据路由表10.42.2.0/24 dev mybr0 proto kernel scope link src 10.42.2.1,将数据发送给mybr0(10.42.2.1)
  15. mybr0作为网桥,找到10.42.2.11,并将数据发出去,数据流向tap1
  16. 数据经过tap1到达10.42.2.11
  17. (后续17-32步)数据返回的过程和流入的过程类似,不再赘述

3. 模拟组网二:利用代理ARP

准备好三台主机CentOS 7版本,比如我这里的三台机器IP地址是 A主机(192.168.154.11)、B主机(192.168.154.12)、C主机(192.168.154.13)

3.1 组网模型图

ipip4-1.png

与模拟组网一主要的区别是,namespace中设置路由为

default via 169.254.1.1 dev veth1 
169.254.1.1 dev veth1 scope link

namespace中设置固定APR:

169.254.1.1 dev veth1 lladdr ee:ee:ee:ee:ee:ee PERMANENT

并设置tap1、tap2、tap3设备为PROXY ARP模式:

echo 1 > /proc/sys/net/ipv4/conf/tap1/proxy_arp
echo 1 > /proc/sys/net/ipv4/conf/tap2/proxy_arp
echo 1 > /proc/sys/net/ipv4/conf/tap3/proxy_arp

不知道为啥mybr0的mac地址也自动变成了ee:ee:ee:ee:ee:ee??

3.2 A主机执行

cat > /etc/sysctl.d/30-ipforward.conf<<EOL
net.ipv4.ip_forward=1
net.ipv6.conf.default.forwarding=1
net.ipv6.conf.all.forwarding=1
EOL
sysctl -p /etc/sysctl.d/30-ipforward.conf

ip link add name mybr0 type bridge
ip addr add 10.42.1.1/24 dev mybr0
ip link set dev mybr0 up

ip netns add ns1
ip netns add ns2
ip netns add ns3

ip link add tap1 type veth peer name veth1 netns ns1
ip link add tap2 type veth peer name veth1 netns ns2
ip link add tap3 type veth peer name veth1 netns ns3

# 设置tap1、tap2、tap3的mac地址为ee:ee:ee:ee:ee:ee
ip l set address ee:ee:ee:ee:ee:ee dev tap1
ip l set address ee:ee:ee:ee:ee:ee dev tap2
ip l set address ee:ee:ee:ee:ee:ee dev tap3

# 开启tap1、tap2、tap3设备的proxy_arp功能
echo 1 > /proc/sys/net/ipv4/conf/tap1/proxy_arp
echo 1 > /proc/sys/net/ipv4/conf/tap2/proxy_arp
echo 1 > /proc/sys/net/ipv4/conf/tap3/proxy_arp

ip link set tap1 up
ip link set tap2 up
ip link set tap3 up

ip link set dev tap1 master mybr0
ip link set dev tap2 master mybr0
ip link set dev tap3 master mybr0

ip netns exec ns1 ip addr add 10.42.1.11/32 dev veth1
ip netns exec ns2 ip addr add 10.42.1.12/32 dev veth1
ip netns exec ns3 ip addr add 10.42.1.13/32 dev veth1

ip netns exec ns1 ip link set veth1 up
ip netns exec ns2 ip link set veth1 up
ip netns exec ns3 ip link set veth1 up

ip netns exec ns1 ip link set lo up
ip netns exec ns2 ip link set lo up
ip netns exec ns3 ip link set lo up

# 设置ns1、ns2、ns3的路由表默认网关为169.254.1.1,流量走veth1设备
ip netns exec ns1 ip route add 169.254.1.1 dev veth1
ip netns exec ns2 ip route add 169.254.1.1 dev veth1
ip netns exec ns3 ip route add 169.254.1.1 dev veth1
ip netns exec ns1 ip route add default via 169.254.1.1 dev veth1 
ip netns exec ns2 ip route add default via 169.254.1.1 dev veth1
ip netns exec ns3 ip route add default via 169.254.1.1 dev veth1

# 设置ns1、ns2、ns3中的固定ARP表:地址169.254.1.1对应的mac为ee:ee:ee:ee:ee:ee,寻址设备为veth1
ip netns exec ns1 ip neigh add 169.254.1.1 dev veth1 lladdr ee:ee:ee:ee:ee:ee 
ip netns exec ns2 ip neigh add 169.254.1.1 dev veth1 lladdr ee:ee:ee:ee:ee:ee
ip netns exec ns3 ip neigh add 169.254.1.1 dev veth1 lladdr ee:ee:ee:ee:ee:ee

modprobe ipip
ip tunnel add tun0 mode ipip remote 0.0.0.0 local 192.168.154.11
ip a a 10.42.1.0/32 dev tun0
ip link set tun0 up

ip route add 10.42.2.0/24 via 192.168.154.12 dev tun0 onlink
ip route add 10.42.3.0/24 via 192.168.154.13 dev tun0 onlink

iptables -F

3.3 B主机执行

cat > /etc/sysctl.d/30-ipforward.conf<<EOL
net.ipv4.ip_forward=1
net.ipv6.conf.default.forwarding=1
net.ipv6.conf.all.forwarding=1
EOL
sysctl -p /etc/sysctl.d/30-ipforward.conf

ip link add name mybr0 type bridge
ip addr add 10.42.2.1/24 dev mybr0
ip link set dev mybr0 up

ip netns add ns1
ip netns add ns2
ip netns add ns3

ip link add tap1 type veth peer name veth1 netns ns1
ip link add tap2 type veth peer name veth1 netns ns2
ip link add tap3 type veth peer name veth1 netns ns3

ip l set address ee:ee:ee:ee:ee:ee dev tap1
ip l set address ee:ee:ee:ee:ee:ee dev tap2
ip l set address ee:ee:ee:ee:ee:ee dev tap3

echo 1 > /proc/sys/net/ipv4/conf/tap1/proxy_arp
echo 1 > /proc/sys/net/ipv4/conf/tap2/proxy_arp
echo 1 > /proc/sys/net/ipv4/conf/tap3/proxy_arp

ip link set tap1 up
ip link set tap2 up
ip link set tap3 up

ip link set dev tap1 master mybr0
ip link set dev tap2 master mybr0
ip link set dev tap3 master mybr0

ip netns exec ns1 ip addr add 10.42.2.11/32 dev veth1
ip netns exec ns2 ip addr add 10.42.2.12/32 dev veth1
ip netns exec ns3 ip addr add 10.42.2.13/32 dev veth1


ip netns exec ns1 ip link set veth1 up
ip netns exec ns2 ip link set veth1 up
ip netns exec ns3 ip link set veth1 up

ip netns exec ns1 ip link set lo up
ip netns exec ns2 ip link set lo up
ip netns exec ns3 ip link set lo up

ip netns exec ns1 ip route add 169.254.1.1 dev veth1
ip netns exec ns2 ip route add 169.254.1.1 dev veth1
ip netns exec ns3 ip route add 169.254.1.1 dev veth1

ip netns exec ns1 ip route add default via 169.254.1.1 dev veth1 
ip netns exec ns2 ip route add default via 169.254.1.1 dev veth1
ip netns exec ns3 ip route add default via 169.254.1.1 dev veth1

ip netns exec ns1 ip neigh add 169.254.1.1 dev veth1 lladdr ee:ee:ee:ee:ee:ee 
ip netns exec ns2 ip neigh add 169.254.1.1 dev veth1 lladdr ee:ee:ee:ee:ee:ee
ip netns exec ns3 ip neigh add 169.254.1.1 dev veth1 lladdr ee:ee:ee:ee:ee:ee




modprobe ipip
ip tunnel add tun0 mode ipip remote 0.0.0.0 local 192.168.154.12
ip a a 10.42.2.0/32 dev tun0
ip link set tun0 up

ip route add 10.42.1.0/24 via 192.168.154.11 dev tun0 onlink
ip route add 10.42.3.0/24 via 192.168.154.13 dev tun0 onlink

iptables -F

3.4 C主机执行

cat > /etc/sysctl.d/30-ipforward.conf<<EOL
net.ipv4.ip_forward=1
net.ipv6.conf.default.forwarding=1
net.ipv6.conf.all.forwarding=1
EOL
sysctl -p /etc/sysctl.d/30-ipforward.conf

ip link add name mybr0 type bridge
ip addr add 10.42.3.1/24 dev mybr0
ip link set dev mybr0 up

ip netns add ns1
ip netns add ns2
ip netns add ns3

ip link add tap1 type veth peer name veth1 netns ns1
ip link add tap2 type veth peer name veth1 netns ns2
ip link add tap3 type veth peer name veth1 netns ns3

ip l set address ee:ee:ee:ee:ee:ee dev tap1
ip l set address ee:ee:ee:ee:ee:ee dev tap2
ip l set address ee:ee:ee:ee:ee:ee dev tap3

echo 1 > /proc/sys/net/ipv4/conf/tap1/proxy_arp
echo 1 > /proc/sys/net/ipv4/conf/tap2/proxy_arp
echo 1 > /proc/sys/net/ipv4/conf/tap3/proxy_arp

ip link set tap1 up
ip link set tap2 up
ip link set tap3 up

ip link set dev tap1 master mybr0
ip link set dev tap2 master mybr0
ip link set dev tap3 master mybr0

ip netns exec ns1 ip addr add 10.42.3.11/32 dev veth1
ip netns exec ns2 ip addr add 10.42.3.12/32 dev veth1
ip netns exec ns3 ip addr add 10.42.3.13/32 dev veth1


ip netns exec ns1 ip link set veth1 up
ip netns exec ns2 ip link set veth1 up
ip netns exec ns3 ip link set veth1 up

ip netns exec ns1 ip link set lo up
ip netns exec ns2 ip link set lo up
ip netns exec ns3 ip link set lo up

ip netns exec ns1 ip route add 169.254.1.1 dev veth1
ip netns exec ns2 ip route add 169.254.1.1 dev veth1
ip netns exec ns3 ip route add 169.254.1.1 dev veth1

ip netns exec ns1 ip route add default via 169.254.1.1 dev veth1 
ip netns exec ns2 ip route add default via 169.254.1.1 dev veth1
ip netns exec ns3 ip route add default via 169.254.1.1 dev veth1

ip netns exec ns1 ip neigh add 169.254.1.1 dev veth1 lladdr ee:ee:ee:ee:ee:ee 
ip netns exec ns2 ip neigh add 169.254.1.1 dev veth1 lladdr ee:ee:ee:ee:ee:ee
ip netns exec ns3 ip neigh add 169.254.1.1 dev veth1 lladdr ee:ee:ee:ee:ee:ee

modprobe ipip
ip tunnel add tun0 mode ipip remote 0.0.0.0 local 192.168.154.13
ip a a 10.42.3.0/32 dev tun0
ip link set tun0 up

ip route add 10.42.1.0/24 via 192.168.154.11 dev tun0 onlink
ip route add 10.42.2.0/24 via 192.168.154.12 dev tun0 onlink

iptables -F

3.5 连通性测试

模拟组网一一样,网络都能测通。

3.6 数据流向分析

模拟组网一类似,主要是从namespace流向mybr0的时候,先是读取的路由配置

default via 169.254.1.1 dev veth1 
169.254.1.1 dev veth1 scope link

通过三层路由协议将数据包发给169.254.1.1,而ARP配置固定的169.254.1.1的地址为ee:ee:ee:ee:ee:ee

169.254.1.1 dev veth1 lladdr ee:ee:ee:ee:ee:ee PERMANENT

因此数据发送到Mac为ee:ee:ee:ee:ee:ee的网卡,即veth1配对的虚拟tap1网卡。桥接到mybr0,因此数据发送到了mybr0。

4. 模拟组网三:利用代理ARP,不走bridge网桥

准备好三台主机CentOS 7版本,比如我这里的三台机器IP地址是 A主机(192.168.154.11)、B主机(192.168.154.12)、C主机(192.168.154.13)

4.1 组网模型图

ipip5-1.png模拟组网二的区别是,没有网桥mybr0设备。分别直接由tap1、tap2、tap3连接到各自namespace的veth1设备。通过配置路由实现,如A主机配置如下:

ip r a 10.42.2.11 dev tap1
ip r a 10.42.2.12 dev tap2
ip r a 10.42.2.13 dev tap3

其它的Proxy ARP配置与模拟组网二一致。由于采用模拟组网二,利用169.254.1.1将二层数据包转给三层网络层去处理。因此namespace中连接到任意网段都可以(只要主机中有IP隧道和路由表能够将数据转发出去即可)

4.2 A主机执行

cat > /etc/sysctl.d/30-ipforward.conf<<EOL
net.ipv4.ip_forward=1
net.ipv6.conf.default.forwarding=1
net.ipv6.conf.all.forwarding=1
EOL
sysctl -p /etc/sysctl.d/30-ipforward.conf

ip netns add ns1
ip netns add ns2
ip netns add ns3

ip link add tap1 type veth peer name veth1 netns ns1
ip link add tap2 type veth peer name veth1 netns ns2
ip link add tap3 type veth peer name veth1 netns ns3

ip l set address ee:ee:ee:ee:ee:ee dev tap1
ip l set address ee:ee:ee:ee:ee:ee dev tap2
ip l set address ee:ee:ee:ee:ee:ee dev tap3

echo 1 > /proc/sys/net/ipv4/conf/tap1/proxy_arp
echo 1 > /proc/sys/net/ipv4/conf/tap2/proxy_arp
echo 1 > /proc/sys/net/ipv4/conf/tap3/proxy_arp

ip link set tap1 up
ip link set tap2 up
ip link set tap3 up

# 分别tap1、tap2、tap2路由到各自namespace的veth1设备
ip r a 10.42.1.11 dev tap1
ip r a 10.42.1.12 dev tap2
ip r a 10.42.1.13 dev tap3

ip netns exec ns1 ip addr add 10.42.1.11/32 dev veth1
ip netns exec ns2 ip addr add 10.42.1.12/32 dev veth1
ip netns exec ns3 ip addr add 10.42.1.13/32 dev veth1

ip netns exec ns1 ip link set veth1 up
ip netns exec ns2 ip link set veth1 up
ip netns exec ns3 ip link set veth1 up

ip netns exec ns1 ip link set lo up
ip netns exec ns2 ip link set lo up
ip netns exec ns3 ip link set lo up

ip netns exec ns1 ip route add 169.254.1.1 dev veth1
ip netns exec ns2 ip route add 169.254.1.1 dev veth1
ip netns exec ns3 ip route add 169.254.1.1 dev veth1

ip netns exec ns1 ip route add default via 169.254.1.1 dev veth1 
ip netns exec ns2 ip route add default via 169.254.1.1 dev veth1
ip netns exec ns3 ip route add default via 169.254.1.1 dev veth1

ip netns exec ns1 ip neigh add 169.254.1.1 dev veth1 lladdr ee:ee:ee:ee:ee:ee 
ip netns exec ns2 ip neigh add 169.254.1.1 dev veth1 lladdr ee:ee:ee:ee:ee:ee
ip netns exec ns3 ip neigh add 169.254.1.1 dev veth1 lladdr ee:ee:ee:ee:ee:ee

modprobe ipip
ip tunnel add tun0 mode ipip remote 0.0.0.0 local 192.168.154.11
ip a a 10.42.1.0/32 dev tun0
ip link set tun0 up

ip route add 10.42.2.0/24 via 192.168.154.12 dev tun0 onlink
ip route add 10.42.3.0/24 via 192.168.154.13 dev tun0 onlink

iptables -F

4.3 B主机执行


cat > /etc/sysctl.d/30-ipforward.conf<<EOL
net.ipv4.ip_forward=1
net.ipv6.conf.default.forwarding=1
net.ipv6.conf.all.forwarding=1
EOL
sysctl -p /etc/sysctl.d/30-ipforward.conf

ip netns add ns1
ip netns add ns2
ip netns add ns3

ip link add tap1 type veth peer name veth1 netns ns1
ip link add tap2 type veth peer name veth1 netns ns2
ip link add tap3 type veth peer name veth1 netns ns3

ip l set address ee:ee:ee:ee:ee:ee dev tap1
ip l set address ee:ee:ee:ee:ee:ee dev tap2
ip l set address ee:ee:ee:ee:ee:ee dev tap3

echo 1 > /proc/sys/net/ipv4/conf/tap1/proxy_arp
echo 1 > /proc/sys/net/ipv4/conf/tap2/proxy_arp
echo 1 > /proc/sys/net/ipv4/conf/tap3/proxy_arp

ip link set tap1 up
ip link set tap2 up
ip link set tap3 up

ip r a 10.42.2.11 dev tap1
ip r a 10.42.2.12 dev tap2
ip r a 10.42.2.13 dev tap3

ip netns exec ns1 ip addr add 10.42.2.11/32 dev veth1
ip netns exec ns2 ip addr add 10.42.2.12/32 dev veth1
ip netns exec ns3 ip addr add 10.42.2.13/32 dev veth1

ip netns exec ns1 ip link set veth1 up
ip netns exec ns2 ip link set veth1 up
ip netns exec ns3 ip link set veth1 up

ip netns exec ns1 ip link set lo up
ip netns exec ns2 ip link set lo up
ip netns exec ns3 ip link set lo up

ip netns exec ns1 ip route add 169.254.1.1 dev veth1
ip netns exec ns2 ip route add 169.254.1.1 dev veth1
ip netns exec ns3 ip route add 169.254.1.1 dev veth1

ip netns exec ns1 ip route add default via 169.254.1.1 dev veth1 
ip netns exec ns2 ip route add default via 169.254.1.1 dev veth1
ip netns exec ns3 ip route add default via 169.254.1.1 dev veth1

ip netns exec ns1 ip neigh add 169.254.1.1 dev veth1 lladdr ee:ee:ee:ee:ee:ee 
ip netns exec ns2 ip neigh add 169.254.1.1 dev veth1 lladdr ee:ee:ee:ee:ee:ee
ip netns exec ns3 ip neigh add 169.254.1.1 dev veth1 lladdr ee:ee:ee:ee:ee:ee

modprobe ipip
ip tunnel add tun0 mode ipip remote 0.0.0.0 local 192.168.154.12
ip a a 10.42.2.0/32 dev tun0
ip link set tun0 up

ip route add 10.42.1.0/24 via 192.168.154.11 dev tun0 onlink
ip route add 10.42.3.0/24 via 192.168.154.13 dev tun0 onlink

iptables -F

4.4 C主机执行


cat > /etc/sysctl.d/30-ipforward.conf<<EOL
net.ipv4.ip_forward=1
net.ipv6.conf.default.forwarding=1
net.ipv6.conf.all.forwarding=1
EOL
sysctl -p /etc/sysctl.d/30-ipforward.conf

ip netns add ns1
ip netns add ns2
ip netns add ns3

ip link add tap1 type veth peer name veth1 netns ns1
ip link add tap2 type veth peer name veth1 netns ns2
ip link add tap3 type veth peer name veth1 netns ns3

ip l set address ee:ee:ee:ee:ee:ee dev tap1
ip l set address ee:ee:ee:ee:ee:ee dev tap2
ip l set address ee:ee:ee:ee:ee:ee dev tap3

echo 1 > /proc/sys/net/ipv4/conf/tap1/proxy_arp
echo 1 > /proc/sys/net/ipv4/conf/tap2/proxy_arp
echo 1 > /proc/sys/net/ipv4/conf/tap3/proxy_arp

ip link set tap1 up
ip link set tap2 up
ip link set tap3 up

ip r a 10.42.3.11 dev tap1
ip r a 10.42.3.12 dev tap2
ip r a 10.42.3.13 dev tap3

ip netns exec ns1 ip addr add 10.42.3.11/32 dev veth1
ip netns exec ns2 ip addr add 10.42.3.12/32 dev veth1
ip netns exec ns3 ip addr add 10.42.3.13/32 dev veth1

ip netns exec ns1 ip link set veth1 up
ip netns exec ns2 ip link set veth1 up
ip netns exec ns3 ip link set veth1 up

ip netns exec ns1 ip link set lo up
ip netns exec ns2 ip link set lo up
ip netns exec ns3 ip link set lo up

ip netns exec ns1 ip route add 169.254.1.1 dev veth1
ip netns exec ns2 ip route add 169.254.1.1 dev veth1
ip netns exec ns3 ip route add 169.254.1.1 dev veth1

ip netns exec ns1 ip route add default via 169.254.1.1 dev veth1 
ip netns exec ns2 ip route add default via 169.254.1.1 dev veth1
ip netns exec ns3 ip route add default via 169.254.1.1 dev veth1

ip netns exec ns1 ip neigh add 169.254.1.1 dev veth1 lladdr ee:ee:ee:ee:ee:ee 
ip netns exec ns2 ip neigh add 169.254.1.1 dev veth1 lladdr ee:ee:ee:ee:ee:ee
ip netns exec ns3 ip neigh add 169.254.1.1 dev veth1 lladdr ee:ee:ee:ee:ee:ee

modprobe ipip
ip tunnel add tun0 mode ipip remote 0.0.0.0 local 192.168.154.13
ip a a 10.42.3.0/32 dev tun0
ip link set tun0 up

ip route add 10.42.1.0/24 via 192.168.154.11 dev tun0 onlink
ip route add 10.42.2.0/24 via 192.168.154.12 dev tun0 onlink

iptables -F

4.5 连通性测试

模拟组网一模拟组网二一样,网络都能测通。

4.6 数据流向分析

数据流与前面两种方案类似,只是少了mybr0设备的流量。 ipip5-2.png ipip5-3.png