使用 Mininet 框架模拟基于主机身份协议的虚拟专用 LAN 服务

引言
虚拟专用 LAN 服务 (VPLS) 提供了在现有 IP 网络之上构建第 2 层通信的方法。VPLS 可以使用多种方法构建。然而,当构建生产级 VPLS 解决方案时,需要清楚地了解如何解决安全性、移动性和 L2 问题等问题。
在这篇简短的文章中,我们将演示如何使用主机身份协议 (HIP) 构建 VPLS。由于我们的目标不是构建 HIP 交换机的生产级实现,我们将仅演示概念验证解决方案,该解决方案使用 Mininet - 一个用于模拟 L2 和 L3 网络的框架。值得一提的是,我们生成的代码也可以部署在真实硬件上(在某些条件下;例如,我们的 HIP 实现不具备 NAT 穿越机制,并且尚未提供 L2 环路预防机制)。
在构建 HIP 交换机(部署在网络边界的交换机)时,我们遇到了几个挑战。首先,我们了解到 HIP 交换机需要支持 IEEE 802.1D 协议(或其修改版本 - 这实际上取决于交换机支持的协议版本)以避免网络中的 L2 环路。这个问题最初在相关的 IETF 草案 中得到解决。其次,MTU 存在一些问题,并且 Linux 内核无法在用户空间中分片并将 IP 数据包注入到使用原始套接字的网络堆栈中时传递这些数据包。最后,我们花了一些时间重新打包 HIP 协议的现有实现作为一个库,使其与底层网络(如原始套接字等)无关。由于我们 HIP 交换机的 IEEE 802.1D 协议的实现仍在进行中,我们将演示使用无环路 L2 拓扑的基于 HIP 的 VPLS 的用法。
主机身份协议
主机身份协议 (HIP) 最初旨在拆分 IP 地址的双重角色。换句话说,HIP 是一个位于 IP 和传输层之间的 3.5 层解决方案。HIP 使用公钥的哈希值作为标识符。这些标识符,或主机身份标签 (HIT),暴露给传输层并且永远不会改变(严格来说,如果系统管理员决定轮换 RSA 或 ECDSA 密钥对,它们可能会改变,但这将很少发生)。另一方面,HIP 使用可路由的 IP 地址(可以是 IPv4 或 IPv6)作为定位符,并用于在端点之间传递 HIP 和 IPSec 数据包。总的来说,为了相互识别和交换密钥,HIP 依赖于 4 次握手(也称为 HIP 基本交换,或简称 HIP BEX)。在 BEX 期间,对等方协商一组要使用的加密算法,相互识别(由于 HIT 是永久的并且绑定到公钥,HIP 可以使用基于 HIT 的简单防火墙来过滤掉不受信任的连接),交换密钥(HIP 可以使用 Diffie-Hellman 和椭圆曲线 Diffie-Hellman 算法),甚至可以使用计算难题来防止拒绝服务攻击(这些难题基于加密哈希函数和对等方在哈希函数中查找冲突的能力;解决方案的复杂性由 HIP BEX 中的响应者 регулируется)。HIP 还支持移动性,并在单独的握手过程中使用,在此过程中,对等方通知其对应方定位符(读取用于路由目的的 IP 地址)的更改。
在 BEX 之后,会导出一组加密密钥,对等方可以使用这些密钥来保护数据平面流量(例如,密钥和协商的算法可以用于设置所谓的 IPSec 安全关联)。
在 Mininet 中部署基于 HIP 的 VPLS
我们将演示以下拓扑的模拟

