手动搭建 vxlan 点对点网络
1. 点对点vxlan通信逻辑拓扑
1.1 目标
两台主机之间的ns1 namespace和 ns2 namespace之间通过vxlan相互通信。
描述网络结构图(包的构成和转发依据)
1.2 实现步骤
1.2.1 关闭防火墙
systemctl stop firewalld
systemctl disalbe firewalld
# 或者 ufw disable
1.2.2 创建vxlan设备,并配置IP
ip link add vxlan1 type vxlan id 100 dstport 4789 remote 10.33.30.151 local 10.33.30.150 dev ens160
参数解释:
id 100 : 指定 VNI 的值,有效值在 1 到 2^24 之间。
dstport : VTEP 通信的端口,IANA 分配的端口是 4789。如果不指定,Linux 默认使用 8472。ovs创建的vxlan port也是默认使用端口4789
remote : 对端 VTEP 的地址,因为这里是用物理机的网卡作为VTEP所以这里就是对端物理机上的IP。
local : 当前节点 VTEP 要使用的 IP 地址,即当前节点隧道口的 IP 地址,因为这里是用物理机的网卡作为VTEP所以这里就是本物理机上的IP。
dev ens160: 当前节点用于 VTEP 通信的设备也就是本机的网卡,用来获取 VTEP IP 地址。这个参数与 local 参数目的相同,二选一即可
查看vxlan1的详细信息:
ip -d link show vxlan1
输出:
vxlan1: <BROADCAST,MULTICAST> mtu 1450 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether f6:6b:60:7a:24:f2 brd ff:ff:ff:ff:ff:ff promiscuity 0
vxlan id 100 remote 10.33.30.151 local 10.33.30.150 dev ens160 srcport 0 0 dstport 4789 ageing 300 noudpcsum noudp6zerocsumtx noudp6zerocsumrx addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
同时会增加一条bridge FDB转发表
bridge fdb
输出:
00:00:00:00:00:00 dev vxlan1 dst 10.33.30.151 via ens160 self permanent
全零表项表示没有匹配的MAC地址时,就发送到该表项中的VTEP。这条表项的意思是,默认的VTEP对端地址为10.33.30.151,原始报文经过vxlan1后会添加vxlan头部,而外部UDP头的目的IP地址会被冠上10.33.30.151
为vxlan1配置IP地址并启用
ip link set dev vxlan1 up ip addr add 192.168.1.254/32 dev vxlan1
问题1: 为什么是32位的,24位的不可以吗?
因为后边br1的ip也是192.168.1.0/24网段的,这里改成24位会无法正常路由,路由条目有两个1.0网段路由,ns1流量访问br1的192.168.1.1的出去流量会因为路由问题无法响应,导致不通。
1.2.3 创建bridge,并设置IP
brctl addbr br1 ip link set dev br1 up ip addr add 192.168.1.1/24 dev br1
1.2.4 创建namespace,veth pair,分别移入bridge和ns中
ip netns add ns1 ip link add tap1 type veth peer name tap2 ip link set dev tap2 up ip link set tap1 netns ns1 ip netns exec ns1 ip link set dev tap1 up ip netns exec ns1 ip addr add 192.168.1.100/24 dev tap1 brctl addif br1 tap2
1.2.5 系统网络内核参数修改
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter echo 0 > /proc/sys/net/ipv4/conf/br1/rp_filter
问题2:上面两个参数不修改也可以通信?
只是本场景没有涉及到,其他场景有可能用到该内核参数,反向路径检测。
echo 1 > /proc/sys/net/ipv4/ip_forward
1.2.6 配置路由
ip netns exec ns1 ip route add default via 192.168.1.1 # ns1命名空间中默认的路由为 192.168.1.1 也就是网桥 br1
ip route add 192.168.2.0/24 via 192.168.2.254 dev vxlan1 onlink # 在 host1 中走向 192.168.2.0/24 网段的路由为 192.168.2.254 也就是 vxlan1
在ns1中 ping ns2中的 192.168.2.100 的话,ip层就是 ns1 -> br1 -> vxlan1
若不设置onlink,会提示network is unreachable
onlink的意义在于协议栈虽然找不到链路层直连路由,但是还是会发布针对via网关的arp请求的.
1.2.7 状态截图vxlan1 主机1
vxlan2主机2
1.3 点对点VXLAN通信过程
主机1 ns1 向主机2 ns2 发送第一个包,各个接口抓包状态。
1.3.1 主机1 br1接口抓包
9a:9d:8a:71:77:a9 是 ns1 namespace tap1设备的mac,
4a:a4:77:8f:e7:90 是br1设备的mac.
(1)当ns1中的tap1网卡去ping另一个主机的ns2中的网卡192.168.2.100时,跨网段访问会将请求发给网关,先发送arp请求获取网关192.168.1.1的mac。
arp请求报文:
sender IP:192.168.1.100
sender mac:9a:9d:8a:71:77:a9
target IP:192.168.1.1
target mac:全0
以太二层封装:
源MAC:NS1中tap1设备(192.168.1.100)的mac
目的MAC:全F
arp广播请求报文会通过tap1–>tap2达到宿主机,本地MAC地址表会学习记录该报文的源MAC和接受接口的对应关系。
收到该arp广播请求,解封装之后查看arp请求的IP是本地的,那么构建arp单播响应,根据先前学习记录的对应mac表项出接口是br1设备上的tap2口到达ns1。
arp响应报文:
sender IP:192.168.1.1
sender mac:4a:a4:77:8f:e7:90
target IP:192.168.1.100
target mac:9a:9d:8a:71:77:a9
以太二层封装:
源MAC:br1网桥设备的mac(192.168.1.1网关的mac)
目的MAC:NS1中tap1网卡设备(192.168.1.100)的mac
(2)ns1收到网关的arp响应之后,缓存到本地
然后继续构建icmp请求报文
源IP:192.168.1.100 目的IP:192.168.2.100 源MAC:9a:9d:8a:71:77:a9
目的MAC:4a:a4:77:8f:e7:90
(3)ICMP请求报文通过tap1–tap2设备从ns1到达宿主机1时也就是到达默认的namespace时,查看报文目的MAC是本机的br1设备MAC,解封装拆掉二层帧头,露出IP报文。
(br设备的MAC地址是它所有从设备中最小的MAC地址),在这里br1设备只有一个从设备tap2,所以br1的mac和tap2的mac一致.
查看宿主机(default namespace)路由表,匹配路由,发现去往192.168.2.0/24的下一跳为192.168.2.254,出接口为vxlan1
不是发往本机的,需要判断本地是否开启了路由转发功能,如果开启则发送arp请求192.168.2.254的mac地址.
出接口是vxlan1,需要进行vxlan封装,会使用出接口的IP,MAC作为报文的源地址。
vxlan1收到报文截图,vxlan接口抓的包是未封装之前或解封装之后的报文。
6:6b:60:7a:24:f2 --> vxlan1(192.168.1.254)的MAC
52:8f:7f:a6:f4:b1 --> vxlan2(192.168.2.254)的MAC
ens160接口抓包截图,是vxlan封装之后的报文
原始arp请求报文:
send MAC:f6:6b:60:7a:24:f2(vxlan1设备的mac)
send IP:192.168.1.254(vxlan1设备的IP)
target MAC:全0
target IP:192.168.2.254
内层以太二层帧:
源MAC:VXLAN1设备的mac
目的MAC:全F
vxlan封装:
vni为100
UDP封装:
源端口随机端口,目的端口4789
外层VTEPIP封装:
源IP:10.33.30.150
目的IP:10.33.30.151
外层以太二层帧:
源MAC:本端VTEP(10.33.30.150)接口的MAC
目的MAC:对端VTEP(10.33.30.151)接口的MAC
主机2 ens160抓取的报文和主机1 ens160抓取的报文一样
(4)报文到达主机2,解封装,主机2 vxlan2抓取报文.
vxlan2这里的报文是已经解封装之后的报文。
根据原始arp广播报文发现(主机本地fdb mac地址表会记录该广播包的源MAC和入接口绑定) 请求的是本机的192.168.2.254的MAC,
构建ARP单播响应,目的MAC是f6:6b:60:7a:24:f2,源MAC是52:8f:7f:a6:f4:b1
根据fdb转发表查看发给f6:6b:60:7a:24:f2这个MAC表项出接口是Vxlan2.
三层路由出接口和二层的出接口必须一致,三层路由表项和二层转发表项都得有,不然会不通(两个表都会查)
arp单播响应也会进行vxlan封装
(5)主机1收到192.168.2.254的arp响应之后,开始构建发送icmp请求报文。
根据三层路由表和 fdb 转发表得知发往aa:f4:53:6c:aa:a6这个MAC的数据包需要走Vxlan1通道,进行vxlan封装:
ICMP报文
IP封装
源IP:192.168.1.100
目的IP:192.168.2.100
内层以太二层封装:
源MAC:vxlan1设备MAC
目的MAC:vxlan2设备MAC
vxlan封装
vni为100
UDP封装:
源端口随机端口,目的端口4789
外层VTEPIP封装:
源IP:10.33.30.150
目的IP:10.33.30.151
外层以太二层帧:
源MAC:本端VTEP接口的MAC
目的MAC:对端VTEP接口的MAC
(6)vxlan封装的ICMP请求报文到达主机2 VTEP设备,解封装之后二层目的MAC是vxlan设备的MAC(192.168.2.254/32),发现原始报文访问的是192.168.2.100,与本地不是同一网段(vxlan设备32位主机路由),查找路由表发现去往192.168.2.0/24网段的出接口是br2,使用src 192.168.2.1作为广播源,arp广播请求192.168.2.100的mac。
(7)ns2的tap1网卡收到arp请求会返回arp响应。
ce:25:e7:db:28:a0 --> br2 192.168.2.1网关的MAC
(8)得到mac之后,构建ICMP报文,目的MAC是192.168.2.100的MAC,根据br2转发表将数据从br2网桥的tap2设备转发出去,最终ns2中的tap1网卡会受到请求包。
报文封装如下:
ICMP报文
IP封装
源IP:192.168.1.100
目的IP:192.168.2.100
内层以太二层封装:
源MAC:br2设备MAC(192.168.2.1MAC)
目的MAC:192.168.2.100的MAC
回包逻辑大体同上。
问题3:为什么还要在vxlan设备上在配置IP地址,直接使用VTEP的地址可以吗?
- 在 VXLAN 设备上配置 IP 地址是为了实现 VXLAN 隧道的建立和维护,因为 VXLAN 隧道是基于 UDP 的,需要源 IP 和目的 IP 来标识不同的 VTEP。直接使用 VTEP 的地址可能会导致隧道建立失败或者隧道混乱。UDP 包里的源/目标 ip 应该是vxlan的。
- 在 VXLAN 设备上配置 IP 地址是为了实现分布式网关功能,即让 VXLAN 设备充当三层网关,处理跨子网的流量。这样可以避免集中式网关的转发路径不优化、ARP 或 ND 表项规格瓶颈等问题。
- 在 VXLAN 设备上配置 IP 地址是为了实现 BVI(Bridge Virtual Interface)功能,即让 VXLAN 设备充当二层网桥,处理同子网的流量。这样可以避免 MAC 地址表溢出、广播风暴等问题。
通信后状态
VXLAN 基础教程:VXLAN 协议原理介绍 - 知乎 (zhihu.com)