使用VNET在FreeBSD上虚拟化您的网络

2020-12-30 22:01:37

FreeBSD Jails是一项众所周知的功能,并已成为FreeBSD上许多出色工具(例如Poudriere软件包生成器)的核心。 Jails提供了进程和文件系统隔离,但是很长一段时间以来,它们并没有提供令人满意的网络隔离。 VIMAGE为通过虚拟网络堆栈或VNET联网提供隔离。

VIMAGE最早是在2003年由Macro Zec在“在FreeBSD内核中实现可克隆的网络堆栈”一文中提出的,而VIMAGE代码首先出现在FreeBSD 8.0中,但是直到FreeBSD 12.0才将VIMAGE内置到FreeBSD GENERIC内核中。是一个被忽略的功能。

如果您曾经使用过监狱,那么您可能会想知道还有更多VNET监狱提供了什么,或者为什么要从使用基于localhost的网络进行迁移。 VNET监狱为每个监狱提供了自己的网络堆栈隔离副本。他们从IP层获取所有信息,创建一个完全由自己拥有的网络堆栈,几乎您可以使用监狱和VNET来处理不同主机的任何事情。

可以从主机为VNET网络堆栈提供接口,一旦将接口委派到VNET监狱中,该接口就会从主机视图中消失,仅在监狱中可见。 FreeBSD提供了充当虚拟以太网电缆的epair接口。将epair的一端提供给VNET监狱,将另一端保留在主机中,您便可以在主机和监狱之间甚至多个监狱之间建立网络连接。与普通的监狱网络不同,VNET监狱能够完全使用该接口,并且一旦获得正确的权限,它就可以像执行完整的主机一样执行数据包捕获和跟踪。

VNET允许监狱以更少的开销来接近完整的虚拟机,并且它们能够在与监狱主机非常相似的环境中隔离地测试网络。

尝试VNET的最佳方法是创建一些测试监狱并使用其网络。使用VNET,可以轻松又便宜地创建一个不会干扰主机配置的新的独立网络。

首先展示VNET提供的功能,我们将创建一个简单的监狱,仅将网络与主机隔离。如果我们在FreeBSD系统上运行以下三个命令,我们可以创建一个简单的监狱:

主机#jail -c name = emptyjail持久化vnet主机#jexec emptyjail / bin / sh emptyjail#ifconfig lo0:flags = 8008< LOOPBACK,MULTICAST> metric 0 mtu 16384 options = 680003< RXCSUM,TXCSUM,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6>组:lo nd6 options = 21< PERFORMNUD,AUTO_LINKLOCAL>

这里的jail命令的重要标志是persist和vnet,即使其中没​​有任何内容在运行,persist也可以保持监狱状态,vnet使用自己的VIMAGE网络堆栈来创建监狱。

我们创建的监狱包含一个环回接口(lo0),但无法从主机看到任何接口,它已在网络和进程级别隔离。由于我们没有指定要用于jails文件系统的新根目录,因此它可以像以前一样看到主机文件系统上的所有内容,这在开发和运行利用VNET的测试时非常方便。

为了使我们的监狱有用,我们需要能够访问网络接口,VNET监狱可以被赋予任何接口,一旦被赋予监狱,它们将从主机网络堆栈的角度消失。当我们想在主机和监狱之间建立网络时,可以使用epair(4)设备。 epair设备是一对背对背连接的类似以太网的接口,有点像仿真跳线。每一面都用字母表示,它们分别是“ a”和“ b”部分。如果我们创建一对,并将其中一半移入监狱,则一旦配置完成,便可以从主机与监狱进行通信。

主机#ja主机#ifconfig epair创建epair0a主机#ifconfig lo0:flags = 8049< UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384 options = 680003< RXCSUM,TXCSUM,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6> inet6 :: 1 prefixlen 128 inet6 fe80 :: 1%lo0 prefixlen 64 scopeid 0x2 inet 127.0.0.1 netmask 0xff000000组:lo nd6 options = 21< PERFORMNUD,AUTO_LINKLOCAL> epair0a:标志= 8842<广播,运行,简单,多播> metric 0 mtu 1500 options = 8< VLAN_MTU>以太网02:c5:7b:f8:1e:0a组:epair媒体:以太网10Gbase-T(10Gbase-T< full-duplex>)状态:有效的nd6选项= 29< PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL> epair0b:标志= 8842<广播,运行,简单,多播> metric 0 mtu 1500 options = 8< VLAN_MTU>以太网02:c5:7b:f8:1e:0b组:epair媒体:以太网10Gbase-T(10Gbase-T“全双工”)状态:有效的nd6选项= 29< PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>

