实验室项目要求我要在一个 bgp 路由拓扑上做路由数据的采集,前脚刚走的学长就留了一个文档,剩下的只能让我自己来搞了。学长的文档还是挺详细的,但是拓扑构建的过程蛮复杂,在这里详细的记录一下,以防以后又要重新弄或者要交给学弟学妹的时候全忘光了
路由拓扑图如下:
环境依赖
Windows 11
WSL2 (Ubuntu)
Docker Desktop
Frrouting (Docker image)
Open vSwitch
环境配置 WSL WSL2 在 Windows 商店中直接下载 Ubuntu 即可,然后按照提示配置安装,基本不会遇到什么问题。
之所以要在这里提到 WSL 是因为我还是想在这里推广一下我们的北邮源 ,北邮源其实是清华源的镜像(没错,镜像的镜像),内容更新一样快但因为用的人少所以速度也非常快。如果你是 Ubuntu 22 LTS,只需要把 /etc/apt/source.list
中内容替换为如下内容即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 deb-src https://mirrors.bupt.edu.cn/ubuntu/ jammy main restricted deb https://mirrors.bupt.edu.cn/ubuntu/ jammy main restricted deb-src https://mirrors.bupt.edu.cn/ubuntu/ jammy multiverse universe deb https://mirrors.bupt.edu.cn/ubuntu/ jammy-updates main restricted deb-src https://mirrors.bupt.edu.cn/ubuntu/ jammy-updates restricted multiverse universe main deb https://mirrors.bupt.edu.cn/ubuntu/ jammy universe deb https://mirrors.bupt.edu.cn/ubuntu/ jammy-updates universe deb https://mirrors.bupt.edu.cn/ubuntu/ jammy multiverse deb https://mirrors.bupt.edu.cn/ubuntu/ jammy-updates multiverse deb https://mirrors.bupt.edu.cn/ubuntu/ jammy-backports main restricted universe multiverse deb-src https://mirrors.bupt.edu.cn/ubuntu/ jammy-backports main restricted universe multiverse deb https://mirrors.bupt.edu.cn/ubuntu/ jammy-security main restricted deb-src https://mirrors.bupt.edu.cn/ubuntu/ jammy-security restricted deb https://mirrors.bupt.edu.cn/ubuntu/ jammy-security universe deb https://mirrors.bupt.edu.cn/ubuntu/ jammy-security multiverse
你也可以直接运行下面的代码,更方便的替换源
1 sudo sed -i 's#http://archive.ubuntu.com/#http://mirrors.bupt.edu.cn/#g' /etc/apt/sources.list
相信我,速度真的很快
Docker Desktop 直接到官网 下载 Windows 版本即可。然后需要在 WSL 已经安装的前提下,打开 Setting - Resources - WSL Integration
,打勾和开关全部拉满。
最后是 Docker 下载镜像也需要换源。网络上很多教程经常提到中科院的 Docker 源,但是现在这玩意已经变成他们校内资源了,所以还是推荐使用网易和阿里云自注册 的 Docker 源。Docker Desktop 的换源位置在 Setting - Docker Engine
的 json 文件中,加入如下内容即可
1 2 3 4 "registry-mirrors" : [ "https://xxxxxx.mirror.aliyuncs.com" , "http://hub-mirror.c.163.com" ]
xxxxxx 的内容是你在阿里云中注册就能免费拿到的,还是挺靠谱的
Open vSwitch 我发现网上的 Open vSwitch(以下简称 ovs)安装教程基本都是通过源码安装的,即使是学长给我的文档也是这样。源码安装不仅麻烦还得搭配各种奇怪的环境,非常费时费力。我上 Google 查一下,原来 apt 能直接傻瓜安装,真的搞不懂为什么这么多人喜欢捣鼓这东西的源码安装
在 WSL 里直接运行如下指令即可:
1 sudo apt-get install openvswitch-switch
然后用ovs-vswitchd --version
检查是否安装成功就行了
Frrouting 由于要搭建拓扑,需要通过 Docker 模拟多个路由器,所以只需要安装 Frrouting 的镜像就行了。而这玩意百度一搜,国内的什么简书、csdn 各大高手的教程又开始源码安装了。我反手 Google 一下,第一页就是 Docker 官网 ,里面直接告诉我一条命令就能搞定:
1 docker pull frrouting/frr
到此环境就配置完了,别看这部分这么简单,如果只看国内这些“大神”们的教程,能给你配一整天。
拓扑环境搭建 对于一台计算机来说,只要它启动了bgpd
守护进程,那么它即可承担 BGP 路由器的全部功能。目前 BGP 协议的开源实现主要就是 C-BGP 和 FRRouting 。每台计算机上只能跑一个 bgpd
进程,但使用 Docker 可以实现多机虚拟化,且 FRRouting 提供了封装好的 Docker 镜像,所以推荐使用 FRRouting 。这种情况下,一台机器上的每一个 FRRouting 的 Docker 实例就可以看做是一个独立的虚拟机,每个虚拟机上仅运行了 bgpd
进程及其依赖的进程。
但如果直接在一台机器上跑多个 FRRouting 的 Docker 容器的话,是无法看到 AS 路径的,因为这种情况下,所有的 Docker 实例均在同一个网段下,是可以直连通信的,无法模拟域间路由下的“多跳”环境。
这要求我们实现一个模拟域间路由下“多跳”的方式:手动将这些 AS 划分到不同的子网下。这需要使用 Open vSwitch 的网桥相关的功能。编写一个脚本文件ovs.sh
,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 #!/bin/bash ovs-vsctl add-br brConn ovs-docker add-port brConn ethTo65533 AS65531 --ipaddress=100.100.7.1/30 ovs-docker add-port brConn ethTo65531 AS65533 --ipaddress=100.100.7.2/30 ovs-docker add-port brConn ethTo65534 AS65531 --ipaddress=100.100.8.1/30 ovs-docker add-port brConn ethTo65531 AS65534 --ipaddress=100.100.8.2/30 ovs-docker add-port brConn ethTo65533 AS65532 --ipaddress=100.100.9.1/30 ovs-docker add-port brConn ethTo65532 AS65533 --ipaddress=100.100.9.2/30 ovs-docker add-port brConn ethTo65534 AS65532 --ipaddress=100.100.10.1/30 ovs-docker add-port brConn ethTo65532 AS65534 --ipaddress=100.100.10.2/30 ovs-docker add-port brConn ethTo65534 AS65533 --ipaddress=100.100.11.1/30 ovs-docker add-port brConn ethTo65533 AS65534 --ipaddress=100.100.11.2/30 ovs-docker add-port brConn ethTo65535 AS65533 --ipaddress=100.100.12.1/30 ovs-docker add-port brConn ethTo65533 AS65535 --ipaddress=100.100.12.2/30 ovs-docker add-port brConn ethTo65535 AS65534 --ipaddress=100.100.13.1/30 ovs-docker add-port brConn ethTo65534 AS65535 --ipaddress=100.100.13.2/30 ovs-docker add-port brConn ethTo65531 AS65536 --ipaddress=100.100.14.1/30 ovs-docker add-port brConn ethTo65536 AS65531 --ipaddress=100.100.14.2/30 ovs-docker add-port brConn ethTo65532 AS65536 --ipaddress=100.100.15.1/30 ovs-docker add-port brConn ethTo65536 AS65532 --ipaddress=100.100.15.2/30 ovs-docker add-port brConn eth1 AS65531 --ipaddress=104.193.81.1/24 ovs-docker add-port brConn eth1 AS65532 --ipaddress=104.193.82.1/24 ovs-docker add-port brConn eth1 AS65533 --ipaddress=104.193.83.1/24 ovs-docker add-port brConn eth1 AS65534 --ipaddress=104.193.84.1/24 ovs-docker add-port brConn eth1 AS65536 --ipaddress=104.193.86.1/24
这个脚本首先创建了一个网桥 brConn(可以将它简单理解为一个交换机)。第二部分内容就是使用 ovs 提供的接口,为 Docker 实例创建网卡,并将网卡全部挂接到同一个 brConn 网桥上。网卡名字为 eThTo**** ,表示这个 Docker 实例中的这张网卡是为了去与哪个 Docker 进行直连通信。第三部分的内容是为 AS 设立它们的合法网络空间(或者说网络资源)。
注意到所有的网卡前缀长度均是 30 位,这意味着这个子网下只有两个 IP 地址是合法的(子网可用 2 位,最多有 4 个 IP 地址,扣除掉两位全为 0 的和两位全为 1 的非法地址),这两个 IP 地址分别作为具有直连关系的两个 AS 间的链路两端网卡的 IP 地址,这样就实现了网络隔离,换句话说,在上述拓扑示例图中,只有具有直连关系的 AS 是在同一个网段下的,可以相互通信,不具有直连关系的 AS 不再同一个网段内,不能直连通信。
接下来需要运行如下所示的docker.sh
脚本,它启动了 6 个 FRRouting Docker 实例。默认情况下,FRRouting 的实例仅包括一个本地回路网卡和另一个 Docker 自带的网卡,这两个网卡都不是我们要用的。我们需要使用之前 ovs 创建的虚拟网卡。
1 2 3 4 5 6 7 8 9 #!/bin/bash docker run -itd --privileged --name AS65531 --net=none frrouting/frr /bin/bash docker run -itd --privileged --name AS65532 --net=none frrouting/frr /bin/bash docker run -itd --privileged --name AS65533 --net=none frrouting/frr /bin/bash docker run -itd --privileged --name AS65534 --net=none frrouting/frr /bin/bash docker run -itd --privileged --name AS65535 --net=none frrouting/frr /bin/bash docker run -itd --privileged --name AS65536 --net=none frrouting/frr /bin/bash
另一个脚本是 destroyAllTopo3.sh
,会销毁掉 brConn 以及对应的网卡,并移除所有运行中的 Docker 实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #!/bin/bash ovs-vsctl del-br brAS65531 ovs-vsctl del-br brAS65532 ovs-vsctl del-br brAS65533 ovs-vsctl del-br brAS65534 ovs-vsctl del-br brConn ovs-vsctl del-br br1To3 ovs-vsctl del-br br1To4 ovs-vsctl del-br br2To3 ovs-vsctl del-br br2To4 ovs-vsctl del-br br3To4 ovs-vsctl del-br br3To5 ovs-vsctl del-br br4To5 docker rm -f $(docker ps -aq)
拓扑节点配置 请严格 按照如下顺序执行配置
开启 ovs 服务
1 sudo /usr/share/openvswitch/scripts/ovs-ctl start
用 root 权限**先后 **执行docker.sh
和ovs.sh
,创建出 6 个 Frrouting 实例
对于这 6 个实例(AS65531 ~ AS65536)中的每一个,使用命令docker exec -it (ASN_NAME) bash
进入到实例中,然后对 6 个实例的每一个,执行下述命令,这三条命令会在容器中启动bgpd
守护进程和ospfd
守护进程。
1 2 3 sed -i 's/bgpd=no/bgpd=yes/g' /etc/frr/daemons sed -i 's/ospfd=no/ospfd=yes/g' /etc/frr/daemons nohup /usr/lib/frr/frrinit.sh start &
仍然使用docker exec -it (ASN_NAME) bash
进入到实例中,对于 6 个实例的每一个,根据ASN_NAME
的不同,拷贝下述命令到终端中并执行:
1 2 3 4 5 6 7 8 9 10 11 12 13 vtysh config router bgp 65536 neighbor 100.100.14.2 remote-as 65531 neighbor 100.100.15.2 remote-as 65532 network 104.193.86.1/24 no bgp ebgp-requires-policy no bgp network import-check exit exit write exit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 vtysh config router bgp 65531 neighbor 100.100.7.2 remote-as 65533 neighbor 100.100.8.2 remote-as 65534 neighbor 100.100.14.1 remote-as 65536 network 104.193.81.1/24 no bgp ebgp-requires-policy no bgp network import-check exit exit write exit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 vtysh config router bgp 65532 neighbor 100.100.9.2 remote-as 65533 neighbor 100.100.10.2 remote-as 65534 neighbor 100.100.15.1 remote-as 65536 network 104.193.82.1/24 no bgp ebgp-requires-policy no bgp network import-check exit exit write exit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 vtysh config router bgp 65533 neighbor 100.100.7.1 remote-as 65531 neighbor 100.100.9.1 remote-as 65532 neighbor 100.100.11.2 remote-as 65534 neighbor 100.100.12.2 remote-as 65535 network 104.193.83.1/24 no bgp ebgp-requires-policy no bgp network import-check exit exit write exit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 vtysh config router bgp 65534 neighbor 100.100.8.1 remote-as 65531 neighbor 100.100.10.1 remote-as 65532 neighbor 100.100.11.1 remote-as 65533 neighbor 100.100.13.2 remote-as 65535 network 104.193.84.1/24 no bgp ebgp-requires-policy no bgp network import-check exit exit write exit
1 2 3 4 5 6 7 8 9 10 11 12 vtysh config router bgp 65535 neighbor 100.100.12.1 remote-as 65533 neighbor 100.100.13.1 remote-as 65534 no bgp ebgp-requires-policy no bgp network import-check exit exit write exit
这些命令首先会启动 vtysh 终端(这是一个现有的 BGP 协议通用的控制终端,大部分的 BGP 协议实现都会用这个相同的终端),然后将配置对应的 AS 号、通过给出的 IP 地址与邻居建立 Peer 关系,宣告自己的前缀,并设置了两个路由策略(no ebgp-requires-policy
, no bgp network import-check
),这两个策略是必须的,否则路由器会过滤掉路由宣告。
拓扑实验 路由信息查看 全部设置完毕后,随便找一个实例进入,启动 vtysh 终端,使用命令show ip bgp
,会看到类似下图的 BGP 路由表;
而命令show ip bgp summary
能看到 BGP 邻居表,具体细节可以看这里
需要注意的是,由于这个拓扑是静态的,因此第一次查看路由表应该只能看到本地路由,如果想看到整个拓扑的路由表请往下看。
数据采集 可以使用以下命令配置 Frrouting 的日志输出,通过查看日志及时 Debug:
1 2 3 4 5 6 7 8 9 mkdir /var/log/frrchown frr /var/log/frr/vtysh config log file /var/log/frr/frr.logexit write
使用下述命令转储路由更新信息:
1 2 3 4 5 6 7 8 9 10 11 12 mkdir /home/updateschown frr updatesvtysh config dump bgp updates /home/updates/%Y%m%d-%H:%M:%S 30 // 每30sdump一次路由更新报文
上述命令只会 dump 路由更新报文(MRT 格式,需要bgpdump
等工具进一步解析),由于拓扑是稳定的、不会更新的,因此大部分情况下输出的都是空文件,你可以选择一个 AS 去使用 network 命令宣告个长度大于等于 25 的前缀。注意这个宣告的前缀必须属于这个 AS 的合法前缀空间。例如 AS65536 拥有的网络资源为 104.193.86.1/24
,那么在 AS65536 的 vtysh 终端就能使用命令network 104.193.86.2/25
宣告一个合法的前缀。需要注意的是,至少发生一次路由宣告后 ,整个拓扑的路由表才会更新。
转储出的文件是存储在 docker 实例中的,由于默认的 docker 实例并没有挂载持久化存储,因此无法直接把转储出的文件从容器中转移到 WSL 上,需要在 root 权限下使用 docker cp
命令,例如:
1 docker cp 2cd200541a0b:/home/updates/20220931-06:19:30 .
这样以后就能把采集到的 BGP 路由数据存储到本地了