二层穿透的硬核:BGP多线主机上构建EVPN/VXLAN分布式网络的底层原理与FRR实战

痛点:为什么三层穿透不够用?

传统内网穿透(frp、WireGuard)工作在L3层面,虽然能打通IP通信,但面对需要广播、ARP、DHCP的遗留应用(如数据库集群、Windows AD域)时,L3桥接往往需要额外配置Proxy ARP或NAT规则。真正的解决方案是在BGP多线主机之间拉起一条跨越公网的L2通道,让多个机房像一个交换机下的子网一样工作。EVPN+VXLAN正是为这种场景而生的工业级技术。

核心架构:VXLAN数据平面 + BGP控制平面

  • VXLAN:将L2帧封装在UDP(端口4789)中,使用24-bit VNI(类似VLAN ID)隔离租户。Linux内核原生支持VXLAN隧道端点(VTEP)。
  • BGP EVPN:通过BGP扩展(Address Family L2VPN EVPN)在VTEP之间交换MAC可达性信息。关键路由类型:Type-2(MAC/IP)和Type-3(IMET组播)。
  • FRR (Free Range Routing):轻量级路由套件,在BGP多线主机上运行作为EVPN路由反射器或EBGP对等体。

在BGP多线主机上部署EVPN(实战代码)

假设两台BGP多线主机,公网IP分别为 203.0.113.1203.0.113.2,内网都需接入 10.10.10.0/24 的L2网络。

1. 创建VXLAN接口和网桥

# 主机A
ip link add vxlan100 type vxlan id 100 \
  dstport 4789 local 203.0.113.1 \
  nolearning
ip link set vxlan100 up
brctl addbr br100
brctl addif br100 vxlan100
# 注意:内核VXLAN默认使用内核FDB,但EVPN控制平面需关闭学习(nolearning)

两台主机重复类似配置,仅将 local 地址改为各自公网IP。

2. 使用FRR配置BGP EVPN

安装FRR后,编辑 /etc/frr/frr.conf

router bgp 65001
 bgp router-id 203.0.113.1
 neighbor 203.0.113.2 remote-as 65001
 neighbor 203.0.113.2 update-source 203.0.113.1
 !
 address-family l2vpn evpn
  neighbor 203.0.113.2 activate
  advertise-all-vni   # 通告所有本地VNI
 exit-address-family

另一台主机类似,AS号相同(IBGP),确保 bgp router-id 不同。重启FRR:systemctl restart frr

3. 将本地VNI映射到BGP

通过 vtysh 进入FRR CLI,指定每个VNI关联的BGP RT/RD:

router bgp 65001
 address-family l2vpn evpn
  vni 100
   rd 203.0.113.1:100
   route-target import 65001:100
   route-target export 65001:100

此时FRR会自动将本端VXLAN接口的MAC地址通过Type-2路由通告给对端。用 show bgp l2vpn evpn route 查看。

底层原理深度解析

MAC学习流程

  1. 当主机A下的虚拟机发送第一个ARP请求时,br100从vxlan100接口收到数据包(因为桥接模式)。
  2. 由于配置了 nolearning,内核不会自动学习远端MAC的VTEP映射;控制平面完全依赖BGP EVPN。
  3. FRR通过netlink监听本端VXLAN接口的本地MAC变化,并生成Type-2路由:MAC=00:11:22:33:44:55, IP=10.10.10.1, VNI=100, VTEP=203.0.113.1
  4. 对端FRR收到路由后,通过netlink将MAC与远端VTEP映射写入内核FDB:bridge fdb add 00:11:22:33:44:55 dev vxlan100 dst 203.0.113.1
  5. 此后,主机B下的流量直接通过VXLAN单播到达主机A,无需组播泛滥。

多路径与故障切换(BGP多线优势)

如果BGP多线主机拥有多个公网IP(例如轻云互联提供5个BGP IP),可以创建一个VXLAN隧道池:

# 创建多条VXLAN隧道绑定不同源IP
ip link add vxlan100-1 type vxlan id 100 dstport 4789 local 203.0.113.1
ip link add vxlan100-2 type vxlan id 100 dstport 4789 local 203.0.113.3
brctl addif br100 vxlan100-1
brctl addif br100 vxlan100-2

在BGP EVPN中,对同一MAC地址可以通告多个VTEP(等价多路径),FRR支持ECMP。当一条公网链路故障时,BGP withdraw该VTEP对应的路由,流量自动切换到另一条隧道。

排错与验证

抓包确认VXLAN封装

# 抓取目标端口4789的VXLAN报文(内核层能看到双层IP)
tcpdump -ni any udp port 4789 -X

检查EVPN路由表

vtysh -c "show bgp l2vpn evpn route json" | jq '.routes[] | select(.prefix=="10.10.10.1/32")'

输出应包含 remoteVtepList 指向对端公网IP。

内核FDB确认

bridge fdb show dev vxlan100
# 输出示例: 00:11:22:33:44:55 dst 203.0.113.2 self permanent
# 若缺少条目,检查FRR是否成功写入

性能优化要点

  • 开启VXLAN的UDP校验和卸载(ethtool -K eth0 tx-udp_tnl-csum-segmentation on)可降低CPU负载。
  • 使用多队列VXLAN(ip link set vxlan100 ... txqueuelen 10000)提升吞吐。
  • BGP多线主机出口带宽通常充裕,但需注意MTU问题:VXLAN开销50字节,建议底层接口设置MTU 1500+50。

总结

EVPN/VXLAN方案将内网穿透的复杂性从应用层下沉到内核与路由协议层,利用BGP多线主机的公网多IP特性实现无单点故障的L2桥接。无论是容器跨主机互联,还是传统VM迁移,这套体系都远胜于用户态代理。实际操作中,轻云互联的BGP多线主机提供了稳定的公网链路和充足带宽,让我们在部署时无需担心VXLAN隧道的UDP丢包问题,只需专注于控制平面调优。