这次,当我们创建监狱时,我们将一半的配对委托给它。我们需要在监狱和主机上配置接口。一旦我们配置了接口,就可以在主机和监狱之间进行通信(注意:将接口委托给监狱时,所有配置都将被删除。必须在接口进入监狱后对其进行配置)。

主机#jail -c name = networkjail持久化vnet vnet.interface = epair0b主机#jexec networkjail / bin / sh networkjail#ifconfig lo0:flags = 8008< LOOPBACK,MULTICAST> metric 0 mtu 16384 options = 680003< RXCSUM,TXCSUM,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6>组:lo nd6 options = 21< PERFORMNUD,AUTO_LINKLOCAL> epair0b:标志= 8842<广播,运行,简单,多播> metric 0 mtu 1500 options = 8< VLAN_MTU>以太网02:c5:7b:f8:1e:0b组:epair媒体:以太网10Gbase-T(10Gbase-T< full-duplex>)状态:有效的nd6选项= 21< PERFORMNUD,AUTO_LINKLOCAL> networkjail#ifconfig epair0b inet 192.0.2.2/24 up networkjail#退出主机#ifconfig epair0a inet 192.0.2.1/24 up host#ping 192.0.2.2 PING 192.0.2.2(192.0.2.2):56数据字节64个字节,来自192.0.2.2 :icmp_seq = 0 ttl = 64时间= 0.143 ms从192.0.2.2开始为64个字节:icmp_seq = 1 ttl = 64 time = 0.069 ms ^ C --- 192.0.2.2 ping统计信息---传输2个数据包,接收2个数据包,0.0最小/平均/最大/标准差往返丢包百分比= 0.069 / 0.106 / 0.143 / 0.037 ms

Python3已安装在主机上,并且由于我们的监狱无法隔离文件系统,因此所有已安装的软件也可用于该监狱。我们可以使用python3内置的http服务器来演示在监狱中运行的简单网络服务。

主机#jexec networkjail sh -c" cd / usr / src; python3 -m http.server"在0.0.0.0端口8000(http://0.0.0.0:8000/)上提供HTTP服务...

这样,主机上的Web浏览器可以指向192.0.2.2:8000,我们可以浏览/ usr / src中的FreeBSD源代码树的结构。我们可以在此VNET监狱中运行将在FreeBSD主机上运行的任何服务。较旧的监狱网络之间的区别在于,我们可以像使用真实网络接口那样进行配对来完成任何操作,例如将其添加到网桥。

当我们删除networkjail时,委派的epair的一半将返回给主机:

主机#ifconfig epair0b ifconfig:接口epair0b不存在主机#jls -v JID主机名路径名状态CPUSetID IP地址1 / networkjail ACTIVE 3主机#jail -r networkjail主机#ifconfig epair0b epair0b:标志= 8842 metric 0 mtu 1500 options = 8< VLAN_MTU>以太网02:c5:7b:f8:1e:0b组:epair媒体:以太网10Gbase-T(10Gbase-T< full-duplex>)状态:有效的nd6选项= 21< PERFORMNUD,AUTO_LINKLOCAL>

当我们消灭一半的epair时,即使将这半方下放到监狱,两半也会从系统中删除。

VNET通过与真实网络非常相似的网段为本地测试提供了便利。可以像在非虚拟网络接口上一样从主机执行任何操作,例如将其添加到网桥或防火墙。

使用VNET时,我们不仅限于使用虚拟接口,还可以将主机上的任何接口委托给VNET。 VNET开启了隔离大量网络的机会,使我们能够构建复杂的拓扑,例如软路由器和防火墙。

我们还可以使用VNET提供的隔离功能,在特定的接口上从主机提供服务,这可能是不希望的或具有破坏​​性的,或者如果设备使用的地址空间与主机所在的网络冲突,则可能会发生这种情况。

在此开发机器上,我们在两个不同的网络上具有网络接口,一个位于开发环境中,另一个位于沙盒测试环境中。数据包永远不能在两者之间传递。沙箱测试网络是虚拟机所在的位置,通常这些bhyve机器都配置有Tap接口,并且它们通过主机上的网桥接口加入网络。 VNET允许我们做同样的事情,但要有牢狱之灾。

在开始之前,我们需要在主机上加载用于epair和bridge的内核模块,当您尝试使用它们时,它们通常会自动在主机上加载,但是监牢无法做到这一点。

VNET还允许我们将开发主机上的物理网络接口提供给监狱,并从该监狱中创建与主机网络隔离的其他子VNET监狱:

这次,我们将children.max参数设置为1来创建监狱,以允许创建子监狱。在隔离的isojail中,我们可以创建一个桥和一个对,将其中的一半委派给下监狱。接下来,我们可以将真实的外部接口em0和一半的epair桥接在隔离的监狱isojail中。当创建更复杂的配置时,重要的是要确保所有接口都被启动,即使未为其分配任何地址,我们也要对作为isojail中网桥成员的epair0a端进行此操作。

