Loading

用VPP软件交换机连接QEMU KVM虚拟机

假设FD.io VPP已经装好,并且可以用QEMU创建和启动 virtual machines。

参考官方实验:FD.io VPP with Virtual Machines

1. 简介

1.1 靶场拓扑介绍

这个仿真靶场平台的实验,可以用一台物理服务器做实验,也可以跨越两台物理服务器作实验。

  • 如果一台服务器作实验:可以把攻击机Kali Linux和预置漏洞的靶机Metasploitable运行在同一台服务器上。这台服务器并不需要有万兆光纤网卡,只需要用桥接模式的vpp软件交换机来连接两台虚拟机。

  • 如果两台服务器做实验:可以一台运行攻击机Kali Linux,另外一台部署预置漏洞的靶机Metasploitable。两台服务器通过万兆光纤网卡连接,两台服务器上分别起桥接模式的VPP软件交换机。如下图所示,右边服务器上的VPP软件交换机启动了桥接模式,连接了万兆光纤物理网卡和虚拟网卡。

    $ ping 192.168.100.3  
    64 bytes from 192.168.100.3: icmp_seq=492 ttl=64 time=0.104 ms
    64 bytes from 192.168.100.3: icmp_seq=493 ttl=64 time=0.063 ms
    ...
    

1.2 KVM虚拟化简介

KVM虚拟机(名称来自英语: Kernel-based Virtual Machine 的缩写,即基于内核的虚拟机),是一种用于Linux内核中的虚拟化基础设施,可以将Linux内核转化为一个虚拟机hypervisor。KVM由Quramnet公司于开发(2008年被 Red Hat 收购),从 Linux 2.6.20 起就作为模块被包含在 Linux 内核中。

KVM虚拟机需要宿主机的CPU能支持硬件虚拟化扩展(比如, Intel VT or AMD-V)。下面的命令可以校验宿主机cpu的硬件虚拟化支持。

egrep '(vmx|svm)' --color /proc/cpuinfo

如果输出结果不包含vmx 或者 svm 标志,这意味着宿主机CPU没有hardware virtualization支持。这样你就没法在宿主机上使用KVM。验证过宿主机cpu可以支持vmx或svm特性,下面才可以继续安装KVM。参考:How to use KVM from the command line on Debian or Ubuntu

参考资料:云计算与虚拟化技术发展编年史,以及虚拟化技术实现 — QEMU-KVM & Libvirt,以及虚拟化技术实现 — KVM 的 CPU 虚拟化

2. 配置网卡

注意:要停止所有实验时,首先需要在QEMU界面里关掉所有虚拟机,然后再重启vpp软件交换机。

virsh list --all
virsh destroy Kali-Linux-2021.2-virtualbox-amd64
virsh destroy metasploitable-linux-2.0.0
virsh list --all

sudo vppctl "set interface l2 bridge VirtualEthernet0/0/0 0"
sudo vppctl "set interface l2 bridge VirtualEthernet0/0/1 0"
sudo vppctl "set interface l2 bridge TenGigabitEthernet86/0/0 0"
sudo vppctl "set interface l2 bridge host-vpp-out0  0"
sudo vppctl "create bridge-domain 100 del"

sudo vppctl "delete vhost-user VirtualEthernet0/0/0" #VPP删除vhost-user接口命令
sudo vppctl "delete vhost-user VirtualEthernet0/0/1" #VPP删除vhost-user接口命令
sudo rm /tmp/vm00.sock
sudo rm /tmp/vm01.sock
sudo vppctl "clear interfaces"

# 该命令会自动删除成对存在的两个虚拟网卡
sudo ip link delete dev vpp-host0

# 停止vpp服务
sudo service vpp stop
sudo ifconfig nic0 down

2.1 绑定物理网卡(如果服务器上有万兆网卡,想跨服务器作大型实验)

先查看本地物理主机inspur1的光纤卡pcie地址

$ sudo lshw -class network -businfo

Bus info          Device      Class          Description
========================================================
pci@0000:1a:00.0  eth0        network        Ethernet Connection X722 for 1GbE
pci@0000:1a:00.1  eth1        network        Ethernet Connection X722 for 1GbE
pci@0000:af:00.0  nic0        network        Ethernet Controller XXV710 for 25Gb
pci@0000:af:00.1  nic1        network        Ethernet Controller XXV710 for 25Gb
                  virbr0-nic  network        Ethernet interface