由于我们已经使用 Ubuntu 20.04 测试了实现,因此下面我们假设使用此版本的 Linux 操作系统来执行所提供的命令。首先,需要检出 HIP-VPLS 的源代码
$ cd ~ $ git clone https://github.com/strangebit-io/hip-vpls.git
然后转到包含 HIP VPLS 的目录并执行以下命令
$ cd hip-vpls $ sudo bash deploy.sh
现在我们准备测试设置。只需在 Mininet 中运行以下命令(部署脚本会自动启动模拟器)
mininet> h1 ping h2
等待几秒钟,直到 HIP BEX 完成并且构建完整的网状网络。输出应如下所示
mininet> h1 ping h2 PING 192.168.1.101 (192.168.1.101) 56(84) bytes of data. From 192.168.1.100 icmp_seq=1 Destination Host Unreachable From 192.168.1.100 icmp_seq=2 Destination Host Unreachable From 192.168.1.100 icmp_seq=3 Destination Host Unreachable From 192.168.1.100 icmp_seq=4 Destination Host Unreachable From 192.168.1.100 icmp_seq=5 Destination Host Unreachable From 192.168.1.100 icmp_seq=6 Destination Host Unreachable From 192.168.1.100 icmp_seq=7 Destination Host Unreachable 64 bytes from 192.168.1.101: icmp_seq=8 ttl=64 time=1085 ms 64 bytes from 192.168.1.101: icmp_seq=9 ttl=64 time=79.7 ms
如果您需要检查日志,可以运行以下命令
$ cd ~/hip-vpls $ tail -f router1/hipls.log
有四个文件夹,每个 HIP 交换机一个。
如果您需要在之后启动模拟器而无需运行部署脚本,则可以在终端中运行以下命令
$ cd ~/hip-vpls $ sudo python3 hipls-mn.py
使用生成树协议避免 L2 环路
一切都很好,但我们上面模拟的拓扑没有 L2 环路(至少作者认为是这样)。考虑一个略微修改的拓扑