主机#jexec isojail / bin / sh isojail#ifconfig网桥创建bridge0 isojail#ifconfig epair创建epair0a isojail#监狱-c名称= subjail持久化vnet vnet.interface = epair0b isojail#ifconfig bridge0 addm em0 addm epair0a up isojail#ifconfig epair0a up

通过设置监狱的层次结构以及桥接和委托接口,我们可以在沙盒网络上配置网络接口子监狱。沙箱网络提供了dhcp,因此我们要做的就是在子监狱中启动dhclient。

借助监狱层次结构和VNET,我们可以创建一个完整的子环境,其中包含它们自己的虚拟网络和真实网络视图。当您需要创建使用相同地址空间或不会被来自其他地方的流量污染的环境时,这将非常有用。

当您按Enter提交一些防火墙配置,然后一切都停止时,每个人都有恐怖的时刻。您想知道本地网络是否已关闭,或者主机是否出现打ic,最终您不得不承认您确定的新防火墙规则已将您锁定在计算机之外。

VNET监狱通过使用隔离的网络堆栈提供了一种安全的方法来测试防火墙配置。如果您使用错误的防火墙规则将自己拒之门外,则可以随时将jexec放进监狱,并清理错误。 FreeBSD中的所有三种防火墙都支持在VNET中运行(尽管尚不支持某些功能,例如带有ipfw的dummynet),并已作为使用VNET的FreeBSD防火墙测试套件的一部分进行了自动测试。

这样做的缺点是必须将要使用的防火墙的内核模块加载到主机上。这应该不会造成任何麻烦,但是发生的事情越多,不良互动的可能性就越大。首先,我们需要为ipfw加载内核模块并将其设置为默认允许流量:

主机#ifconfig epair创建epair0a主机#监狱-c名称= firewalljail坚持vnet vnet.interface = epair0b主机#ifconfig epair0a inet 192.0.2.2/24 up主机#jexec firewalljail / bin / sh Firewalljail#ifconfig lo0:标志= 8008 ,MULTICAST> metric 0 mtu 16384 options = 680003< RXCSUM,TXCSUM,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6>组:lo nd6 options = 21< PERFORMNUD,AUTO_LINKLOCAL> epair0b:标志= 8842<广播,运行,简单,多播> metric 0 mtu 1500 options = 8< VLAN_MTU> ether 02:46:6b:30:e6:0b组:epair媒体:以太网10Gbase-T(10Gbase-T< full-duplex>)状态:活动nd6选项= 21< PERFORMNUD,AUTO_LINKLOCAL> firewalljail#ifconfig epair0b inet 192.0.2.1/24 upfirewalljail#ping -c 1 192.0.2.2 PING 192.0.2.2(192.0.2.2):56数据字节来自192.0.2.2的64字节:icmp_seq = 0 ttl = 64时间= 0.124 ms --- 192.0.2.2 ping统计信息---发送的1个数据包,接收的1个数据包,0.0%的数据包丢失往返最小/平均/最大/标准差= 0.124 / 0.124 / 0.124 / 0.000毫秒Firewalljail#ipfw list 65535 allow ip from任何对任何

在监狱里,我们可以看到我们的ipfw实例具有自己的规则集,仅默认设置允许所有规则安装。我们还可以对主机对端的地址执行ping操作,以显示允许通过数据包。

当数据包被防火墙丢弃时,防火墙可以选择向我们发送ICMP错误消息,因此,不仅仅是超时ping还会告诉我们“发送至:拒绝权限”。我们可以在监狱中配置“拒绝所有”规则,并查看所有进出监狱的流量,而主机网络不受影响。

firewalljail#ipfw将100拒绝ip从任意值添加到任何00100拒绝ip从任意到任意防火墙jail#ping -c 1 192.0.2.2 PING 192.0.2.2(192.0.2.2):56个数据字节ping:sendto:权限被拒绝--- 192.0 .2.2 ping统计信息---传输1个数据包,接收0个数据包,100.0%数据包丢失

VNET监狱是FreeBSD的一项非常强大的功能,这些只是简单的示例,目的是演示它们的易用性以及测试的一些好处。如果曾经希望有额外的机器可以测试或使用其他网络接口,则可以使用VNET监狱重新创建大量该实用程序。带有嵌套的VNET监狱允许创建隔离的环境,该环境可以将测试环境与主机网络完全分开。

网络对于许多公司而言至关重要。如果您有FreeBSD网络实施或所需的驱动程序,我们的团队可以帮助您进一步努力。

在vnet文章中,您还可以提及/ usr / share / examples中的示例,并且它也可以与netgraph一起很好地用于有趣的拓扑。