修改vpp启动配置文件,位置/etc/vpp/startup.conf,把下面配置信息插入,目前只利用nic0到另外一台服务器的光纤连接,所以只配置nic0的信息。

dpdk {
	socket-mem 1024 #更改每个套接字的大页面分配 默认值256
	dev 0000:af:00.0{  #根据服务器上的光纤网卡的情况修改,我用的是X710网卡的第一个网口
		name TenGigabitEthernet86/0/0
	}
	uio-driver vfio-pci  ## dpdk driver for nic0
}

重新开启vpp,查看此时的网卡信息

sudo ifconfig nic0 down
sudo service vpp start

2.2 在VPP中创建虚拟网口,等待连接虚拟机

Virtio networking (virtio-net)介绍:这是Linux KVM虚拟化方案中宿主机host和客户虚拟机guest之间的网络通信协议。下图展示了基于virtio虚拟网络的系统架构。可以看到宿主机的vhost和虚拟机guest之间建立了virtio网络连接。

在 vhost 的方案中,由于 vhost 实现在内核中,guest 与 vhost 的通信,相较于原生的 virtio 方式性能上有了一定程度的提升,从 guest 到 kvm.ko 的交互只有一次用户态的切换以及数据拷贝。这个方案对于不同 host 之间的通信,或者 guest 到 host nic 之间的通信是比较好的,但是对于某些用户态进程间的通信,比如数据面的通信方案,vpp、openvswitch 和与之类似的 SDN 的解决方案,guest 需要和 host 用户态的 vswitch 进行数据交换,如果采用 vhost 的方案,guest 和 host 之间又存在多次的上下文切换和数据拷贝,为了避免这种情况,业界就想出将 vhost 从内核态移到用户态。这就是 vhost-user 的实现。

首先将用create vhost-user命令,创建虚拟网口。vhost-user 基于 C/S 的模式,采用 UNIX 域套接字(UNIX domain socket)来完成进程间的事件通知和数据交互,相比 vhost 中采用 ioctl 的方式,vhost-user 采用 socket 的方式大大简化了操作。该命令用法如下。其作用是在VPP软件交换机中创建虚拟网口,并创建linux套接字,让虚拟机可以连接VPP软件交换机。这个命令既可以把VPP启动成套接字server,也可以作client。

create vhost-user socket <socket-filename> [server] [feature-mask <hex>] [hwaddr <mac-addr>] [renumber <dev_instance>]

然后用如下命令清除旧的网络连接,确保干净的环境。

sudo vppctl "delete vhost-user VirtualEthernet0/0/0" #VPP删除vhost-user接口命令
sudo vppctl "delete vhost-user VirtualEthernet0/0/1" #VPP删除vhost-user接口命令
sudo rm /tmp/vm00.sock
sudo rm /tmp/vm01.sock
sudo vppctl "clear interfaces"

下面用create vhost-user命令创建两个虚拟网口,对应到两个kvm虚拟机。

$ sudo vppctl  "create vhost-user socket /tmp/vm00.sock"  ## veth for Kali Linux
VirtualEthernet0/0/0

$ sudo vppctl  "create vhost-user socket /tmp/vm01.sock"  ## veth for metasploitable2
VirtualEthernet0/0/1

$ sudo vppctl  "show int"
              Name               Idx    State  MTU (L3/IP4/IP6/MPLS)     Counter          Count     
TenGigabitEthernet86/0/0          1     down         9000/0/0/0     
VirtualEthernet0/0/0              2     down         9000/0/0/0     
VirtualEthernet0/0/1              3     down         9000/0/0/0     
local0                            0     down          0/0/0/0      
  • 这里应该可以看到名字是TenGigabitEthernet86/0/0的DPDK驱动绑定的物理网卡。
  • 注意这里的虚拟网卡 VirtualEthernet0/0/0。这里把VPP的虚拟以太网卡创建成了client模式。如果把VPP启动成server模式,意味着如果VPP进程崩溃了,所有连接在上面的虚拟机都需要重启。相反来说,如果把VPP启动成client模式,QEMU虚拟机启动成server模式,意味着VPP进程崩溃了也可以重启,然后重新连接各台QEMU虚拟机。