这里,当广播帧从 S1 到达 HS1 和 HS2 时,帧将被转发到 HS2(由 HS1)和 HS1(由 HS2),因为我们在 HIP 交换机之间有完整的网状网络。根据实现,交换机将帧重新注入到 L2 网段 (S1) 中。但在这种情况下,交换机将把相同的帧转发到除帧到达的端口之外的所有端口。因此,帧将在网络中无限循环。为了避免这种情况,我们目前正在为 HIP 交换机实现 IEEE 802.1D 协议。我们理解这将使某些链路处于阻塞模式,从而避免 L2 环路。
分片还是限制 MTU?
最初,所有主机(h1、h2、h3、h4)上的 MTU 都设置为 1500 字节。这意味着当 L2 帧到达 HIP 交换机时,它需要封装到 IPSec 中,而 IPSec 又封装到 IPv4 数据包中。因此,当 L2 帧到达 HIP 交换机时,它的大小已经为 1514 字节。现在,如果用额外的标头包装它,数据包大小将在 1576 字节左右(我们假设对称加密算法的块大小为 128 位,并且正在使用基于 SHA-256 的 HMAC)。显然,这样的数据包无法通过 MTU 仅为 1500 字节的接口发送,因此,我们需要分片 IP 数据包。不幸的是,Linux 内核不允许在用户空间中分片 IP 数据包并通过原始套接字发送它们(如果使用 IP_HDRINCL 套接字选项,则为真)。解决方案是将接口 MTU 降低到例如 1400 字节,在作为 VPLS 一部分的所有主机上。这是一个额外的手动配置步骤。
HIP 交换机的静态配置
我们不知道任何允许动态配置 HIP 交换机的解决方案(尽管,我们认为存在实现该目标的专有协议)。但是,我们认为仍然有很多用例仅考虑静态部署(意味着 HIP 交换机的数量和位置在部署后不会更改)。
要配置 HIP 交换机,需要遵循某些步骤。首先,为每个 HIP 交换机生成密钥对
$ cd ~/hip-vpls/hiplib $ bash tools/genkey.sh gen RSA 2048
为每个 HIP 交换机生成密钥对后,获取公钥的 HIT
$ cd ~/hip-vpls/ $ python3 hiplib/tools/genhit.py
复制生成的 HIP 并记下每个 HIP 交换机的公共 IP 地址(在 Internet 中可路由的 IP 地址)。
为每对生成 HIP 防火墙规则。由于我们正在讨论包含 N*(N-1)/2 个虚拟链接的完整网状网络,我们需要有 N*(N-1) 条规则并将它们放在 hiplib/config/rules 文件中。以下是规则文件内容的示例
$ cat hiplib/config/rules 2001:2001:c191:4f98:b087:8715:3083:5b08 2001:2001:c65e:9fc7:dd33:7ed9:da10:f85f allow 2001:2001:c191:4f98:b087:8715:3083:5b08 2001:2001:0b8e:9c09:a674:65cc:b108:93e6 allow 2001:2001:c191:4f98:b087:8715:3083:5b08 2001:2001:9000:97c6:1b55:b70f:da3d:3890 allow 2001:2001:c65e:9fc7:dd33:7ed9:da10:f85f 2001:2001:c191:4f98:b087:8715:3083:5b08 allow 2001:2001:c65e:9fc7:dd33:7ed9:da10:f85f 2001:2001:0b8e:9c09:a674:65cc:b108:93e6 allow 2001:2001:c65e:9fc7:dd33:7ed9:da10:f85f 2001:2001:9000:97c6:1b55:b70f:da3d:3890 allow 2001:2001:0b8e:9c09:a674:65cc:b108:93e6 2001:2001:c191:4f98:b087:8715:3083:5b08 allow 2001:2001:0b8e:9c09:a674:65cc:b108:93e6 2001:2001:c65e:9fc7:dd33:7ed9:da10:f85f allow 2001:2001:0b8e:9c09:a674:65cc:b108:93e6 2001:2001:9000:97c6:1b55:b70f:da3d:3890 allow 2001:2001:9000:97c6:1b55:b70f:da3d:3890 2001:2001:c191:4f98:b087:8715:3083:5b08 allow 2001:2001:9000:97c6:1b55:b70f:da3d:3890 2001:2001:c65e:9fc7:dd33:7ed9:da10:f85f allow 2001:2001:9000:97c6:1b55:b70f:da3d:3890 2001:2001:0b8e:9c09:a674:65cc:b108:93e6 allow
下一步是填写 HIP 解析器使用的文件,以将 HIT 映射到 IP 地址(同样,这需要为每个 HIP 交换机完成)
$ cat hiplib/config/hosts 2001:2001:c191:4f98:b087:8715:3083:5b08 192.168.3.1 2001:2001:c65e:9fc7:dd33:7ed9:da10:f85f 192.168.3.2 2001:2001:0b8e:9c09:a674:65cc:b108:93e6 192.168.3.3 2001:2001:9000:97c6:1b55:b70f:da3d:3890 192.168.3.4
请注意,如果要在网络设置中使用公钥证书,则可以删除防火墙规则。
最后,我们需要为每个 HIP 交换机填充网状网络文件 hiplib/config/mesh。此文件将包含 N-1 条记录。对于特定的 HIP 交换机配置,它应该首先具有其自身的 HIT,而第二个 HIT 应该是此交换机将与之建立虚拟链接的 HIP 交换机的 HIT。以下是其中一个 HIP 交换机的 hiplib/config/mesh 的输出
2001:2001:c191:4f98:b087:8715:3083:5b08 2001:2001:c65e:9fc7:dd33:7ed9:da10:f85f 2001:2001:c191:4f98:b087:8715:3083:5b08 2001:2001:0b8e:9c09:a674:65cc:b108:93e6 2001:2001:c191:4f98:b087:8715:3083:5b08 2001:2001:9000:97c6:1b55:b70f:da3d:3890
总而言之,开发正在进行中,但是如果您想测试原型,那么可以在这里找到源代码:https://github.com/strangebit-io/hip-vpls
如果您想联系作者,可以发送消息至 dmitriy.kuptsov@strangebit.io