最后可以用 Show Vhost-User 命令测试一下vhost连接。

$ sudo vppctl  "show vhost"

Virtio vhost-user interfaces
Global:
  coalesce frames 32 time 1e-3
  Number of rx virtqueues in interrupt mode: 0
  Number of GSO interfaces: 0
  Thread 0: Polling queue count 2
Interface: VirtualEthernet0/0/0 (ifindex 2)
  Number of qids 2
virtio_net_hdr_sz 12
 features mask (0xfffffffbdfffa27c): 
 features (0x150208000): 
   VIRTIO_NET_F_MRG_RXBUF (15)
   VIRTIO_NET_F_GUEST_ANNOUNCE (21)
   VIRTIO_RING_F_INDIRECT_DESC (28)
   VHOST_USER_F_PROTOCOL_FEATURES (30)
   VIRTIO_F_VERSION_1 (32)
  protocol features (0x3)
   VHOST_USER_PROTOCOL_F_MQ (0)
   VHOST_USER_PROTOCOL_F_LOG_SHMFD (1)

 socket filename /tmp/vm00.sock type client errno "No such file or directory"

 rx placement: 
   thread 0 on vring 1, polling
 tx placement
   threads 0 on vring 0: lock-free

 Memory regions (total 0)

Interface: VirtualEthernet0/0/1 (ifindex 3)
  Number of qids 2
virtio_net_hdr_sz 0
 features mask (0xfffffffbdfffa27c): 
 features (0x0): 
  protocol features (0x0)

 socket filename /tmp/vm01.sock type client errno "Connection refused"

 rx placement: 
   thread 0 on vring 1, polling
 tx placement

 Memory regions (total 0)

注意这里的 No such file or directoryMemory regions (total 0),因为虚拟机还没创建出来。

3. 创建QEMU虚拟机

使用 “virsh create command”命令创建QEMU虚拟机。关于 virsh 更多信息,请查看 virsh man page

注意,由于这里使用了vhost-user端口,要求QEMU版本大于2.7。可以通过kvm命令验证一下。

$ kvm --version
QEMU emulator version 2.11.1(Debian 1:2.11+dfsg-1ubuntu7.36)
Copyright (c) 2003-2017 Fabrice Bellard and the QEMU Project developers

3.1 准备libvert和qemu虚拟软件

Libvirt简介
Libvirt 是一组软件的汇集,提供了管理虚拟机和其它虚拟化功能(如:存储和网络接口等)的便利途径。这些软件包括:一个长期稳定的 C 语言 API、一个守护进程(libvirtd)和一个命令行工具(virsh)。Libvirt 的主要目标是提供一个单一途径以管理多种不同虚拟化方案以及虚拟化主机,包括:KVM/QEMU,Xen,LXC,OpenVZ 或 VirtualBox hypervisors

Libvirt 的一些主要功能如下:

  • VM management(虚拟机管理):各种虚拟机生命周期的操作,如:启动、停止、暂停、保存、恢复和迁移等;多种不同类型设备的热插拔操作,包括磁盘、网络接口、内存、CPU等。
  • Remote machine support(支持远程连接):Libvirt 的所有功能都可以在运行着 libvirt 守护进程的机器上执行,包括远程机器。通过最简便且无需额外配置的 SSH 协议,远程连接可支持多种网络连接方式。
  • Storage management(存储管理):任何运行 libvirt 守护进程的主机都可以用于管理多种类型的存储:创建多种类型的文件镜像(qcow2,vmdk,raw,…),挂载 NFS 共享,枚举现有 LVM 卷组,创建新的 LVM 卷组和逻辑卷,对裸磁盘设备分区,挂载 iSCSI 共享,以及更多……
  • Network interface management(网络接口管理):任何运行 libvirt 守护进程的主机都可以用于管理物理的和逻辑的网络接口,枚举现有接口,配置(和创建)接口、桥接、VLAN、端口绑定。
  • Virtual NAT and Route based networking(虚拟 NAT 和基于路由的网络):任何运行 libvirt 守护进程的主机都可以管理和创建虚拟网络。Libvirt 虚拟网络使用防火墙规则实现一个路由器,为虚拟机提供到主机网络的透明访问。

Libvirt启动虚拟机可以使用命令行带参数的方式启动虚拟机,也可是使用xml的方式编排虚拟机。本环境使用xml方式部署虚拟机。

用QEMU的KVM虚机加载RAW磁盘镜像,并且用的是软件交换机vpp的vhost-user虚拟网络连接。这要求虚拟机必须用超大页。

prealloced numa-mode memory启动。Since hugepages are also being used by VPP (only 1024 by default), it is necessary to allocate more (how much will vary depending on the VM, and should be selected pending your system's available RAM):

sudo sysctl -w vm.nr_hugepages=4096

现在创建虚拟机。virsh list 可以显示创建出的虚拟机。开始的时候没有任何虚机。

$ virsh list --all
Id    Name                           State
----------------------------------------------------

如果有尚未关闭的虚拟机,比如Kali-Linux-2021.2-virtualbox-amd64。则可以用virsh destroy Kali-Linux-2021.2-virtualbox-amd64销毁。

3.2 制作和启动kali linux虚拟机镜像

制作一个Kali Linux的kvm磁盘镜像,采用img后缀的RAW镜像。

首先,下载VirtualBox可以加载的Kali Linux最新版本的OVA格式镜像,比如kali-linux-2021.2-virtualbox-amd64.ova。并且在VirtualBox中导入该OVA镜像。注意:Kali虚拟机的ova镜像导入VirtualBox以后,还在启动前需要对虚拟机作硬件设置。请参考【SEED虚拟机的导入设置方法】。导入后的虚机目录里可以找到VDI格式虚拟磁盘。

然后,用如下的vboxmanage clonehd命令,将VirtualBox的VDI格式虚拟磁盘转成KVM可直接访问的img后缀原始RAW格式磁盘。参考:How to Use Virtualbox VMs on KVM In Linux: Convert VirtualBox VDI Disk Format to RAW Image

vboxmanage clonehd --format RAW /media/wxg/28CCF498CCF4620C/VirtualBox\ VMs/Kali-Linux-2021.2-virtualbox-amd64/Kali-Linux-2021.2-virtualbox-amd64-disk001.vdi /media/wxg/28CCF498CCF4620C/virtual_machines/Kali-Linux-2021.2-virtualbox-amd64.img

下面,virsh工具支持xml格式的虚拟机配置文件,可避免用qemu-system-x86_64命令行的方式管理繁琐的虚拟机参数。请下载链接里的配置内容,取名为Kali-Linux-2021.2-virtualbox-amd64.xml。XML配置文件中的含义解释参考说明文件

根据自己的环境,修改xml配置文件中的虚拟机名称、系统唯一uuid号码、内存空间大小等信息,特别是修改放置Kali-Linux-2021.2-virtualbox-amd64.img的路径。

然后,用 virsh create 命令创建KVM虚拟机 ,同时指定虚拟机xml配置。

$ cd /media/wxg/28CCF498CCF4620C/virtual_machines ## 改成你自己放虚拟机配置文件的目录
$ virsh create ./Kali-Linux-2021.2-virtualbox-amd64.xml
Domain Kali-Linux-2021.2-virtualbox-amd64 created from ./Kali-Linux-2021.2-virtualbox-amd64.xml

$ virsh list
 Id    Name                           State
----------------------------------------------------
 3     Kali-Linux-2021.2-virtualbox-amd64 running

现在虚拟机创建好了。注意到,可以利用 “virsh dumpxml”命令来生成当前虚拟机对应的xml配置文件。

$ virsh dumpxml Kali-Linux-2021.2-virtualbox-amd64
<domain type='kvm' id='65'>
  <name>iperf-server3</name>
  <uuid>e23d37c1-10c3-4a6e-ae99-f315a4165641</uuid>
  <memory unit='KiB'>262144</memory>
.....

一旦虚拟机创建好了,注意到pp的套接字文件名将显示 Success,并且 Memory Regions也被创建出来。这个时和 VM 和 FD.io VPP 已经连接起来。

$ sudo vppctl "show vhost"

Virtio vhost-user interfaces
Global:
  coalesce frames 32 time 1e-3
  number of rx virtqueues in interrupt mode: 0
Interface: VirtualEthernet0/0/0 (ifindex 3)
virtio_net_hdr_sz 12
 features mask (0xffffffffffffffff):
 features (0x58208000):
   VIRTIO_NET_F_MRG_RXBUF (15)
   VIRTIO_NET_F_GUEST_ANNOUNCE (21)
   VIRTIO_F_ANY_LAYOUT (27)
   VIRTIO_F_INDIRECT_DESC (28)
   VHOST_USER_F_PROTOCOL_FEATURES (30)
  protocol features (0x3)
   VHOST_USER_PROTOCOL_F_MQ (0)
   VHOST_USER_PROTOCOL_F_LOG_SHMFD (1)

 socket filename /tmp/vm00.sock type client errno "Success"

 rx placement:
   thread 1 on vring 1, polling
 tx placement: spin-lock
   thread 0 on vring 0
   thread 1 on vring 0

 Memory regions (total 2)
 region fd    guest_phys_addr    memory_size        userspace_addr     mmap_offset        mmap_addr
 ====== ===== ================== ================== ================== ================== ===============    ===
  0     31    0x0000000000000000 0x00000000000a0000 0x00007f1db9c00000 0x0000000000000000 0x00007f7db0400    000
  1     32    0x00000000000c0000 0x000000000ff40000 0x00007f1db9cc0000 0x00000000000c0000 0x00007f7d94ec0    000

 Virtqueue 0 (TX)
  qsz 1024 last_avail_idx 0 last_used_idx 0
  avail.flags 0 avail.idx 256 used.flags 1 used.idx 0
  kickfd 33 callfd 34 errfd -1

 Virtqueue 1 (RX)
  qsz 1024 last_avail_idx 8 last_used_idx 8
  avail.flags 0 avail.idx 8 used.flags 1 used.idx 8
  kickfd 29 callfd 35 errfd -1

Also notice qsz 1024. A queue size of 256 will affect vhost throughput. The qsz should be 1024. In QEMU 2.10.0 and libvirt 3.7.0 and later versions this is specified in the xml file with the line shown above and in the example.

3.3 创建Metasploitable KVM虚拟机

通过KVM创建Metasploitable虚拟机时,操作步骤和3.2相同,需要将其中的文件路径以及文件名称进行修改。

首先,在VirtualBox中导入下载的Metasploitable镜像,成功创建Metasploitable虚拟机。创建时,为了方便通过KVM启动虚拟机,需要把Metasploitable虚拟机的虚拟磁盘设置为VDI/VMDK格式。

然后,将VirtualBox的VMDK格式虚拟磁盘转成KVM可直接访问的img后缀原始RAW格式磁盘。

vboxmanage clonehd --format RAW /media/wxg/28CCF498CCF4620C/VirtualBox\ VMs/Metasploitable2-Linux/Metasploitable.vmdk
/media/wxg/28CCF498CCF4620C/virtual_machines/metasploitable-linux-2.0.0.img

用qemu-system-x86_64命令行的方式,管理虚拟机参数较为麻烦。virsh工具支持xml格式的虚拟机配置文件。拷贝链接中的xml配置内容,取名为metasploitable-linux-2.0.0.xml。XML配置文件中的含义解释参考说明文件

根据自己的环境,修改xml配置文件中的虚拟机名称、系统唯一uuid号码、内存空间大小等信息,特别是修改放置etasploitable-linux-2.0.0.img的路径。

用 virsh create 命令创建metasploitable虚拟机 ,同时指定使用给的虚拟机xml配置。

$ cd /media/wxg/28CCF498CCF4620C/virtual_machines ## 改成你自己放虚拟机的目录
$ virsh create ./metasploitable-linux-2.0.0.xml
Domain Kali-Linux-2021.2-virtualbox-amd64 created from /media/wxg/28CCF498CCF4620C/virtual_machines/Kali-Linux-2021.2-virtualbox-amd64.xml

$ virsh list
 Id    Name                           State
----------------------------------------------------
 5     metasploitable-linux-2.0.0     running

可以看到metasploitable虚拟机创建成功。在vpp中查看此时的网络连接状态:

sudo vppctl  "show vhost"

Virtio vhost-user interfaces
Global:
  coalesce frames 32 time 1e-3
  Number of rx virtqueues in interrupt mode: 0
  Number of GSO interfaces: 0
  Thread 0: Polling queue count 2
Interface: VirtualEthernet0/0/0 (ifindex 2)
  Number of qids 2
virtio_net_hdr_sz 12
 features mask (0xfffffffbdfffa27c): 
 features (0x150208000): 
   VIRTIO_NET_F_MRG_RXBUF (15)
   VIRTIO_NET_F_GUEST_ANNOUNCE (21)
   VIRTIO_RING_F_INDIRECT_DESC (28)
   VHOST_USER_F_PROTOCOL_FEATURES (30)
   VIRTIO_F_VERSION_1 (32)
  protocol features (0x3)
   VHOST_USER_PROTOCOL_F_MQ (0)
   VHOST_USER_PROTOCOL_F_LOG_SHMFD (1)

 socket filename /tmp/vm00.sock type client errno "Success"

 rx placement: 
   thread 0 on vring 1, polling
 tx placement
   threads 0 on vring 0: lock-free

 Memory regions (total 2)
 region fd    guest_phys_addr    memory_size        userspace_addr     mmap_offset        mmap_addr
 ====== ===== ================== ================== ================== ================== ==================
  0     35    0x0000000000000000 0x00000000000a0000 0x00007f0f87600000 0x0000000000000000 0x00007f733b000000
  1     36    0x00000000000c0000 0x000000007ff40000 0x00007f0f876c0000 0x00000000000c0000 0x00007f39ff0c0000

 Virtqueue 0 (TX)
  global TX queue index 0
  qsz 1024 last_avail_idx 0 last_used_idx 0 last_kick 0
  avail.flags 0 avail event idx 0 avail.idx 1024 used.flags 1 used event idx 0 used.idx 0
  kickfd 37 callfd 38 errfd -1

 Virtqueue 1 (RX)
  global RX queue index 1
  qsz 1024 last_avail_idx 13 last_used_idx 13 last_kick 0
  avail.flags 0 avail event idx 0 avail.idx 13 used.flags 1 used event idx 12 used.idx 13
  kickfd 31 callfd 39 errfd -1

Interface: VirtualEthernet0/0/1 (ifindex 3)
  Number of qids 2
virtio_net_hdr_sz 10
 features mask (0xfffffffbdfffa27c): 
 features (0x40000000): 
   VHOST_USER_F_PROTOCOL_FEATURES (30)
  protocol features (0x3)
   VHOST_USER_PROTOCOL_F_MQ (0)
   VHOST_USER_PROTOCOL_F_LOG_SHMFD (1)

 socket filename /tmp/vm01.sock type client errno "Success"

 rx placement: 
   thread 0 on vring 1, polling
 tx placement
   threads 0 on vring 0: lock-free

 Memory regions (total 2)
 region fd    guest_phys_addr    memory_size        userspace_addr     mmap_offset        mmap_addr
 ====== ===== ================== ================== ================== ================== ==================
  0     32    0x0000000000000000 0x00000000000a0000 0x00007f0071e00000 0x0000000000000000 0x00007f733ae00000
  1     40    0x00000000000c0000 0x000000007ff40000 0x00007f0071ec0000 0x00000000000c0000 0x00007f397f0c0000

 Virtqueue 0 (TX)
  global TX queue index 1
  qsz 1024 last_avail_idx 0 last_used_idx 0 last_kick 0
  avail.flags 0 avail event idx 0 avail.idx 512 used.flags 1 used event idx 0 used.idx 0
  kickfd 41 callfd 42 errfd -1

 Virtqueue 1 (RX)
  global RX queue index 2
  qsz 1024 last_avail_idx 5 last_used_idx 5 last_kick 0
  avail.flags 0 avail event idx 0 avail.idx 5 used.flags 1 used event idx 0 used.idx 5
  kickfd 33 callfd 43 errfd -1

可以看到Memory regions已经分配成功,说明vpp与虚拟机已经成功连接。

4. 建立宿主机Host到软件交换机VPP的虚拟链路

参考VPP官方Progressive_VPP_Tutorial#Exercise:_Create_an_Interface

希望在Ubuntu宿主机上能够用tcpdump命令观测vpp软件交换机镜像的流量。所以通过如下步骤建立宿主机Host到软件交换机VPP的虚拟链路。可以通过该链路tcpdump流量到宿主机来离线分析。

首先,使用ubuntu自带的ip link命令创建虚拟网桥,ip link可以创建成对存在的两个虚拟网卡,这两个网卡之间通过一条看不见的"物理链路"相连,使得两者可以连通。创建命令如下:

#创建vpp-ou0和vpp-host0两个虚拟网卡
#后续会将vpp-out0绑定到vpp软件交换机上,使得在物理主机vpp-host0上可以收到vpp的流量数据
sudo ip link add name vpp-out0 type veth peer name vpp-host0

#将网卡设置为开启状态
sudo ip link set dev vpp-host0 up
sudo ip link set dev vpp-out0 up

#现在可以通过ifconfig看到创建的两个虚拟网卡
ifconfig

#可以选择手动配置网卡ip
sudo ip addr add 192.168.100.20/24 dev vpp-host0  ## 选择合适的局域网ip地址

然后,在主机创建成功虚拟link后,可以在vpp绑定创建的vpp-out端口,从而实现vpp与物理宿主机的交互。命令如下:

sudo vppctl "create host-interface name vpp-out0"

最后,可以在vpp中查看此时的网卡状态:

$ sudo vppctl  "show int"
              Name               Idx    State  MTU (L3/IP4/IP6/MPLS)     Counter          Count     
TenGigabitEthernet86/0/0          1     down         9000/0/0/0     
VirtualEthernet0/0/0              2     down         9000/0/0/0     
VirtualEthernet0/0/1              3     down         9000/0/0/0     
host-vpp-out0                     4     down         9000/0/0/0     
local0                            0     down          0/0/0/0        

如果需要删除创建的虚拟网卡,则输入命令:

# 该命令会自动删除成对存在的两个虚拟网卡
sudo ip link delete dev vpp-host0

5. 用软件交换机VPP 来桥接虚拟网卡和物理光纤卡

使用vpp的 set interface l2 bridge命令桥接所有网口到100号bridge。注意:下面的命令必须逐条执行。

sudo vppctl "set interface l2 bridge VirtualEthernet0/0/0 100"
sudo vppctl "set interface l2 bridge VirtualEthernet0/0/1 100"
sudo vppctl "set interface l2 bridge TenGigabitEthernet86/0/0 100"  ## 如果服务器上有万兆物理网卡
sudo vppctl "set interface l2 bridge host-vpp-out0 100"

使用下面命令查看VPP网桥的设置状态:

sudo vppctl  "show bridge-domain 100 detail"
  
    BD-ID   Index   BSN  Age(min)  Learning  U-Forwrd   UU-Flood   Flooding  ARP-Term  arp-ufwd Learn-co Learn-li   BVI-Intf 
   100      1      0     off        on        on       flood        on       off       off        6    16777216     N/A    
span-l2-input l2-input-classify l2-input-feat-arc l2-policer-classify l2-input-acl vpath-input-l2 l2-ip-qos-record l2-input-vtr l2-gbp-lpm-classify gbp-src-classify gbp-null-classify l2-gbp-lpm-anon-classify gbp-learn-l2 l2-emulation l2-learn l2-rw l2-fwd gbp-fwd l2-flood l2-flood l2-output 

           Interface           If-idx ISN  SHG  BVI  TxFlood        VLAN-Tag-Rewrite       
     VirtualEthernet0/0/0        2     1    0    -      *                 none             
     VirtualEthernet0/0/1        3     1    0    -      *                 none             
   TenGigabitEthernet86/0/0      1     1    0    -      *                 none             
         host-vpp-out0           4     1    0    -      *                 none             

也可以使用show bridge查看。

如果要删除某个桥时,首先需要将该domain下的所有网卡移动到0号domain,然后才可以删除。通过如下命令:

sudo vppctl "set interface l2 bridge VirtualEthernet0/0/0 0"
sudo vppctl "set interface l2 bridge VirtualEthernet0/0/1 0"
sudo vppctl "set interface l2 bridge TenGigabitEthernet86/0/0 0"
sudo vppctl "set interface l2 bridge host-vpp-out0  0"
sudo vppctl "create bridge-domain 100 del"

6. 将软件交换机VPP的网卡开启

现在所有的网口已经桥接好,可以用 Set Interface State 命令修改网卡状态为up。

sudo vppctl "set interface state VirtualEthernet0/0/0 up"
sudo vppctl "set interface state VirtualEthernet0/0/1 up"
sudo vppctl "set interface state TenGigabitEthernet86/0/0 up"  ## 如果服务器上有万兆物理网卡
sudo vppctl "set interface state host-vpp-out0 up"
sudo vppctl "show int"

              Name               Idx    State  MTU (L3/IP4/IP6/MPLS)     Counter          Count     
TenGigabitEthernet86/0/0          1      up          9000/0/0/0     rx packets                     1
                                                                    rx bytes                     342
VirtualEthernet0/0/0              2      up          9000/0/0/0     tx packets                     1
                                                                    tx bytes                     342
VirtualEthernet0/0/1              3      up          9000/0/0/0     tx packets                     1
                                                                    tx bytes                     342
host-vpp-out0                     4      up          9000/0/0/0     tx packets                     1
                                                                    tx bytes                     342
local0                            0     down          0/0/0/0          

7. 用ping测试两台虚拟机之间的连通性

打开QEMU的图形化界面。能看到Kali和metasploitable2的虚拟机都起来了。分别点击两个虚拟机,弹出他们的图形化界面。

在Kali虚拟机中查看IP地址。Kali虚拟机的用户名和密码都是kali。

$ ifconfig -a
eth0      Link encap:Ethernet  HWaddr 52:54:00:4C:47:F2  
          inet addr:192.168.100.12  Bcast:192.168.100.255  Mask:255.255.255.0
.....

在metasploitable2虚拟机中查看IP地址。metasploitable2虚拟机的用户名和密码都是msfadmin。

$ ifconfig -a
eth0      Link encap:Ethernet  HWaddr 52:54:00:4C:47:F2  
          inet addr:192.168.100.11  Bcast:192.168.100.255  Mask:255.255.255.0
.....

接下来进行ping测试,从Kali虚拟机进行ping测试:

$ ping 192.168.100.11
PING 192.168.100.11 (192.168.100.11) 56(84) bytes of data.
64 bytes from 192.168.100.11: icmp_seq=1 ttl=64 time=1.18 ms
64 bytes from 192.168.100.11: icmp_seq=2 ttl=64 time=0.132 ms

测试通过!

8. VPP端口镜像,流量导出

8.1 VPP端口镜像命令

vpp中提供了端口镜像功能,可以满足基本的端口镜像服务。该端口镜像只能够完成端口级别的镜像,暂时无法进行流级别的端口镜像,端口镜像的命令如下:

set interface span <if-name> [l2] {disable | destination <if-name> [both|rx|tx]}
  • 第一个if-name表示需要被镜像的端口
  • l2表示是否指定二层报文
  • disable表示删除某个端口镜像
  • destination <if-name>指定端口镜像的目的地址
  • [both|rx|tx] 指定需要镜像流入/流出/双向的流量

8.2 端口镜像实际使用

对流经kali虚拟机的流量都进行镜像并导出,在vpp中输入如下命令:

  1. 多台服务器的实验:镜像到物理端口

    sudo vppctl "set interface span VirtualEthernet0/0/0 l2 destination TenGigabitEthernet86/0/0 both"
    

    之后流经kali虚拟机的流量都会被VPP端口镜像,通过物理光纤口经过物理交换机,到达dell服务器的nic1网口。实验室的H3C物理交换机配置了端口镜像服务,可以将经过流量的拷贝到dell服务器的nic1网口。

    可以在dell服务器中使用tcpdump -i nic1命令抓取收到的流量报文,或者可以使用wireshark抓取nic1接口上的报文。

  2. 单台服务器的实验:镜像到宿主机的虚拟端口

    sudo vppctl "set interface span VirtualEthernet0/0/0 l2 destination host-vpp-out0 both"
    

    可以在宿主机使用tcpdump命令在host-vpp-out0的对应虚拟端口vpp-host0抓取收到的流量报文,或者可以使用wireshark命令抓取。

    sudo tcpdump -i vpp-host0
    

8.3 关闭端口镜像

在需要关闭端口镜像时,输入以下命令即可:

sudo vppctl "set interface span VirtualEthernet0/0/0 l2 disable"

如果设置端口镜像时没有指定 l2,则在停用端口镜像服务时,参数中也不需要加参数l2

posted @ 2022-08-13 21:27  锦瑟,无端  阅读(625)  评论(0编辑  收藏  举报