第5章 管理虚拟网络 本章将系统地讲解虚拟网络的日常管理,这需要具备一定的Linux网络管理的知识,包括物理网络接口、虚拟网络接口、网桥及路由等。 本章要点: TUN/TAP设备工作原理与管理。 网桥工作原理与管理。 理解不同网络类型的原理。 掌握NAT、桥接、隔离、路由、开放等网络类型的配置。 掌握VLAN的原理与配置。 掌握网络过滤器的原理与配置。 5.1查看默认网络环境 KVM支持多种网络类型,首先我们查看一下默认的网络环境。 在RHEL/CentOS 8等Linux发行版本中安装虚拟化组件的时候,通常会自动创建一个默认的虚拟网络配置,这包括一个名为virbr0的网桥、virbr0nic的虚拟网络接口、iptables的NAT配置及DNSMASQ的配置等。下面我们就通过实验来查看默认的网络环境,从而理解libvirt虚拟网络的原理。 5.1.1查看宿主机的网络环境 在没有启动虚拟机的情况下,宿主机上默认的网络环境如图51所示。 图51宿主机上默认的网络环境 查看宿主机网络环境的命令如下: 1 #ip address 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens32: mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 00:0c:29:f7:6b:c8 brd ff:ff:ff:ff:ff:ff inet 192.168.114.231/24 brd 192.168.114.255 scope global noprefixroute ens32 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fef7:6bc8/64 scope link valid_lft forever preferred_lft forever 3: virbr0: mtu 1500 qdisc noqueue state DOWN group default qlen 1000 link/ether 52:54:00:e0:41:ac brd ff:ff:ff:ff:ff:ff inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0 valid_lft forever preferred_lft forever 4: virbr0-nic: mtu 1500 qdisc fq_codel master virbr0 state DOWN group default qlen 1000 link/ether 52:54:00:e0:41:ac brd ff:ff:ff:ff:ff:ff 2 #ip link 1: lo: mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: ens32: mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000 link/ether 00:0c:29:f7:6b:c8 brd ff:ff:ff:ff:ff:ff 3: virbr0: mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000 link/ether 52:54:00:e0:41:ac brd ff:ff:ff:ff:ff:ff 4: virbr0-nic: mtu 1500 qdisc fq_codel master virbr0 state DOWN mode DEFAULT group default qlen 1000 link/ether 52:54:00:e0:41:ac brd ff:ff:ff:ff:ff:ff 3 #nmcli connection NAMEUUID TYPE DEVICE ens32 152beb06-47c5-c5e8-95a9-385590654382 ethernet ens32 virbr0 3068816f-b57c-4620-aea2-0e83642cdd87 bridge virbr0 4 #nmcli device DEVICE TYPE STATE CONNECTION ens32 ethernet connected ens32 virbr0 bridge connected virbr0 lo loopback unmanaged -- virbr0-nic tun unmanaged -- libvirt网络的最重要的组件是虚拟网络交换机,默认为由Linux的网桥实现。libvirt默认会创建一个名为virbr0的网桥,virbr0是Virtual Bridge 0的缩写。与物理交换机类似,虚拟网络交换机也是从其接收的数据包(帧)中获得MAC地址,并存储在MAC表中。物理交换机的端口数量有限,而虚拟交换机的端口数量则没有限制。 在Linux系统中,可以向网桥分配IP地址。从第1行命令的输出中可以看到,libvirt向virbr0分配的IP地址是192.168.122.1/24。libvirt根据自己的配置文件来分配这个IP地址,所以不会在/etc/sysconfig/networkscripts/目录中看到名为ifcfg virbr0的配置文件。 由于Linux的网桥会将其上第1个接口设备的MAC地址当作它的MAC地址,所以libvirt会创建一个名为virbr0nic的TAP设备。从第1行、第2行命令的输出中可以看出virbr0与virbr0nic的MAC地址都是52:54:00:e0:41:ac。 连接网桥的接口通常被称为slave接口。它们既可以是物理网卡,也可以是虚拟网络接口设备(例如: TAP类型的虚拟设备),所以通过网桥可以连通物理与虚拟网络设备。从相互关系上来讲,这些slave接口的master就是虚拟机交换机。从第1行、第2行命令的输出中可以看到virbr0nic的属性字符串有master virbr0字样,这说明它是virbr0网桥的slave接口。 5.1.2查看libvirt的网络环境 在libvirtd守护程序启动时,会根据配置文件创建一个名为default的虚拟网络。除了在宿主机上创建virbr0、virbr0nic之外,还会通过配置IP转发、iptables的NAT表从而在Linux协议栈中实现NAT功能。 libvirt使用的是IP伪装(IP masquerading),而不是源NAT(SourceNAT,SNAT)或目标NAT(DestinationNAT,DNAT)。IP伪装使虚拟机可以使用宿主机的IP地址与外部网络进行通信。默认情况下,当虚拟网络交换机以NAT模式运行时,虚拟机可以访问位于宿主物理计算机外部的资源,但是位于宿主物理计算机外部的计算机无法与内部的虚拟机进行通信,也就是说: 仅允许由内到外的访问,而不允许从外到内的访问。 首先,我们通过virtmanager这种比较直观的方式来查看虚拟网络default: (1) 在virtmanager的Edit菜单上,选择Connection Details。 (2) 在打开的Connection Details菜单中单击Virtual Networks选项卡,如图52所示。 (3) 窗口的左侧列出了所有可用的虚拟网络。我们可以查看和修改虚拟网络的配置。 下面通过命令行工具查看网络环境,命令如下: 1 #cat /proc/sys/net/ipv4/ip_forward 1 2 #iptables -t nat -L -n Chain PREROUTING (policy ACCEPT) targetprot opt sourcedestination 图52virtmanager中的虚拟网络配置 Chain INPUT (policy ACCEPT) targetprot opt sourcedestination Chain POSTROUTING (policy ACCEPT) targetprot opt sourcedestination RETURN all -- 192.168.122.0/24 224.0.0.0/24 RETURN all -- 192.168.122.0/24 255.255.255.255 MASQUERADE tcp -- 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535 MASQUERADE udp -- 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535 MASQUERADE all -- 192.168.122.0/24 !192.168.122.0/24 Chain OUTPUT (policy ACCEPT) targetprot opt sourcedestination 注意: 不建议在虚拟交换机运行时编辑这些防火墙规则,因为有可能导致交换机通信故障。 为了简化虚拟网络中的管理,libvirt还使用了DNSMASQ组件为default网络中的虚拟机提供DNS和DHCP功能,命令如下: 3 #ps aux | grep dnsmasq dnsmasq15610.00.0718882428?S08:210:00 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/libexec/libvirt_leaseshelper root 15620.00.0718601828? S08:210:00 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/libexec/libvirt_leaseshelper root 30410.00.0121081108pts/2 S+09:240:00 grep --color=auto dnsmasq 4 #cat /var/lib/libvirt/dnsmasq/default.conf ##WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE ##OVERWRITTEN AND LOST. Changes to this configuration should be made using: ## virsh net-edit default ##or other application using the libvirt API. ## ##dnsmasq conf file created by libvirt strict-order pid-file=/var/run/libvirt/network/default.pid except-interface=lo bind-dynamic interface=virbr0 dhcp-range=192.168.122.2,192.168.122.254 dhcp-no-override dhcp-authoritative dhcp-lease-max=253 dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts 从第3行命令的输出中可以看出DNSMASQ所使用的配置文件也是由libvirt提供的,它的路径名为/var/lib/libvirt/dnsmasq/default.conf。 从第4行命令的输出中可以看出向虚拟机分配的IP地址的范围是从192.168.122.2到192.168.122.254。 接下来,执行如下命令: 5 #virsh net-list Name State Autostart Persistent ---------------------------------------------------------- default active yes yes 6 #virsh net-dumpxml default default 6c729bec-ce6c-4ca3-b05c-1fdb99be4fdc 7 #ls /etc/libvirt/qemu/networks/ autostart default.xml 8 #cat /etc/libvirt/qemu/networks/default.xml default 6c729bec-ce6c-4ca3-b05c-1fdb99be4fdc 从第5行命令的输出可以看出,这个名为default的网络是随着libvirtd的启动而自动启动的,当前的状态是已激活。 第6行命令输出了default网络的详细定义: (1) default指定了虚拟网络的名称。 (2) 6c729becce6c4ca3b05c1fdb99be4fdc指定了虚拟网络的全局唯一标识符。 (3) 指定了虚拟网络将连接到物理网络,mode属性确定了转发方法,目前允许的方法有nat、route、open、bridge、private、vepa、passthrough和hostdev。如果没有配置forward属性,则该网络与任何其他网络都是隔离的,也就是isolated模式。nat会在连接到该网络的虚拟机与物理网络之间进行网络地址转换。 (4) 设置了用于的端口范围。 (5) 指定了libvirt在宿主机上创建网桥设备的信息。name属性定义了网桥设备的名称,新网桥启用对生成树协议(STP)的支持,默认延迟为0。建议使用以virbr开头的桥名称。虚拟机连接到该桥接设备,就像将真实世界的计算机连接到物理交换机一样。 (6) 属性定义了一个MAC(硬件)地址,格式为6组2位十六进制数字,各组之间用冒号分隔。这个MAC地址在创建时即分配给桥接设备。建议让libvirt自动生成一个随机MAC地址并将其保存在配置中。 (7) 为网桥指定IP地址。 (8) 指定了在虚拟网络上启用DHCP服务。 (9) 指定了要提供给DHCP客户端的地址池的边界。 提示: libvirt网络配置的详细介绍可参见https://libvirt.org/formatnetwork.html。 RHEL/CentOS 8中的libvirt网络配置保存在/etc/libvirt/qemu/networks/目录下的XML文件中。强烈不建议直接编辑这些配置文件,而应通过virsh的netedit子命令来修改。 5.1.3查看虚拟机的网络配置 下面,我们再查看一下当启动虚拟机后网络所发生的变化,命令如下: 1 #virsh domiflist centos6.10 InterfaceType SourceModelMAC ------------------------------------------------------- - network default virtio 52:54:00:27:5f:c9 2 #virsh start centos6.10 3 #virsh domiflist centos6.10 InterfaceTypeSourceModelMAC ------------------------------------------------------- vnet0 network default virtio 52:54:00:27:5f:c9 从第1行命令的输出中可以看出: 这个名为centos6.10的虚拟机未启动之时,Interface的属性为空,它连接到网络的名称是default。 当启动此虚拟机时,libvirt会在宿主机上创建一个新的虚拟网络接口,并将其连接到网桥中的virbr0上。我们可以从系统日志(/var/log/messages)中看到类似这样的信息: Kernel: virbr0: port 2(vnet0) entered blocking state Kernel: virbr0: port 2(vnet0) entered disabled state Kernel: device vnet0 entered promiscuous mode 新的虚拟网络接口的名称是以vnet开头的,后面是从0开始的序号。如果虚拟机操作系统的网络是自动获得IP地址的,则还会在系统日志中看到它从DNSMASQ中租用IP地址的信息: dnsmasq-dhcp[1561]: DHCPDISCOVER(virbr0) 192.168.122.142 52:54:00:27:5f:c9 dnsmasq-dhcp[1561]: DHCPOFFER(virbr0) 192.168.122.142 52:54:00:27:5f:c9 dnsmasq-dhcp[1561]: DHCPREQUEST(virbr0) 192.168.122.142 52:54:00:27:5f:c9 dnsmasq-dhcp[1561]: DHCPACK(virbr0) 192.168.122.142 52:54:00:27:5f:c9 我们还可以使用ip和nmcli命令查看宿主机上网络的变化情况,命令如下: 4 #ip addr … 3: virbr0: mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 52:54:00:e0:41:ac brd ff:ff:ff:ff:ff:ff inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0 valid_lft forever preferred_lft forever 4: virbr0-nic: mtu 1500 qdisc fq_codel master virbr0 state DOWN group default qlen 1000 link/ether 52:54:00:e0:41:ac brd ff:ff:ff:ff:ff:ff 5: vnet0: mtu 1500 qdisc fq_codel master virbr0 state UNKNOWN group default qlen 1000 link/ether fe:54:00:27:5f:c9 brd ff:ff:ff:ff:ff:ff inet6 fe80::fc54:ff:fe27:5fc9/64 scope link valid_lft forever preferred_lft forever 5 #nmcli connection NAMEUUID TYPE DEVICE ens32 152beb06-47c5-c5e8-95a9-385590654382 ethernet ens32 virbr0 3068816f-b57c-4620-aea2-0e83642cdd87 bridge virbr0 vnet0 0c886394-b825-432f-9f79-bfe0a67199db tun vnet0 从第4行命令的输出可以看出: 新增加了一个名vnet0的接口,它的master是virbr0。第5行命令的输出显示了它的类型是TUN,准确来讲应当是TAP设备。 注意: NetworkManager有些版本(例如1.22.85.el8_2.x86_64)总是将TUN/TAP设备显示为TAP设备,而ip命令(例如iproute5.3.01.el8.x86_64)显示的类型则是正确的。5.2节将深入讲解TUN/TAP设备。 我们再启动一台新的虚拟机win2k3,它会在网桥virbr0中再新增加一个slave设备,新设备名称为vnet1,命令如下: 6 #ip addr … 5: vnet0: mtu 1500 qdisc fq_codel master virbr0 state UNKNOWN group default qlen 1000 link/ether fe:54:00:27:5f:c9 brd ff:ff:ff:ff:ff:ff inet6 fe80::fc54:ff:fe27:5fc9/64 scope link valid_lft forever preferred_lft forever 6: vnet1: mtu 1500 qdisc fq_codel master virbr0 state UNKNOWN group default qlen 1000 link/ether fe:54:00:9d:57:9c brd ff:ff:ff:ff:ff:ff inet6 fe80::fc54:ff:fe9d:579c/64 scope link valid_lft forever preferred_lft forever 7 #nmcli connection NAMEUUID TYPE DEVICE ens32 152beb06-47c5-c5e8-95a9-385590654382 ethernet ens32 virbr0 3068816f-b57c-4620-aea2-0e83642cdd87 bridge virbr0 vnet0 0c886394-b825-432f-9f79-bfe0a67199db tun vnet0 vnet1 3d4e1388-aee6-42df-a283-fcc909939762 tun vnet1 此时宿主机上网络环境如图53所示。两台虚拟机之间的通信、宿主机与虚拟机之间的通信全部是在虚拟交换机(网桥)virbr0内部完成的。两台虚拟机对外部网络的访问是先将消息发送给它们的默认网关virbr0(192.168.122.1),再通过iptables实现的NAT功能从ens32发送出去。由于采用的NAT模式是MASQUERADE(一种SNAT),所以默认情况下外部网络的主机不能访问这两台虚拟机,换句话来讲,就是这两台虚拟机对于外部网络来讲是不可见的。 图53RHEL/CentOS8中libvirt使用的default网络的工作原理 5.2TUN/TAP设备工作原理与管理 libvirt的虚拟网络离不开TAP类型的虚拟网络接口设备,所以需要讲解一下它的工作原理。首先回顾一下Linux物理网卡的工作原理。计算机系统通常会有一个或多个网络设备,例如eth0、eth1等。这些网络设备与物理网络适配器相关联,后者负责将数据包放置到线路上,如图54所示。 图54Linux物理网卡工作原理 eth0通过物理网卡NIC与外部网络相连,该物理网卡收到的数据包会经由eth0传递给内核的网络协议栈(Network Stack),然后由协议栈对这些数据包进行进一步的处理。 对于一些错误的数据包,协议栈可以选择丢弃。对于目标不属于本机的数据包,协议栈可以选择转发,而对于目标地址是本机的而且是上层应用所需要数据包,协议栈会通过Socket API传递给上层正在等待的应用程序。 虚拟网络接口设备完成的功能与物理网卡类似,有两种常见类型: TUN和TAP。在Linux内核官方网站上有一个文档(https://www.Kernel.org/doc/Documentation/networking/tuntap.txt)是这样定义的: TUN/TAP为用户空间程序提供数据包的接收和传输。可以将其视为简单的点对点或以太网设备。它们不是从物理介质接收数据包,而是从用户空间程序接收数据包。它们也不是通过物理介质发送数据包,而是将其写入用户空间程序。 也就是说,TUN/TAP接口是没有关联物理设备的虚拟接口。用户空间程序可以附加到TUN/TAP接口并处理发送到该接口的流量,如图55所示。 图55Linux中TUN/TAP虚拟设备工作原理 使用TUN/TAP技术可以在主机上构建虚拟网络接口,它们的功能类似于物理网卡,可以为其分配IP、将数据包路由到该接口、分析流量等。TUN/TAP有两种常用的应用场景: VPN和云计算。 TUN与TAP有什么区别呢? TUN(tunnel)设备在OSI模型的第3层运行,它实现的是虚拟的IP点对点接口,应用程序只能从此接口发送或接收IP数据包。它没有MAC地址,而且不能成为网桥的slave设备。 TAP(Network Tap)的运行方式与TUN极为相似,但是它运行在OSI模型的第2层上,应用程序从此接口发送和接收原始以太网数据包,所以它与以太网卡特别相似。它有MAC地址,可以成为网桥的slave设备。 下面通过实验讲解TAP设备的管理。 首先是ip命令。ip是iproute软件包里面的一个强大的网络配置工具,其中tuntap子命令可用于管理TUN/TAP接口,命令如下: 1 #ip link 1: lo: mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: ens32: mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000 link/ether 00:0c:29:f7:6b:c8 brd ff:ff:ff:ff:ff:ff 3: virbr0: mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether 52:54:00:e0:41:ac brd ff:ff:ff:ff:ff:ff 4: virbr0-nic: mtu 1500 qdisc fq_codel master virbr0 state DOWN mode DEFAULT group default qlen 1000 link/ether 52:54:00:e0:41:ac brd ff:ff:ff:ff:ff:ff 6: vnet0: mtu 1500 qdisc fq_codel master virbr0 state UNKNOWN mode DEFAULT group default qlen 1000 link/ether fe:54:00:27:5f:c9 brd ff:ff:ff:ff:ff:ff 7: vnet1: mtu 1500 qdisc fq_codel master virbr0 state UNKNOWN mode DEFAULT group default qlen 1000 link/ether fe:54:00:9d:57:9c brd ff:ff:ff:ff:ff:ff 2 #ip tuntap help Usage: ip tuntap { add | del | show | list | lst | help } [ dev PHYS_DEV ] [ mode { tun | tap } ] [ user USER ] [ group GROUP ] [ one_queue ] [ pi ] [ vnet_hdr ] [ multi_queue ] [ name NAME ] Where: USER := { STRING | NUMBER } GROUP := { STRING | NUMBER } 3 #ip tuntap list virbr0-nic: tap persist vnet0: tap vnet_hdr vnet1: tap 第1行ip link命令用于显示当前主机上的所有物理及虚拟的网络设备。 第2行命令用于显示ip命令的tuntap子命令的帮助。 第3行命令用于显示当前的TUN/TAP设备信息,此处共有3个TAP设备。 提示: libvirt在创建TAP设备时,会根据虚拟机网卡类型及用途为TAP设备增加额外的标记(Flag),例如为virtio类型网卡增加的标记是vnet_hdr,而对于传统的e1000的网卡则不设置标记。 接下来添加1个TAP设备,然后查看这个新设备,命令如下: 4 #ip tuntap add dev tap-nic1 mode tap 5 #ip tuntap list virbr0-nic: tap persist vnet0: tap vnet_hdr vnet1: tap tap-nic1: tap persist 6 #ip link 1: lo: mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: ens32: mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000 link/ether 00:0c:29:f7:6b:c8 brd ff:ff:ff:ff:ff:ff 3: virbr0: mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether 52:54:00:e0:41:ac brd ff:ff:ff:ff:ff:ff 4: virbr0-nic: mtu 1500 qdisc fq_codel master virbr0 state DOWN mode DEFAULT group default qlen 1000 link/ether 52:54:00:e0:41:ac brd ff:ff:ff:ff:ff:ff 6: vnet0: mtu 1500 qdisc fq_codel master virbr0 state UNKNOWN mode DEFAULT group default qlen 1000 link/ether fe:54:00:27:5f:c9 brd ff:ff:ff:ff:ff:ff 7: vnet1: mtu 1500 qdisc fq_codel master virbr0 state UNKNOWN mode DEFAULT group default qlen 1000 link/ether fe:54:00:9d:57:9c brd ff:ff:ff:ff:ff:ff 8: tap-nic1: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 76:0a:b9:fa:83:e9 brd ff:ff:ff:ff:ff:ff 7 #ip addr add 172.16.123.1/24 dev tap-nic1 第4行命令添加了1个名为tapnic1的TAP设备。从第5、6行命令的输出可以看到这个新的设备。 我们可以像管理物理网卡一样管理虚拟网络接口,例如第7行命令给它设置了1个静态的IP地址。接下来删除这个TAP设备,然后查看是否成功删除,命令如下: 8 #ip tuntap del dev tap-nic1 mode tap 9 #ip tuntap list virbr0-nic: tap persist vnet0: tap vnet_hdr vnet1: tap 实验做完了,第8行命令用于删除这个TAP设备,第9行命令用于查看TAP设备列表。 RHEL/CentOS 8中使用ip命令配置设备信息,大部分会在设备重启后还原。如果需要持久的TUN/TAP设置,则推荐使用NetworkManager来创建。下面我们通过NetworkManager中的命令行工具nmcli来做类似的实验,命令如下: 10 #nmcli connection add type tun con-name newcon1 ifname tap-nic2 mode tap ip4 172.16.123.2/24 Connection 'newcon1' (09df2d02-dfc1-4a92-9d24-72dd97fe0756) successfully added. 11 #nmcli connection NAME UUID TYPE DEVICE ens32 152beb06-47c5-c5e8-95a9-385590654382 ethernet ens32 newcon1 09df2d02-dfc1-4a92-9d24-72dd97fe0756 tun tap-nic2 virbr0 46edfc4d-8edb-4560-8a86-c84cad9b61c9 bridge virbr0 vnet0 540308fa-9ffa-40ec-8860-dd5ce13dde73 tun vnet0 vnet1 7a8486a7-88d0-4423-950a-0705d7aa3025 tun vnet1 12 #nmcli device DEVICE TYPE STATE CONNECTION ens32 ethernet connected ens32 tap-nic2 tun connected newcon1 virbr0 bridge connected virbr0 vnet0 tun connected vnet0 vnet1 tun connected vnet1 lo loopback unmanaged -- virbr0-nic tun unmanaged -- NetworkManager将所有网络配置存储为连接(connection),它们是描述如何创建或描述如何连接到网络的配置(2层详细信息、IP地址等)的集合。NetworkManager支持的连接类型有多种,包括ethernet、wifi、pppoe、infiniband、bluetooth、bond、bridge、tun、vxlan等。需要注意的是,NetworkManager不区分连接类型究竟是TUN还是TAP,统一称为TUN。 第10行命令创建了一个新的连接,将type设置为tun,通过conname指定了连接的名称为newcon1,通过ifname指定了接口名称为tapnic2,通过mode指定了模式为tap,通过ip4指定了IP地址为172.16.123.2/24。 从第11行命令的输出中可以看到这个名为newcon1的新连接及其属性。 从第12行命令的输出中可以看到新设备tapnic2,type显示为tun。我们可以认为这是指连接的类型,而且不是设备的类型。tapnic2的类型还是tap,这个可以从第14行命令的输出中看出,命令如下: 13 #ip address show tap-nic2 7: tap-nic2: mtu 1500 qdisc fq_codel state DOWN group default qlen 1000 link/ether ce:ba:06:00:66:ef brd ff:ff:ff:ff:ff:ff inet 172.16.123.2/24 brd 172.16.123.255 scope global noprefixroute tap-nic2 valid_lft forever preferred_lft forever inet6 fe80::c5d3:c6b8:d79:81a7/64 scope link tentative noprefixroute valid_lft forever preferred_lft forever 14 #ip tuntap virbr0-nic: tap persist vnet0: tap vnet_hdr vnet1: tap tap-nic2: tap persist 15 #nmcli connection delete newcon1 Connection 'newcon1' (09df2d02-dfc1-4a92-9d24-72dd97fe0756) successfully deleted. 16#ip tuntap list virbr0-nic: tap persist vnet0: tap vnet_hdr vnet1: tap 从第13行命令的输出中可看到虚拟网络接口tapnic2的信息,包括随机生成的MAC地址、IPv4地址、IPv6地址等信息。 第15行命令会清除连接newcon1,这个操作也会同时删除虚拟网络接口设备tapnic2。 5.3网桥工作原理与管理 网桥是一种数据链路层的设备。2.4版以后的Linux内核之中已经集成了网桥功能。在虚拟化解决方案中,网桥是一个很重要的组件。 5.3.1考察现有网桥 在RHEL/CentOS 8中,可以通过iproute、NetworkManager和Cockpit来查看及了解当前主机上的网桥情况。 在“5.1.1查看宿主机的网络环境”一节中讲解了如何通过iproute和NetworkManager来查看宿主机当前的网桥,下面我们通过Cockpit查看这部分配置。 在Cockpit中单击Networking就可以看到宿主机的所有网络接口信息,在其中可以看到网桥virbr0,如图56所示。 图56Cockpit中的网络接口 单击virbr0就可以看到这个网桥的详细信息,包括IP地址、支持STP、转发延迟及两个端口vnet0和vnet1,如图57所示。 图57Cockpit中的网桥详细信息 提示: RHEL 7.7已经不推荐使用bridgeutils了,所以在RHEL 8/CentOS 8中已经无法使用brctl命令了,我们完全可以使用iproute、NetworkManager和Cockpit来替代它。 5.3.2通过iproute管理网桥 在iproute软件包中,ip命令是最常用的命令,下面通过它创建一个网桥接口,网桥接口的名称可以用于表示网桥,命令如下: 1 #ip link add name br2 type bridge 2 #ip address … 7: br2: mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether 36:21:b7:e4:58:fe brd ff:ff:ff:ff:ff:ff 3 #ip link … 7: br2: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 36:21:b7:e4:58:fe brd ff:ff:ff:ff:ff:ff 第1行命令创建了1个名为br2的网桥接口。从第2行、第3行命令的输出中可以看到这个新的网桥。网桥都有1个随机生成的MAC地址,注意此时这个新网桥的MAC地址是36:21:b7:e4:58:fe。 有了网桥,下面就可以为其添加子接口了。网桥上的子接口既可以是物理接口也可以是虚拟接口,本次实验将使用虚拟接口,命令如下: 4 #ip tuntap add dev tap-nic1 mode tap 5 #ip tuntap add dev tun-nic1 mode tun 6 #ip tuntap virbr0-nic: tap persist vnet0: tap vnet_hdr vnet1: tap tap-nic1: tap persist tun-nic1: tun persist 7 #ip link … 7: br2: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 36:21:b7:e4:58:fe brd ff:ff:ff:ff:ff:ff 8: tap-nic1: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 26:3a:41:e8:7f:78 brd ff:ff:ff:ff:ff:ff 9: tun-nic1: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 500 link/none 第4行命令添加了1个名为tapnic1的TAP类型的虚拟接口。出于对比的目的,使用第5行命令再创建了1个名为tunnic1的TUN类型的虚拟接口。可以在第6行命令的输出中看到这2个虚拟接口。 从第7行命令的输出中可以看出,tapnic1与br2的MAC地址是不同的。由于tunnic1是一个3层的设备,所以它是没有MAC地址的。 接下来激活连接及设置子接口,命令如下: 8 #ip link set br2 up 9 #ip link set tap-nic1 up 10 #ip link set tun-nic1 up 11 #ip link set tap-nic1 master br2 12 #ip link set tun-nic1 master br2 RTNETLINK answers: Invalid argument ip命令创建的连接默认为没有被激活,所以第8、9、10行命令激活了这3个连接。第11行命令将这个名为tapnic1的TAP设备设置为网桥br2的子接口,命令没有输出表示成功。由于tunnic1是一个3层的设备,它无法充当网桥的子接口,所以第12行命令会返回一个错误。 查看网络配置,命令如下: 13 #ip addr … 3: virbr0: mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 52:54:00:e0:41:ac brd ff:ff:ff:ff:ff:ff inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0 valid_lft forever preferred_lft forever 4: virbr0-nic: mtu 1500 qdisc fq_codel master virbr0 state DOWN group default qlen 1000 link/ether 52:54:00:e0:41:ac brd ff:ff:ff:ff:ff:ff … 7: br2: mtu 1500 qdisc noqueue state DOWN group default qlen 1000 link/ether 26:3a:41:e8:7f:78 brd ff:ff:ff:ff:ff:ff inet6 fe80::3421:b7ff:fee4:58fe/64 scope link valid_lft forever preferred_lft forever 8: tap-nic1: mtu 1500 qdisc fq_codel master br2 state DOWN group default qlen 1000 link/ether 26:3a:41:e8:7f:78 brd ff:ff:ff:ff:ff:ff 9: tun-nic1: mtu 1500 qdisc fq_codel state DOWN group default qlen 500 link/none 我们注意一下第13命令的输出: tapnic1的master是网桥br2,而且网桥br2会将它的第1个接口的MAC地址当作自己的MAC,也就是tapnic1的MAC地址26:3a:41:e8:7f:78。这是Linux网桥一个特性: 它会自动将第1个网络接口的MAC当作自己的MAC地址,所以libvirt在创建网桥virbr0时,会先创建一个TAP类型的接口virbr0nic,这样virbr0和virbr0nic的MAC地址都是52:54:00:e0:41:ac。 提示: 默认情况下libvirt生成的MAC地址是52:54:00开头的。 在iproute软件包中,除了ip命令外,还有1个名为bridge的命令也与网桥有关,命令如下: 14 #bridge link 4: virbr0-nic: mtu 1500 master virbr0 state disabled priority 32 cost 100 5: vnet0: mtu 1500 master virbr0 state forwarding priority 32 cost 100 6: vnet1: mtu 1500 master virbr0 state forwarding priority 32 cost 100 8: tap-nic1: mtu 1500 master br2 state disabled priority 32 cost 100 做完实验之后,我们可以使用下述命令清理实验环境。 15 #ip link set tap-nic1 nomaster 16 #ip link delete br2 type bridge 17 #ip tuntap delete tap-nic1 mode tap 18 #ip tuntap delete tun-nic1 mode tun 5.3.3通过NetworkManager管理网桥 可以通过nmcli的connection子命令来管理网桥。与ip命令类似,它也是先创建网桥的连接再创建子接口。不同之处是它会自动创建网桥接口文件。 在下面的实验中,我们将使用一块新网卡ens34作为新网桥的子接口,代码如下: 1 #nmcli connection NAMEUUID TYPE DEVICE ens32 152beb06-47c5-c5e8-95a9-385590654382 ethernet ens32 ens34 293e8ad9-d491-46ee-a0ac-789fc12c5407 ethernet ens34 virbr0 b4cc48df-f27f-4c97-9709-bcca97a890e5 bridge virbr0 vnet0 39e2fcf8-26f4-4e4f-be22-1eb79f43c01b tun vnet0 vnet1 84718c08-1d46-4d0b-b80c-79fb448eccce tun vnet1 2 #nmcli device DEVICE TYPE STATE CONNECTION ens32 ethernet connected ens32 ens34 ethernet connected ens34 virbr0 bridge connected virbr0 vnet0 tun connected vnet0 vnet1 tun connected vnet1 lo loopback unmanaged -- virbr0-nic tun unmanaged -- 4 #ls /etc/sysconfig/network-scripts/ ifcfg-ens32 ifcfg-ens34 5 #cat /etc/sysconfig/network-scripts/ifcfg-ens34 TYPE=Ethernet PROXY_METHOD=none BROWSER_ONLY=no BOOTPROTO=dhcp DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=yes IPV6_AUTOCONF=yes IPV6_DEFROUTE=yes IPV6_FAILURE_FATAL=no IPV6_ADDR_GEN_MODE=stable-privacy NAME=ens34 UUID=293e8ad9-d491-46ee-a0ac-789fc12c5407 DEVICE=ens34 ONBOOT=yes 6 #ip address … 3: ens34: mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 00:0c:29:f7:6b:d2 brd ff:ff:ff:ff:ff:ff inet 192.168.114.130/24 brd 192.168.114.255 scope global dynamic noprefixroute ens34 valid_lft 1750sec preferred_lft 1750sec inet6 fe80::697b:329c:b7b3:238d/64 scope link noprefixroute valid_lft forever preferred_lft forever … 从第1行及第2行命令的输出中可以看出: 有一个名为ens34的连接,它有一个同名的以太网接口设备。 在/etc/sysconfig/networkscripts/目录中有一个名为ifcfgens34的网桥接口文件,从第5行的命令输出就可以看到这个配置文件的内容。系统初始化时会自动根据这个配置文件进行相应的设置,例如通过DHCP给ens34分配的IP地址,这可以从第6行命令的输出中看到IP地址是192.168.114.130/24。 提示: 如果/etc/sysconfig/networkscripts/目录中没有新网卡的接口文件,则除了手工创建之外,还可以通过nmcli device connect ens34命令来生成一个新的接口文件。 接下来执行以下命令: 7 #nmcli connection add type bridge autoconnect yes con-name virbr1 ifname virbr1 Connection 'virbr1' (24fc8f00-ca86-47da-817c-cb392c4d15b4) successfully added. 8 #nmcli connection NAME UUID TYPE DEVICE virbr1 24fc8f00-ca86-47da-817c-cb392c4d15b4 bridge virbr1 ens32 152beb06-47c5-c5e8-95a9-385590654382 ethernet ens32 ens34 861f3757-4b5b-464a-9d56-fd7c0b4e8cee ethernet ens34 virbr0 d767930b-ee30-49ee-8d59-e51708f1cc1d bridge virbr0 9 #nmcli device DEVICE TYPE STATE CONNECTION ens32 ethernet connected ens32 ens34 ethernet connected ens34 virbr0 bridge connected virbr0 virbr1 bridge connecting (getting IP configuration) virbr1 lo loopback unmanaged -- virbr0-nic tun unmanaged -- 10 #ls /etc/sysconfig/network-scripts/ ifcfg-ens32 ifcfg-ens34 ifcfg-virbr1 11 #cat /etc/sysconfig/network-scripts/ifcfg-virbr1 STP=yes BRIDGING_OPTS=priority=32768 TYPE=Bridge PROXY_METHOD=none BROWSER_ONLY=no BOOTPROTO=dhcp DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=yes IPV6_AUTOCONF=yes IPV6_DEFROUTE=yes IPV6_FAILURE_FATAL=no IPV6_ADDR_GEN_MODE=stable-privacy NAME=virbr1 UUID=24fc8f00-ca86-47da-817c-cb392c4d15b4 DEVICE=virbr1 ONBOOT=yes 第7行命令成功添加了一个新的连接并设置了属性,type指定的类型是bridge,autoconnect指定为自动启动,conname指定的连接名称为virbr1,ifname指定的接口名称也是virbr1。 从第8行、第9行的输出中可以看到这个网桥的连接及设备信息。 第7行命令会在/etc/sysconfig/networkscripts/目录中生成一个名为ifcfgvirbr1的网络接口文件。 注意第11行命令的输出中的两个属性: TYPE=Bridge和BOOTPROTO=dhcp。 接下来执行的命令如下: 12 #ip address … 3: ens34: mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 00:0c:29:f7:6b:d2 brd ff:ff:ff:ff:ff:ff inet 192.168.114.130/24 brd 192.168.114.255 scope global dynamic noprefixroute ens34 valid_lft 1582sec preferred_lft 1582sec inet6 fe80::697b:329c:b7b3:238d/64 scope link noprefixroute valid_lft forever preferred_lft forever … 6: virbr1: mtu 1500 qdisc noqueue state DOWN group default qlen 1000 link/ether 92:23:18:cb:00:e3 brd ff:ff:ff:ff:ff:ff 13 #nmcli connection modify virbr1 ipv4.addresses 172.16.123.11/24 ipv4.method manual 14 #cat /etc/sysconfig/network-scripts/ifcfg-virbr1 STP=yes BRIDGING_OPTS=priority=32768 TYPE=Bridge PROXY_METHOD=none BROWSER_ONLY=no BOOTPROTO=none DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=yes IPV6_AUTOCONF=yes IPV6_DEFROUTE=yes IPV6_FAILURE_FATAL=no IPV6_ADDR_GEN_MODE=stable-privacy NAME=virbr1 UUID=24fc8f00-ca86-47da-817c-cb392c4d15b4 DEVICE=virbr1 ONBOOT=yes IPADDR=172.16.123.11 PREFIX=24 从第12行命令的输出可以看出: 由于还没有激活新网桥virbr1,所以它没有从DHCP服务器获得IP地址。需要注意的是virbr1的MAC地址是随机生成的92:23:18:cb:00:e3,与ens34的MAC地址00:0c:29:f7:6b:d2并不相同。 第13行命令将virbr1的IP地址修改为静态IP地址172.16.123.11/24。这个修改会反映在/etc/sysconfig/networkscripts/目录中的网格接口文件ifcfgvirbr1的变化上。 接下来执行的命令如下: 15 #nmcli connection delete ens34 Connection 'ens34' (861f3757-4b5b-464a-9d56-fd7c0b4e8cee) successfully deleted. 16 #nmcli connection add type bridge-slave autoconnect yes con-name ens34 master virbr1 Connection 'ens34' (ad4ae2e5-f95f-415a-a9e1-23e2ff650956) successfully added. 17 #nmcli connection NAME UUID TYPE DEVICE virbr1 24fc8f00-ca86-47da-817c-cb392c4d15b4 bridge virbr1 ens32 152beb06-47c5-c5e8-95a9-385590654382 ethernet ens32 virbr0 d767930b-ee30-49ee-8d59-e51708f1cc1d bridge virbr0 ens34 ad4ae2e5-f95f-415a-a9e1-23e2ff650956 ethernet ens34 18 #nmcli device DEVICE TYPE STATE CONNECTION ens32 ethernet connected ens32 virbr1 bridge connected virbr1 virbr0 bridge connected virbr0 ens34 ethernet connected ens34 lo loopback unmanaged -- virbr0-nic tun unmanaged -- 19 #ls /etc/sysconfig/network-scripts/ ifcfg-ens32 ifcfg-ens34 ifcfg-virbr1 20 #cat /etc/sysconfig/network-scripts/ifcfg-ens34 TYPE=Ethernet NAME=ens34 UUID=ad4ae2e5-f95f-415a-a9e1-23e2ff650956 ONBOOT=yes BRIDGE=virbr1 21 #nmcli connection up virbr1 Connection successfully activated (master waiting for slaves) (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/7) 网络设备ens34现在还属于一个同名的连接,所以需要先将这个连接删除。第15行命令将连接ens34删除。 第16行命令将网络设备ens34添加到网桥virbr1,从而成为网桥的子接口。type指定的类型为bridgeslave,autoconnect指定为自动启动,conname指定的连接名称为ens34,master指定的网桥名称是virbr1。 从第17行、第18行的输出中可以看到virbr1、ens34的连接及设备信息。 第16行命令会为ens34在/etc/sysconfig/networkscripts/目录中生成一个新的网络接口文件ifcfgens34。通过第20行命令查看这个新文件,新文件很简单,核心属性是BRIDGE=virbr1,它为ens34指定了master。 第21行命令激活了网桥。在RHEL/CentOS 8中,这些操作会在系统的/var/log/messages生成日志条目。当操作失败时,阅读这些日志条件将有助于我们进行排错操作。 接下来执行的命令如下: 22 #ip address … 3: ens34: mtu 1500 qdisc fq_codel master virbr1 state UP group default qlen 1000 link/ether 00:0c:29:f7:6b:d2 brd ff:ff:ff:ff:ff:ff … 6: virbr1: mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:0c:29:f7:6b:d2 brd ff:ff:ff:ff:ff:ff inet 172.16.123.11/24 brd 172.16.123.255 scope global noprefixroute virbr1 valid_lft forever preferred_lft forever inet6 fe80::e708:9d2e:c0ca:f913/64 scope link noprefixroute valid_lft forever preferred_lft forever 23 #bridge link 3: ens34: mtu 1500 master virbr1 state forwarding priority 32 cost 100 5: virbr0-nic: mtu 1500 master virbr0 state disabled priority 32 cost 100 从第22行命令的输出可以看出: ens34的master是virbr1,这说明它是网桥virbr1的子接口。同时要注意virbr1的MAC地址已经不再是原有那个随机成的MAC地址了,而是借用了第1个子接口,即ens34的MAC地址00:0c:29:f7:6b:d2。 第23行命令的输出也显示出ens34的master是virbr1。 创建网桥的实验做完了,下面我们进行删除及恢复操作,命令如下: 24 #mkdir ~/bak 25 #cp /etc/sysconfig/network-scripts/ifcfg-* ~/bak 26 #nmcli connection down virbr1 Connection 'virbr1' successfully deactivated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/7) 27 #nmcli connection delete virbr1 Connection 'virbr1' (24fc8f00-ca86-47da-817c-cb392c4d15b4) successfully deleted. 28 #nmcli connection delete ens34 Connection 'ens34' (ad4ae2e5-f95f-415a-a9e1-23e2ff650956) successfully deleted. 29 #nmcli device connect ens34 Device 'ens34' successfully activated with '6d322e2c-af9c-4c87-9740-d4cf6e076bfc'. 为了后续的实验,使用第24行、第25行命令将当前的网桥接口文件备份到~/bak目录中。 使用第26行命令关闭virbr1,然后删除连接virbr1、ens34。 通过第29行命令会重新连接设备ens34,并在/etc/sysconfig/networkscripts/目录生成包含默认属性值的ifcfgens34文件。 提示: 在NetworkManager中还有图形化网络连接编辑器nmconnectioneditor。与nmclic类似,它也可以很方便地添加、删除和修改NetworkManager存储的网络连接。 5.3.4通过网络接口文件管理网桥 在目录/etc/sysconfig/networkscripts/下创建网桥的配置文件ifcfgvirbr1和子接口配置文件ifcfgens34,也可以很方便地创建网桥,命令如下: 1 #vi /etc/sysconfig/network-scripts/ifcfg-virbr1 #添加以下内容: TYPE=Bridge STP=yes BOOTPROTO=none NAME=virbr1 DEVICE=virbr1 ONBOOT=yes IPADDR=172.16.123.11 PREFIX=24 2 #vi /etc/sysconfig/network-scripts/ifcfg-ens34 #添加以下内容: TYPE=Ethernet NAME=ens34 ONBOOT=yes BRIDGE=virbr1 3 #nmcli connection reload 4 #ip address … 3: ens34: mtu 1500 qdisc fq_codel master virbr1 state UP group default qlen 1000 link/ether 00:0c:29:f7:6b:d2 brd ff:ff:ff:ff:ff:ff … 6: virbr1: mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:0c:29:f7:6b:d2 brd ff:ff:ff:ff:ff:ff inet 172.16.123.11/24 brd 172.16.123.255 scope global noprefixroute virbr1 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:feb3:7340/64 scope link valid_lft forever preferred_lft forever 如第1行、第2行命令所示,不管是网桥的配置文件还是子接口的配置文件,仅需要必需的属性即可。当然,还可以将上一实验备份在目录~/bak/下的ifcfgvirbr1和ifcfgens34直接复制到目录/etc/sysconfig/networkscripts/下。 当执行第3行命令重新加载网络连接配置之后,网桥就配置成功了。这可以从第4行命令的输出信息中得到验证。如果失败,则可以查看系统日志/var/log/messages中的条目来查找错误原因。 5 #rm /etc/sysconfig/network-scripts/ifcfg-virbr1 6 #rm /etc/sysconfig/network-scripts/ifcfg-ens34 7 #nmcli connection down virbr1 Connection 'virbr1' successfully deactivated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/6) 8 #nmcli connection reload 清除网桥virbr1也很简单,首先执行第5行、第6行命令删除网桥接口配置文件,然后在关闭网桥virbr1之后重新加载网络连接即可。 5.3.5通过Cockpit管理网桥 相对于前面几种方法,使用Cockpit来管理网桥是最简单的。在网络信息中单击Add Bridge就可以添加新网桥了,如图58所示。 图58Cockpit中的网络接口 输入新网桥名称virbr1,选中子接口(Cockpit将其称为port)ens34,其他选项保持默认,然后单击Apply按钮创建新网桥,如图59所示。 通过Cockpit来创建新网桥virbr1,会自动在/etc/sysconfig/networkscripts/目录中创建配置文件ifcfgens34和ifcfgvirbr1。 图59在Cockpit中创建新的网桥 Cockpit默认使用DHCP服务向新网桥分配IP地址,当然也可以单击新网桥virbr1的链接进行修改,如图510所示。 图510成功创建的新网桥 可以在新页面中设置IP地址、STP及子接口等信息,也可以单击Delete按钮删除网桥,如图511所示。 图511网桥的详细信息 5.4KVM/libvirt常用的网络类型 在掌握了TUN/TAP设备及网桥基本原理之后,我们就可以来学习KVM/libvirt常用的网络类型了。 本节先介绍虚拟机支持的网络、libvirt管理的虚拟网络,然后讲解具体网络的工作原理。 5.4.1虚拟机支持的网络 为虚拟机创建网络连接的时候,除了需要设置虚拟网卡的设备类型(如: virtio、e1000或rtl8139)之外,我们还需要为其指定网络连接的目标,可以将其分为两类。 (1) 虚拟的网络: 由libvirt来管理维护,例如NAT、Routed和Isolated等。虚拟机的配置是interface type="network"。 (2) 共享的物理设备: 由宿主机操作系统管理维护,例如带物理网卡子接口的网桥、宿主机的物理网卡等。虚拟机配置是interface type="bridge"或interface type="direct"。 在RHEL/CentOS 8中,不同管理工具支持的虚拟机的网络类型、表示方法有些细微的差异。例如: virtmanager(virtmanager2.2.13.el8.noarch)使用Network source的一个选项来设置虚拟机的网络连接,如图512所示。Cockpit(cockpitmachines211.31.el8.noarch)则使用Interface Type和Model两个选项,如图513所示,而通过virsh的edit子命令编辑虚拟机的XML文件则可以支持所有的网络类型(https://libvirt.org/formatdomain.html)。 图512virtmanager2.2.13.el8使用Network Source的一个选项来配置虚拟机的网络接口 图513cockpitmachines211.3使用Interface Type和Model两个选项来配置虚拟机网络接口 表51~表58是不同管理方式的对照。 表51连接到虚拟网络default 工具网卡配置 virtmanager Virtual network 'default': NAT Cockpit Interface Type: Virtual Network Source: default 虚拟机XML 表52连接到虚拟网络isolated1 工具网卡配置 virtmanager Virtual Network 'isolated1': Isolated Network CockpitInterface Type: Virtual Network Source:isolated1 虚拟机XML 表53连接到桥接网络virbr1 工具网卡配置 virtmanager Bridge virbr1: Host device ens34 Cockpit Interface Type: Virtual Network Source: virbr1 虚拟机XML 表54连接宿主机设备ens34(VEPA) 工具网卡配置 virtmanager Host device ens34: macvtap, Source mode: VEPA Cockpit Interface Type: Direct attachment Source: ens34默认是vepa 虚拟机XML 表55连接宿主机设备ens34(Bridge) 工具网卡配置 virtmanager Host device ens34: macvtap, Source mode: Bridge Cockpit Interface Type: Direct attachment Source: ens34需要手工修改mode 虚拟机XML 表56连接宿主机设备ens34(Private) 工具网卡配置 virtmanager Host device ens34: macvtap, Source mode: Private Cockpit Interface Type: Direct attachment Source: ens34需要手工修改mode 虚拟机XML 表57连接宿主机设备ens34(Passthrough) 工具网卡配置 virtmanager Host device ens34: macvtap, Source mode: Passthrough Cockpit Interface Type: Direct attachment Source: ens34需要手工修改mode 虚拟机XML 表58连接指定共享设备 工具网卡配置 virtmanager Specify shared device name Bridge name: brtest Cockpit 不支持 虚拟机XML 5.4.2libvirt管理的虚拟网络 在RHEL/CentOS 8中启动libvirtd守护程序时,libvirtd会读取/etc/libvirt/qemu/networks/autostart/中的符号链接所指向的虚拟网络配置文件,然后使用NetworkManager来创建相应的网桥、TAP等设备,并根据需要配置IP转发、路由表和iptables中的NAT规则,从而为虚拟机提供虚拟网络环境。 图514virtmanager2.2.13.el8 创建虚拟网络 对于虚拟网络,RHEL/CentOS 8中不同管理工具也有一些细微的差异。例如: virtmanager (virtmanager2.2.13.el8.noarch)使用的术语是Mode和Forward to,共用5种Mode,如图514所示。Cockpit(cockpitmachines211.31.el8.noarch)使用的术语主要是Forward Mode和Device,仅有3种Forward Mode,如图515所示,而通过virsh的netcreate、netdefine、netedit和netupdate子命令编辑网络XML文件则支持所有的虚拟网络类型(https://libvirt.org/formatnetwork.html)。 图515cockpitmachines211.3创建虚拟网络 表59~表513是不同管理方式的对照。 表59NAT模式虚拟网络 工具虚拟网络配置 virtmanager Mode: NAT,Forward to: Any physical device Cockpit Forward Mode: NAT,Device: Automatic 虚拟网络XML nat1 表510开放模式虚拟网络 工具虚拟网络配置 virtmanagerMode: Open CockpitForward Mode: Open,IP Configuration: IPv4 only 虚拟网络XML open1 表511隔离模式虚拟网络 工具虚拟网络配置 virtmanager Mode: Isolated Cockpit Forward Mode: None(Isolated Network),IP Configuration: IPv4 only 虚拟网络XML isolated1 续表 工具虚拟网络配置 虚拟网络XML 表512路由模式虚拟网络 工具虚拟网络配置 virtmanager Mode: Routed,Forward to: Any physical device Cockpit 不适用 虚拟网络XML route1 表513SRIOV模式虚拟网络 工具虚拟网络配置 virtmanager Mode: SRIOV pool Cockpit 不适用 虚拟网络XML sriov1 5.4.3NAT模式 对于桌面虚拟化或测试环境来讲,NAT模式是最常用的虚拟网络模式。不需要进行特别配置,此模式的虚拟机就可以访问外部网络,它还允许宿主机与虚拟机之间进行通信。NAT模式的主要“缺点”是宿主机之外的系统无法访问虚拟机。默认的default网络就是NAT模式,如图53所示。 NAT模式的虚拟网络是在iptables的帮助下创建的,其实是使用伪装选项,因此,停止iptables会导致虚拟机内部网络的中断。下面通过实验进行验证,代码如下: 1 #virsh domiflist centos6.10 InterfaceType Source Model MAC ------------------------------------------------------- vnet0 network default virtio 52:54:00:32:f8:e2 2 #virsh domifaddr centos6.10 Name MAC address Protocol Address ------------------------------------------------------- vnet0 52:54:00:32:f8:e2 ipv4 192.168.122.18/24 3 #ssh 192.168.122.18 "ping -c 1 www.baidu.com" root@192.168.122.18's password: 输入虚拟机操作系统root的密码 PING www.wshifen.com (103.235.46.39) 56(84) Bytes of data. 64 Bytes from 103.235.46.39: icmp_seq=1 ttl=127 time=418 ms --- www.wshifen.com ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 418ms rtt min/avg/max/mdev = 418.056/418.056/418.056/0.000 ms 第1行命令的输出结果显示虚拟机centos6.10有一个连接到default网络的网络接口。 第2行命令的输出结果显示这个接口的IP地址是192.168.122.18/24。 第3行命令的输出结果验证了两个结论,一个是在宿主机可以访问处于NAT网络的虚拟机,另外一个是从这台虚拟机可以访问宿主机外部的网络。 接下来执行的命令如下: 4 #systemctl stop firewalld.service 5 #iptables -L -t nat Chain PREROUTING (policy ACCEPT) targetprot opt sourcedestination Chain INPUT (policy ACCEPT) targetprot opt sourcedestination Chain POSTROUTING (policy ACCEPT) targetprot opt sourcedestination Chain OUTPUT (policy ACCEPT) targetprot opt sourcedestination 6 #ssh 192.168.122.18 "ping -c 1 www.baidu.com" root@192.168.122.18's password: PING www.wshifen.com (103.235.46.39) 56(84) Bytes of data. --- www.wshifen.com ping statistics --- 1 packets transmitted, 0 received, 100% packet loss, time 10000ms 第4行命令停止了防火墙服务。从第5行命令的输出中可以看出iptables的NAT表中的所有链的规则均为空。 从第6行命令的输出结果可以看出,这台虚拟机现在无法访问宿主机外部的网络。 提示: 域名解析和DHCP服务是由dnsmasq进程提供的,停止防火墙服务不会影响此进程,所以第6行命令的输出显示域名解析服务工作正常。 5.4.4桥接模式 libvirt不能直接管理桥接模式的网络,所以需要先使用NetworkManager、Cockpit等工具在操作系统中创建一个网桥,然后将一个物理网卡(或捆绑在一起的多个物理网卡)分配给网桥作为子接口,最后将虚拟机连接到此网桥(虚拟交换机),如图516所示。 图516桥接模式的网络 网桥是在OSI网络模型的第2层上运行的。网桥(虚拟交换机)virbr1通过ens32与宿主机外部的网络相连接。虚拟机centos6.10、win2k3与宿主机在同一个子网中,外部物理网络上的主机可以检测到它们并对其进行访问。 5.4.5隔离模式 顾名思义,这是一种封闭的网络,连接在此虚拟交换机的虚拟机可以彼此通信,也可以与宿主机进行通信,但是它们的流量不会通过宿主机扩散到外部,当然也无法从宿主机外部访问它们,如图517所示。 5.4.6路由模式 在路由模式下,宿主机充当路由器并配置路由规则,虚拟机通过虚拟交换机与物理网络相连,如图518所示。使用此模式有一个关键点: 必须在外部的路由器或网关设备上设置正确的IP路由,以便答复数据包返回宿主机,例如: 需要有“将目标地址是192.168.100.0/24的数据包转发给ens32的IP地址”的路由,否则这些回复数据包将永远不会到达宿主机。 图517隔离模式的网络 图518路由模式的网络 提示: 除非有特殊的需求(如防火墙的DMZ区域),才会创建这种复杂性的网络,否则通常不会使用此模式。 5.4.7开放模式 开放模式与路由模式类似,区别在于libvirt是否为虚拟网络设置防火墙规则。 在路由模式中,libvirt会配置防火墙规则,例如允许DHCP、DNS等流量,而在配置开放模式时,libvirt不会在此虚拟网络生成任何iptables规则,这样就需要用户自行配置。这就是“开放”所代表的含义。 图519直接附加模式 5.4.8直接附加模式 虚拟机的直接附加模式既没有使用libvirt管理的虚拟网络,也没有使用宿主机上的网桥,而是通过宿主机上的macvtap驱动程序,将虚拟机的网卡直接附加到宿主机上的指定物理网卡,如图519所示。 这种模式最大的优点是在物理交换机上可以同时知道宿主机和虚拟机的网卡,从而可以进行统一管理。 直接附加有4种模式: VEPA、bridge、private、passthrough,它们在流量控制上有一些差异,默认为VEPA模式。 注意: 不要将此模式与宿主机设备直通(passthrough)混淆。 5.4.9PCI直通与SRIOV KVM Hypervisor可以将宿主机上符合条件的PCI设备分配给虚拟机,这就是PCI直通(PCI passthrough)。它可以使虚拟机独占式地访问PCI设备,而且不需要或很少需要KVM的参与,所以可以提高性能。 目前大多数网卡支持这种特性,通过PCI直通将它们分配给虚拟机,从而满足对网络性能要求比较高的应用需求。 但是在服务器上安装PCI或PCIE设备的数量总是有限的,而且随着设备数量的增加,也会增加成本。SRIOV(Single Root Input/Output Virtualization)就是针对这种问题的一种解决方案。它可以将单个物理PCI设备划分为多个虚拟的PCI设备,然后把它们分配给虚拟机。例如,将宿主机上支持SRIOV功能的网卡划分成多个独立的虚拟网卡,将每个虚拟网卡分配给一个虚拟机使用。 下面就以Intel的X540AT2以太网卡为例进行说明。 首先,保证宿主机上有正确的驱动程序,可以识别到这块网卡,然后使用virtmanager为一台虚拟机添加硬件,单击PCI Host Device,右边就会显示一系列可以分配给虚拟机的PCI设备。选中所需的Intel的X540的Virtual Function,然后单击Finish按钮,如图520所示。这样虚拟机就可以使用这个PCI直通设备了。 图520给虚拟机添加支持SRIOV的网卡 5.5创建和管理隔离的网络 隔离的网络是最简单的网络。本节我们将参考图517所示的拓扑,通过virtmanager、Cockpit和virsh来创建和管理一个名为isolated1的隔离网络。 5.5.1通过virtmanager创建和管理隔离网络 首先,我们通过virtmanager进行创建,然后通过virsh及其他操作系统命令进行查看。 (1) 在virtmanager的Edit菜单上,选择Connection Details。 (2) 在打开的Connection Details菜单中单击Virtual Networks选项卡。 (3) 窗口的左侧列出了所有可用的虚拟网络。单击左下角的按钮,会出现Create a new virtual network窗口,如图521所示。 图521在virtmanager中创建新的隔离网络 (4) 设置新虚拟网络的名称,将Mode设置为Isolated,设置适合的IPv4 configuration。 (5) 单击XML标签,会看到虚拟网络的XML定义,如图522所示。 图522新的隔离网络的XML定义 (6) 单击Finish按钮完成新虚拟网络的创建。新的虚拟网络的信息如图523所示。 图523新的隔离网络的详细信息 下面通过virsh及其他操作系统命令来查看这个新的虚拟网络,命令如下: 1 #virsh net-list Name State Autostart Persistent ------------------------------------------------- default active yes yes isolated1 active yes yes 2 #virsh net-dumpxml isolated1 isolated1 44505edf-d08b-4552-a9f9-0254b80db693 第1行命令的输出显示系统新增加了一个名为isolated1的虚拟网络,它是永久的、自动启动的,而且当前状态是已激活的。 第2行命令的输出显示了isolated1的详细信息,包括以下信息。 (1) name: 提供了虚拟网络的名称。 (2) uuid: 为虚拟网络提供了全局唯一的标识符。 (3) bridge: name属性定义了将用于构建虚拟网络的网桥设备的名称。虚拟机将连接到该网桥,从而使它们可以相互通信。由于当前没有forward元素,所以这是一个隔离网络。以后会学到mode等于nat、route或open的forward元素。属性stp指定是否支持生成树协议。属性delay指定以秒为单位设置延迟值(默认为0)。 (4) mac: address属性定义了一个MAC(硬件)地址。 (5) domain: name属性定义了虚拟网络的名称。 (6) ip: address定义了点分十进制格式的IPv4地址或标准冒号分隔的十六进制格式的IPv6地址,这些地址将在与虚拟网络关联的网桥设备上进行配置。netmask定义了子网掩码。 (7) dhcp: 指定在此虚拟网络上启用DHCP服务。 (8) range: start和end属性指定了要提供给DHCP客户端的地址池的边界。 接下来执行的命令如下: 3 #ls /etc/libvirt/qemu/networks/ autostart default.xml isolated1.xml 4 #cat /etc/libvirt/qemu/networks/isolated1.xml isolated1 44505edf-d08b-4552-a9f9-0254b80db693 5 #ls /etc/libvirt/qemu/networks/autostart/ -l total 0 lrwxrwxrwx. 1 root root 14 Jul 30 16:30 default.xml -> ../default.xml lrwxrwxrwx. 1 root root 40 Nov 23 17:50 isolated1.xml -> /etc/libvirt/qemu/networks/isolated1.xml 第3行命令的输出显示在/etc/libvirt/qemu/networks/目录中,新增了1个XML文件isolated1.xml。不建议直接编辑这个文件,而要使用virsh netedit进行编辑,这是因为它在保存文件时会进行一些必要的检查。 第5行命令的输出显示在/etc/libvirt/qemu/networks/autostart/目录中,有一个指定配置文件的符号链接,这样可以保证在启动libvirtd守护程序时自动启动这个虚拟网络。 接下来执行的命令如下: 6 #ip address … 8: virbr1: mtu 1500 qdisc noqueue state DOWN group default qlen 1000 link/ether 52:54:00:9a:14:dd brd ff:ff:ff:ff:ff:ff inet 192.168.100.1/24 brd 192.168.100.255 scope global virbr1 valid_lft forever preferred_lft forever 9: virbr1-nic: mtu 1500 qdisc fq_codel master virbr1 state DOWN group default qlen 1000 link/ether 52:54:00:9a:14:dd brd ff:ff:ff:ff:ff:ff 7 #nmcli connection NAMEUUID TYPE DEVICE ens32 152beb06-47c5-c5e8-95a9-385590654382 ethernet ens32 virbr0 2ffc46c3-9abb-4071-b5f8-61557313d623 bridge virbr0 virbr1 44d4f380-9fde-4d84-a8c9-1a24d159e30b bridge virbr1 8 #nmcli device DEVICE TYPE STATE CONNECTION ens32 ethernet connected ens32 virbr0 bridge connected virbr0 virbr1 bridge connected virbr1 lo loopback unmanaged -- virbr0-nic tun unmanaged -- virbr1-nic tun unmanaged -- 第6行命令的输出显示系统新增加了1个名为virbr1的网桥,它的IP地址是我们指定的192.168.100.1/24。此网桥有一个名为virbr1nic的子接口,virbr1与virbr1nic的MAC地址都是52:54:00:9a:14:dd。 在第7行、第8行的nmcli的子命令的输出中,也会看到virbr1与virbr1nic。 9#route -n Kernel IP routing table DestinationGatewayGenmaskFlagsMetricRefUseIface 0.0.0.0192.168.114.20.0.0.0UG10200ens32 192.168.100.00.0.0.0255.255.255.0U000 virbr1 192.168.114.00.0.0.0255.255.255.0U10200 ens32 192.168.122.00.0.0.0255.255.255.0U000 virbr0 第9行命令的输出显示在宿主机的路由表中,新增了一个到192.168.100.0/24的路由,接口是virbr1交换机,所以可以在宿主机上访问连接到isolated1网络的虚拟机。 提示: 在创建隔离模式的虚拟网络时,不会引起iptables规则的变化。 当不再需要此虚拟网络的时候,可以在virtmanager中先单击按钮停止网络,然后单击按钮删除网络。 5.5.2通过Cockpit创建和管理隔离网络 通过Cockpit创建和管理隔离网络与virtmanager很类似。 (1) 单击左边导航中的Virtual Machines链接,再单击Networks链接。 (2) 单击Create Virtual Network链接,然后为新虚拟网络设置属性,然后单击Create按钮以完成创建,如图524所示。需要注意的是: IPv4 Network选项设置的是新创建网桥的IP地址,而不是网段的IP地址。 图524在Cockpit中创建新的隔离网络 (3) 与virtmanager不同,还需要单击Activate按钮以激活新创建的虚拟网络。还可以根据需要选中Run when host boots检查框,将虚拟网络设置为自动启动,如图525所示。 图525新的隔离网络的详细信息 当不再需要此虚拟网络的时候,可以单击Deactive按钮停止网络,然后单击Delete按钮删除网络。 5.5.3通过virsh创建和管理隔离网络 virsh管理虚拟网络的子命令多数是以net开头的,可以通过virsh help network获得这些子命令的清单,通过virsh help获得某个子命令的详细帮助,命令如下: 1 #virsh help network Networking (help keyword 'network'): net-autostartautostart a network net-create create a network from an XML file net-define define an inactive persistent virtual network or modify an existing persistent one from an XML file net-destroy destroy (stop) a network net-dhcp-leases print lease info for a given network net-dumpxml network information in XML net-edit edit XML configuration for a network net-event Network Events net-info network information net-list list networks net-name convert a network UUID to network name net-start start a (previously defined) inactive network net-undefine undefine a persistent network net-update update parts of an existing network's configuration net-uuid convert a network name to network UUID 2 #virsh help net-create NAME net-create - create a network from an XML file SYNOPSIS net-create DESCRIPTION Create a network. OPTIONS [--file] file containing an XML network description virsh的netcreate子命令可以根据1个XML文件中的设置来创建临时性的(transient)虚拟网络。netdefine子命令既可以创建新的虚拟网络,也可以修改现有的虚拟网络。netdefine子命令创建的新的虚拟网络是持久的,但默认为未激活,需要使用netstart子命令进行激活。 下面,我们使用netdefine子命令来做一个实验,命令如下: 3#vi isolated1.xml #新虚拟网络的定义如下 isolated1 4 #virsh net-define isolated1.xml Network isolated1 defined from isolated1.xml 5 #virsh net-dumpxml isolated1 isolated1 744c4ba9-cb35-4acc-b577-00b75d4eee52 第3行命令在当前目录下创建了一个新文件,在其中为新的虚拟网络设置了一些必要的属性。如果不指定模式,则默认为隔离模式。如果不指定bridge属性,则libvirt会根据默认值生成一个名称为virbr开头的网桥。 第4行命令定义了一个新的网桥。从第5行命令的输出中可以看到libvirt会生成一些属性值,包括uuid、bridge、mac等。 接下来执行的命令如下: 6 #virsh net-list Name State Autostart Persistent ------------------------------------------------ default active yes yes 7 #virsh net-list --all Name State Autostart Persistent ------------------------------------------------ default active yes yes isolated1 inactive no yes 8 #virsh net-start isolated1 Network isolated1 started 9 #virsh net-autostart isolated1 Network isolated1 marked as autostarted 10 #virsh net-list --all Name State Autostart Persistent ------------------------------------------------ default active yes yes isolated1 active yes yes 由于新增加的虚拟网络并没有被激活,所以它不会出现在第6行命令的输出中。第7行命令有all选项,所以可以看到这个新网络。 第8行命令启动这个网络。第9行命令将其设置为自动启动。 如果需要修改虚拟网络,则既可以通过netedit子命令来编辑XML文件,也可以通过netupdate子命令根据另外一个XML的文件进行更新。 当不再需要某个虚拟网络的时候,可以先使用netdestroy子命令停止它,然后使用netundefine子命令删除它的定义。 5.5.4使用隔离网络 隔离模式允许虚拟机之间相互通信,但是它们无法与外部物理网络进行通信。下面我们通过实验进行验证。 我们将虚拟机centos6.10和win2k3都更改到isolated1这个虚拟网络中。更改虚拟机网络连接的方法很简单,例如在virtmanager中更改虚拟机的网络配置即可,如图526所示。 图526更新虚拟机的网络配置 使用virsh的edit可以修改虚拟机的XML文件。例如将原有虚拟网卡配置进行修改,原配置如下:
修改后的配置如下:
最主要是修改。修改之后重新启动虚拟机即可生效。 如果想修改正在运行的虚拟机网卡配置,则需要使用updatedevice子命令,命令如下: 1 #vi new.xml
2 #virsh update-device --domain centos6.10 --file new.xml --persistent --live Device updated successfully #virsh edit centos6.10 3 #virsh domiflist centos6.10 InterfaceType Source Model MAC ------------------------------------------------------- vnet0 network isolated1 virtio 52:54:00:32:f8:e2 第1行命令创建了包括新配置的XML文件。与原有XML文件的区别主要是这一行。 第2行命令使用XML文件来更新设备。通过domain指定虚拟机的名称、ID或uuid,file后可指定 XML文件,persistent使变化持久,live用于修改正在运行的虚拟机。 从第3行命令的输出可以看出虚拟机的网卡切换到isolated1虚拟网络了。 提示: 如果虚拟机IP是动态IP地址,则需要等到DHCP租期过期后才会更新。如果需要立即更新,就需要在虚拟机操作系统中进行DHCP刷新操作了。 思考: 一台宿主机上可以拥有多个隔离的网络,属于不同隔离网络的虚拟机是否可能通信呢?如果不可以,则是否可以通过调整配置来使它们之间相互通信呢? 5.6创建和管理NAT的网络 5.6.1使用多种方式创建NAT网络 在RHEL/CentOS 8上安装KVM虚拟化组件的时候,会自动创建一个名为default的NAT网络。一台宿主机上可以有多个采用NAT模式的虚拟网络,下面我们再创建一个名为nat2的NAT模式的虚拟网络。 如果使用virtmanager来创建,则需要将Mode设置为NAT,可以保持Forward to为Any physical device,设置适合的IPv4 configuration,如图527所示。 图527在virtmanager中创建新的NAT网络 单击XML选项卡可以查看新网络的XML定义,单击Finish按钮完成定义,如图528所示。 图528在virtmanager查看新的网络的XML定义 在Cockpit创建新的NAT网络的方式与virtmanager类似,不过需要注意的是: IPv4 Network选项设置的是新创建网桥的IP地址,而不是网段的IP地址,如图529所示。 图529在Cockpit中创建新的NAT网络 通过virsh来创建NAT模式的网络,仍然需要使用XML格式的配置文件,命令如下: 1 #vi new.xml nat2 2 #virsh net-define new.xml Network nat2 defined from new.xml 3 #virsh net-autostart nat2 Network nat2 marked as autostarted 4 #virsh net-start nat2 Network nat2 started 5 #virsh net-list --all Name State Autostart Persistent ---------------------------------------------------------- default active yes yes nat2 active yes yes 第1行命令在当前目录下创建了一个新文件,在其中为新的虚拟网络设置了一些必要的属性。“”定义的虚拟网络是NAT。如果不指定bridge属性,则libvirt会生成一个以virbr开头的网桥。 第2行命令定义了一个新的网桥。 第3行命令设置为自动启动,第4行命令用于启动这个网络。 接下来执行的命令如下: 6 #ip address … 6: virbr1: mtu 1500 qdisc noqueue state DOWN group default qlen 1000 link/ether 52:54:00:4d:94:67 brd ff:ff:ff:ff:ff:ff inet 192.168.100.1/24 brd 192.168.100.255 scope global virbr1 valid_lft forever preferred_lft forever 7: virbr1-nic: mtu 1500 qdisc fq_codel master virbr1 state DOWN group default qlen 1000 link/ether 52:54:00:4d:94:67 brd ff:ff:ff:ff:ff:ff 7 #virsh net-dumpxml nat2 nat2 8a54c7f3-e910-4d12-8312-34a11467ac86 第6行命令的输出显示: 新增1个名为virbr1的网桥,它有1个名为virbr1nic的子接口。网桥virbr1与virbr1nic的MAC地址相同。 第7行命令会输出新网桥的详细信息,会看到有些属性使用了默认值或是自动生成的。 接下来执行的命令如下: 8 #iptables -L -t nat -n Chain PREROUTING (policy ACCEPT) targetprot opt sourcedestination Chain INPUT (policy ACCEPT) targetprot opt sourcedestination Chain POSTROUTING (policy ACCEPT) targetprot opt sourcedestination RETURN all -- 192.168.100.0/24 224.0.0.0/24 RETURN all -- 192.168.100.0/24 255.255.255.255 MASQUERADE tcp -- 192.168.100.0/24 !192.168.100.0/24masq ports: 1024-65535 MASQUERADE udp -- 192.168.100.0/24 !192.168.100.0/24masq ports: 1024-65535 MASQUERADE all -- 192.168.100.0/24 !192.168.100.0/24 RETURN all -- 192.168.122.0/24 224.0.0.0/24 RETURN all -- 192.168.122.0/24 255.255.255.255 MASQUERADE tcp -- 192.168.122.0/24 !192.168.122.0/24masq ports: 1024-65535 MASQUERADE udp -- 192.168.122.0/24 !192.168.122.0/24masq ports: 1024-65535 MASQUERADE all -- 192.168.122.0/24 !192.168.122.0/24 Chain OUTPUT (policy ACCEPT) targetprot opt sourcedestination 9 #route -n Kernel IP routing table Destination Gateway Genmask FlagsMetricRef UseIface 0.0.0.0 192.168.114.2 0.0.0.0 UG 100 0 0 ns32 192.168.100.0 0.0.0.0 255.255.255.0 U 0 0 0 virbr1 192.168.114.0 0.0.0.0 255.255.255.0 U 100 0 0 ens32 192.168.122.0 0.0.0.0 255.255.255.0 U 0 0 0 virbr0 libvirt会根据NAT模式的虚拟网络的配置来修改iptables的NAT规则和系统的路由。 从第8行命令的输出可以看到在iptables的NAT表的POSTROUTING链中有多条针对192.168.100.0/24的规则。正是由于这些规则才使连接到nat2网络中的虚拟机可以访问外部的网络。 第9行命令的输出显示在宿主机的路由表中,新增了一个到192.168.100.0/24的路由,目标地址是这个网络的数据包将通过virbr1交换机输送出去。这样,就可以在宿主机上访问连接到nat2网络的虚拟机了,而且属于default网络的虚拟机也可以访问nat2网络的虚拟机。 5.6.2使用NAT网络 在实验环境中,准备使用两台虚拟机来做实验。win2k3还是属于default网络,将centos6.10修改为nat2,命令如下: 1 #virsh edit centos6.10 …
… 2 #virsh start centos6.10 3 #virsh start win2k3 第1行命令用于编辑虚拟配置的XML文件,修改网卡的属性source,并将其修改为。 第2行、第3行命令分别启动了这2台属于不同虚拟网络的虚拟机。 接下来执行的命令如下: 4 #ip address … 8: vnet0: mtu 1500 qdisc fq_codel master virbr1 state UNKNOWN group default qlen 1000 link/ether fe:54:00:27:5f:c9 brd ff:ff:ff:ff:ff:ff inet6 fe80::fc54:ff:fe27:5fc9/64 scope link valid_lft forever preferred_lft forever 9: vnet1: mtu 1500 qdisc fq_codel master virbr0 state UNKNOWN group default qlen 1000 link/ether fe:54:00:9d:57:9c brd ff:ff:ff:ff:ff:ff inet6 fe80::fc54:ff:fe9d:579c/64 scope link valid_lft forever preferred_lft forever … 5 #virsh domiflist centos6.10 Interface Type Source Model MAC ------------------------------------------------------- vnet0 network nat2 virtio 52:54:00:27:5f:c9 6 #virsh domifaddr centos6.10 Name MAC address Protocol Address ----------------------------------------------------------------- vnet0 52:54:00:27:5f:c9 ipv4 192.168.100.139/24 7 #virsh domiflist win2k3 Interface Type Source Model MAC ------------------------------------------------------- vnet1 network default e1000 52:54:00:9d:57:9c 8 #virsh domifaddr win2k3 Name MAC address Protocol Address ----------------------------------------------------------------- vnet1 52:54:00:9d:57:9c ipv4 192.168.122.41/24 从第3行命令的输出可以看到宿主机上新增了2个TAP类型的虚拟网络接口vnet0和vnet1,它们分别是网桥virbr1和virbr0的子接口。 从第5行至第8行的输出可以看出: 虚拟机centos6.10连接到虚拟网络nat2,它的IP地址是DNSMASQ分配的192.168.100.139/2。虚拟机win2k3连接到虚拟网络default,它的IP地址是DNSMASQ分配的192.168.122.41/24。 提示: 宿主机上名称为vnet开头的TAP设备与虚拟机的以太网卡是“一对”设备,它们的MAC地址后面5组2位十六进制数字是相同的,例如: vnet0与centos6.10的eth0的MAC地址都是以“54:00:27:5f:c9”结束。 下面,我们连接到虚拟机centos6.10(192.168.100.139)来做一些测试,命令如下: 9 #ssh 192.168.100.139 "ping -c 2 www.baidu.com" root@192.168.100.139's password: PING www.wshifen.com (103.235.46.39) 56(84) Bytes of data. 64 Bytes from 103.235.46.39: icmp_seq=1 ttl=127 time=278 ms 64 Bytes from 103.235.46.39: icmp_seq=2 ttl=127 time=277 ms --- www.wshifen.com ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1281ms rtt min/avg/max/mdev = 277.802/278.094/278.387/0.603 ms 10 #ssh 192.168.100.139 "ping -c 2 192.168.122.41" root@192.168.100.139's password: PING 192.168.122.41 (192.168.122.41) 56(84) Bytes of data. 64 Bytes from 192.168.122.41: icmp_seq=1 ttl=127 time=1.96 ms 64 Bytes from 192.168.122.41: icmp_seq=2 ttl=127 time=2.10 ms --- 192.168.122.41 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1005ms rtt min/avg/max/mdev = 1.962/2.034/2.107/0.085 ms 从第9行命令的输出中可以看出: 从宿主机可以访问连接到虚拟网络nat2的虚拟机,而这些虚拟机可以通过宿主机的NAT功能访问外部网络资源。 从第10行命令的输出可以看出: 连接到虚拟网络nat2的虚拟机也可以访问同一宿主机上的其他NAT网络中的虚拟机(default网络中的win2k3)。 5.7创建和管理桥接的网络 桥接模式的网络是很常见的,外部网络上的主机可以访问这种连接模式网桥中的虚拟机。 下面按图516所示的拓扑来做一个桥接模式网络的实验。 5.7.1在宿主机上创建网桥 执行的命令如下: 1 #ip address 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens32: mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 00:0c:29:b3:73:36 brd ff:ff:ff:ff:ff:ff inet 192.168.114.231/24 brd 192.168.114.255 scope global noprefixroute ens32 valid_lft forever preferred_lft forever inet6 fe80::c589:de19:7895:d32e/64 scope link noprefixroute valid_lft forever preferred_lft forever 3: virbr0: mtu 1500 qdisc noqueue state DOWN group default qlen 1000 link/ether 52:54:00:fd:b2:60 brd ff:ff:ff:ff:ff:ff inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0 valid_lft forever preferred_lft forever 4: virbr0-nic: mtu 1500 qdisc fq_codel master virbr0 state DOWN group default qlen 1000 link/ether 52:54:00:fd:b2:60 brd ff:ff:ff:ff:ff:ff 第1行命令会显示创建新网桥之前网络接口的信息。IP地址192.168.114.231/24是与ens32相关联的。 使用Cockpit来创建网桥是最简单的方法。新网桥的名称是virbr1。将宿主机上唯一的物理网卡en32作为它的子接口,如图530所示。 图530使用Cockpit创建新的网桥 接下来执行的命令如下: 2 #ip address 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens32: mtu 1500 qdisc fq_codel master virbr1 state UP group default qlen 1000 link/ether 00:0c:29:b3:73:36 brd ff:ff:ff:ff:ff:ff 3: virbr0: mtu 1500 qdisc noqueue state DOWN group default qlen 1000 link/ether 52:54:00:fd:b2:60 brd ff:ff:ff:ff:ff:ff inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0 valid_lft forever preferred_lft forever 4: virbr0-nic: mtu 1500 qdisc fq_codel master virbr0 state DOWN group default qlen 1000 link/ether 52:54:00:fd:b2:60 brd ff:ff:ff:ff:ff:ff 5: virbr1: mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:0c:29:b3:73:36 brd ff:ff:ff:ff:ff:ff inet 192.168.114.231/24 brd 192.168.114.255 scope global noprefixroute virbr1 valid_lft forever preferred_lft forever inet6 fe80::17b3:2554:31a6:df6e/64 scope link noprefixroute valid_lft forever preferred_lft forever 3 #nmcli connection NAME UUID TYPE DEVICE virbr1 66629af3-7afb-4cbd-9170-020a9f9cb805 bridge virbr1 virbr0 665697d3-824e-4832-b057-14acf8d379e0 bridge virbr0 ens32 152beb06-47c5-c5e8-95a9-385590654382 ethernet ens32 第2行命令输出了创建新网桥之后网络接口的信息。IP地址192.168.114.231/24与virbr1相关联,ens32则成为virbr1的子接口。网桥virbr1与第1个子接口也就是ens32的MAC地址是相同的,都是“00:0c:29:b3:73:36”。 注意: 如果宿主机上仅有一个网卡,而且在远程通过nmcli或网络接口配置文件来创建网桥,就要特别小心,因为错误的配置会导致无法再进行远程连接。 接下来执行的命令如下: 4 #cat /etc/sysconfig/network-scripts/ifcfg-virbr1 STP=no TYPE=Bridge PROXY_METHOD=none BROWSER_ONLY=no BOOTPROTO=none IPADDR=192.168.114.231 PREFIX=24 GATEWAY=192.168.114.2 DNS1=8.8.8.8 DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=yes IPV6_AUTOCONF=yes IPV6_DEFROUTE=yes IPV6_FAILURE_FATAL=no IPV6_ADDR_GEN_MODE=stable-privacy NAME=virbr1 UUID=66629af3-7afb-4cbd-9170-020a9f9cb805 DEVICE=virbr1 ONBOOT=yes AUTOCONNECT_SLAVES=yes 5 #cat /etc/sysconfig/network-scripts/ifcfg-ens32 TYPE=Ethernet PROXY_METHOD=none BROWSER_ONLY=no DEFROUTE=yes IPV4_FAILURE_FATAL=no NAME=ens32 DEVICE=ens32 ONBOOT=yes IPADDR=192.168.114.231 PREFIX=24 GATEWAY=192.168.114.2 DNS1=8.8.8.8 UUID=152beb06-47c5-c5e8-95a9-385590654382 BRIDGE=virbr1 第4行命令会显示新网桥virbr1的网络接口配置文件的内容,其中最重要的属性是TYPE=Bridge。 第5行命令显示了配置文件ifcfgens32的变化。这个修改后的配置文件不是特别“干净”,有一些无用信息。不过最关键的属性是BRIDGE=virbr1。 5.7.2使用网桥 以虚拟机centos6.10为例,我们通过Cockpit来修改其网络接口的配置。在Interface Type中选择Bridge to LAN,然后在Source中选择virbr1,单击Save按钮保存更改,如图531所示。 图531使用Cockpit更新虚拟机的网络配置 执行的命令如下: 1 #virsh domiflist centos6.10 Interface Type Source Model MAC ------------------------------------------------------- - bridge virbr1 virtio 52:54:00:32:f8:e2 2 #virsh dumpxml centos6.10 …
… 3 #virsh start centos6.10 4 #ping -c 2 192.168.114.129 PING 192.168.114.129 (192.168.114.129) 56(84) Bytes of data. 64 Bytes from 192.168.114.129: icmp_seq=1 ttl=64 time=1.15 ms 64 Bytes from 192.168.114.129: icmp_seq=2 ttl=64 time=0.940 ms --- 192.168.114.129 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 3ms rtt min/avg/max/mdev = 0.940/1.047/1.154/0.107 ms 第1行命令的输出内容显示了此虚拟机已经连接网桥virbr1。 第2行命令的输出内容显示了它的网桥接口类型是。 第3行命令用于启动虚拟机。这时,虚拟机centos6.10会从宿主机所在物理网络中的DHCP服务器获得IP地址。我们可以登录到此虚拟机查看其IP地址,在本示例中是192.168.114.129 第4行命令用于对这个IP地址进行测试。当然外部物理网络上的其他主机也可以访问此虚拟机。 5.8创建和管理路由的网络 路由模式不是很常见。在这种模式中,宿主机充当虚拟网络与外部物理网络之间的路由器,而且会自动配置正确的路由条目。这种模式的关键点是在宿主机之外的路由设置,需要用到虚拟网络的“返程”路由。 我们将根据图532所示的拓扑来做一个实验。在这个实验中,宿主机网卡ens32的IP地址是192.168.1.231/24,需要创建的新虚拟网络的IP地址是192.168.100.0/24。除了在宿主机上进行配置外,还需要在宿主机之外的设备上配置正确的路由条目,在此实验中,将在外部主机192.168.1.48/24上添加“将目标地址是192.168.100.0/24的数据包转发给192.168.1.231”的路由条目。 图532路由模式网络实验拓扑 5.8.1在宿主机上创建路由模式的网络 当前版本的Cockpit虚拟化插件(cockpitmachines211.31.el8.noarch)不支持创建路由模式的网络,但是可以正确地显示路由模式的网络。我们可以通过virtmanager来创建路由模式的网络。创建时,将Mode设置为Routed,可以保持Forward to为Any physical device,设置适合的IPv4 configuration,如图533所示。 图533使用virtmanager创建路由模式网络 仍然使用virsh的netdefine子命令来创建,创建时需要使用XML格式文件的内容如下: route1 libvirt在创建新的路由模式网络的时候,会在宿主机上创建新网桥及其子接口、增加路由中的路由条目、增加防火墙规则,执行的命令如下: 1 #ip address 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens32: mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 00:0c:29:b3:73:36 brd ff:ff:ff:ff:ff:ff inet 192.168.1.231/24 brd 192.168.1.255 scope global noprefixroute ens32 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:feb3:7336/64 scope link valid_lft forever preferred_lft forever 3: virbr0: mtu 1500 qdisc noqueue state DOWN group default qlen 1000 link/ether 52:54:00:fd:b2:60 brd ff:ff:ff:ff:ff:ff inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0 valid_lft forever preferred_lft forever 4: virbr0-nic: mtu 1500 qdisc fq_codel master virbr0 state DOWN group default qlen 1000 link/ether 52:54:00:fd:b2:60 brd ff:ff:ff:ff:ff:ff 5: virbr1: mtu 1500 qdisc noqueue state DOWN group default qlen 1000 link/ether 52:54:00:d2:32:33 brd ff:ff:ff:ff:ff:ff inet 192.168.100.1/24 brd 192.168.100.255 scope global virbr1 valid_lft forever preferred_lft forever 6: virbr1-nic: mtu 1500 qdisc fq_codel master virbr1 state DOWN group default qlen 1000 link/ether 52:54:00:d2:32:33 brd ff:ff:ff:ff:ff:ff 2 #virsh net-list Name State Autostart Persistent ---------------------------------------------------------- default active yes yes route1 active yes yes 3 #virsh net-info route1 Name: route1 UUID: e166c9be-b791-4ea4-814a-6f1c99326eea Active: yes Persistent: yes Autostart: yes Bridge: virbr1 4 #virsh net-dumpxml route1 route1 e166c9be-b791-4ea4-814a-6f1c99326eea 第1行命令的输出内容显示了新网桥的名称virbr1,其IP地址是192.168.100.1/24。virbr1有1个接口virbr1nic。 第2行命令的输出内容显示了当前虚拟网络的列表。 第3行、第4行命令的输出内容显示了新虚拟网络的详细信息。 接下来执行的命令如下: 5 #route -n Kernel IP routing table Destination Gateway Genmask FlagsMetricRefUse Iface 0.0.0.0 192.168.1.2 0.0.0.0 UG 100 0 0 ens32 192.168.1.0 0.0.0.0 255.255.255.0 U 100 0 0 ens32 192.168.100.0 0.0.0.0 255.255.255.0 U 0 0 0 virbr1 192.168.122.0 0.0.0.0 255.255.255.0 U 0 0 0 virbr0 在第5行命令的输出中看到了新增加的路由条目: 目标是192.168.100.0/24的数据将被发送给virbr1,也就是新的虚拟网络。 接下来执行的命令如下: 6 #iptables -L -n -v Chain INPUT (policy ACCEPT 202 packets, 17430 Bytes) targetprot opt inoutsourcedestination ACCEPTudp -- virbr1 *0.0.0.0/0 0.0.0.0/0udp dpt:53 ACCEPTtcp -- virbr1 *0.0.0.0/0 0.0.0.0/0tcp dpt:53 ACCEPTudp -- virbr1 *0.0.0.0/0 0.0.0.0/0udp dpt:67 ACCEPTtcp -- virbr1 *0.0.0.0/0 0.0.0.0/0tcp dpt:67 ACCEPTudp -- virbr0 *0.0.0.0/0 0.0.0.0/0udp dpt:53 ACCEPTtcp -- virbr0 *0.0.0.0/0 0.0.0.0/0tcp dpt:53 ACCEPTudp -- virbr0 *0.0.0.0/0 0.0.0.0/0udp dpt:67 ACCEPTtcp -- virbr0 *0.0.0.0/0 0.0.0.0/0tcp dpt:67 Chain FORWARD (policy ACCEPT 0 packets, 0 Bytes) target prot opt in out source destination ACCEPT all -- * virbr1 0.0.0.0/0 192.168.100.0/24 ACCEPT all -- virbr1 * 192.168.100.0/24 0.0.0.0/0 ACCEPT all -- virbr1 virbr1 0.0.0.0/0 0.0.0.0/0 REJECT all -- * virbr1 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable REJECT all -- virbr1 * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable ACCEPTall -- * virbr0 0.0.0.0/0 192.168.122.0/24ctstate RELATED,ESTABLISHED ACCEPT all -- virbr0 * 192.168.122.0/24 0.0.0.0/0 ACCEPT all -- virbr0 virbr0 0.0.0.0/0 0.0.0.0/0 REJECT all -- * virbr0 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable REJECT all -- virbr0 * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable Chain OUTPUT (policy ACCEPT 177 packets, 21663 Bytes) target prot opt in out source destination ACCEPT udp -- * virbr1 0.0.0.0/0 0.0.0.0/0 udp dpt:68 ACCEPT udp -- * virbr0 0.0.0.0/0 0.0.0.0/0 udp dpt:68 从第6行命令的输出中可以看到新增加的防火墙规则。 (1) INPUT链: 允许virbr1入站的DNS(53端口)和DHCP(67端口)的包。 (2) FORWARD链: 允许源是virbr1出站及相关联的返回包,源与目标都是virbr1的包,拒绝icmpportunreachable类型的包。 (3) OUTPUT链: 允许virbr1出站的DHCP(68端口)的包。 5.8.2使用路由模式的网络 将虚拟机centos6.10调整到新增加的虚拟网络,命令如下: 1 #virsh edit centos6.10 …
… 2 #virsh start centos6.10 3 #virsh domiflist centos6.10 Interface Type Source Model MAC ------------------------------------------------------- vnet0 network route1 virtio 52:54:00:32:f8:e2 4 #virsh domifaddr centos6.10 Name MAC address Protocol Address ----------------------------------------------------------------- vnet0 52:54:00:32:f8:e2 ipv4 192.168.100.182/24 第1行命令用于编辑虚拟机的配置文件,其核心属性是。 第2行命令用于启动这台虚拟机。 第3行命令的输出显示此虚拟机已经切换到新的名为route1的虚拟网络中了。 第4行命令显示虚拟机的IP地址是192.168.100.182/24,它是由宿主机的DNSMASQ组件分配的。 接下来执行的命令如下: 5 #ssh 192.168.100.182 "route -n" root@192.168.100.182's password: Kernel IP routing table Destination Gateway Genmask FlagsMetricRef Use Iface 192.168.100.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 169.254.0.0 0.0.0.0 255.255.0.0 U 1002 0 0 eth0 0.0.0.0 192.168.100.1 0.0.0.0 UG 0 0 0 eth0 6 #ssh 192.168.100.182 "ping -c 2 192.168.1.231" root@192.168.100.182's password: PING 192.168.1.231 (192.168.1.231) 56(84) Bytes of data. 64 Bytes from 192.168.1.231: icmp_seq=1 ttl=64 time=0.300 ms 64 Bytes from 192.168.1.231: icmp_seq=2 ttl=64 time=0.582 ms --- 192.168.1.231 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1002ms rtt min/avg/max/mdev = 0.300/0.441/0.582/0.141 ms 7 #ssh 192.168.100.182 "ping -c 2 192.168.1.48" root@192.168.100.182's password: PING 192.168.1.48 (192.168.1.48) 56(84) Bytes of data. --- 192.168.1.48 ping statistics --- 2 packets transmitted, 0 received, 100% packet loss, time 11003ms 第5行命令的输出显示了虚拟机操作系统中的路由表,其缺省网关是192.168.100.1,也就是宿主中的virbr1。 第6行命令从虚拟机中ping宿主机的ens32的IP地址,由于宿主机知道192.168.100.0/24在哪里,所以可以正常返回响应。 第7行命令从虚拟机中ping宿主机之外的主机(192.168.1.48),从输出信息中可以看到: 没有收到响应的包(0 received)。 这是由于在外部主机192.168.1.48上没有到192.168.100.0/24的正确路由。 在本实验中,192.168.1.48是一台Windows 10的计算机,所以可以通过route print查看其路由表,命令如下: C:\WINDOWS\system32>route print -4 ================================================================== 接口列表 4...38 d5 47 b9 33 c6 ......Realtek PCIe GbE Family Controller 1...........................Software Loopback Interface 1 ================================================================== IPv4 路由表 ================================================================== 活动路由: 网络目标 网络掩码 网关 接口 跃点数 0.0.0.0 0.0.0.0 192.168.1.1 192.168.1.48 291 127.0.0.0 255.0.0.0 在链路上 127.0.0.1 331 127.0.0.1 255.255.255.255 在链路上 127.0.0.1 331 127.255.255.255 255.255.255.255 在链路上 127.0.0.1 331 192.168.1.0 255.255.255.0 在链路上 192.168.1.48 291 192.168.1.48 255.255.255.255 在链路上 192.168.1.48 291 192.168.1.255 255.255.255.255 在链路上 192.168.1.48 291 224.0.0.0 240.0.0.0 在链路上 127.0.0.1 331 224.0.0.0 240.0.0.0 在链路上 192.168.1.48 291 255.255.255.255 255.255.255.255 在链路上 127.0.0.1 331 255.255.255.255 255.255.255.255 在链路上 192.168.1.48 V 291 ================================================================== 永久路由: 网络地址 网络掩码 网关地址 跃点数 0.0.0.0 0.0.0.0 192.168.1.1 默认 ================================================================== 由于在路由表中没有与192.168.100.0/24相匹配的条目,所以它会将响应192.168.100.0/24的包发给默认网关(192.168.1.1),而不是宿主机的IP地址192.168.1.231。在本实验中,可以通过添加静态路由来解决这个问题,命令如下: C:\WINDOWS\system32>route add 192.168.100.0 MASK 255.255.255.0 192.168.1.231 C:\WINDOWS\system32>route print -4 | find "192.168.100" 192.168.100.0255.255.255.0192.168.1.231192.168.1.4836 这样就可以ping通了,命令如下: 9 #ssh 192.168.100.182 "ping -c 2 192.168.1.48" root@192.168.100.182's password: PING 192.168.1.48 (192.168.1.48) 56(84) Bytes of data. 64 Bytes from 192.168.1.48: icmp_seq=1 ttl=127 time=0.857 ms 64 Bytes from 192.168.1.48: icmp_seq=2 ttl=127 time=1.86 ms --- 192.168.1.48 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1004ms rtt min/avg/max/mdev = 0.857/1.363/1.869/0.506 ms 5.9创建和管理开放的网络 开放模式与路由模式类似,其主要区别是libvirt不会为开放模式设置防火墙规则。下面通过实验来查看这种模式,命令如下: 1 #vi new.xml open1 2 #virsh net-define new.xml 3 #virsh net-autostart open1 4 #virsh net-start open1 5 #virsh net-list Name State Autostart Persistent ---------------------------------------------------------- default active yes yes open1 active yes yes 第1行命令用于创建新网络的XML定义文件。 第2行命令通过XML文件定义新网络,第3行命令用于设置自动启动,第4行命令用于启动这个开放式网络。 第5行命令的输出显示新网络创建成功了。 接下来执行的命令如下: 6 #virsh net-info open1 Name: open1 UUID: 55dfc4da-dccf-47b7-a2b9-d2f5c130804c Active: yes Persistent: yes Autostart: yes Bridge: virbr1 7 #virsh net-dumpxml open1 open1 55dfc4da-dccf-47b7-a2b9-d2f5c130804c 通过第6行、第7行命令可以查看新网络的信息。 接下来执行的命令如下: 8 #ip address 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens32: mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 00:0c:29:f7:6b:c8 brd ff:ff:ff:ff:ff:ff inet 192.168.1.48/24 brd 192.168.1.255 scope global noprefixroute ens32 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fef7:6bc8/64 scope link valid_lft forever preferred_lft forever 3: virbr0: mtu 1500 qdisc noqueue state DOWN group default qlen 1000 link/ether 52:54:00:e0:41:ac brd ff:ff:ff:ff:ff:ff inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0 valid_lft forever preferred_lft forever 4: virbr0-nic: mtu 1500 qdisc fq_codel master virbr0 state DOWN group default qlen 1000 link/ether 52:54:00:e0:41:ac brd ff:ff:ff:ff:ff:ff 5: virbr1: mtu 1500 qdisc noqueue state DOWN group default qlen 1000 link/ether 52:54:00:16:a8:57 brd ff:ff:ff:ff:ff:ff inet 192.168.100.1/24 brd 192.168.100.255 scope global virbr1 valid_lft forever preferred_lft forever 6: virbr1-nic: mtu 1500 qdisc fq_codel master virbr1 state DOWN group default qlen 1000 link/ether 52:54:00:16:a8:57 brd ff:ff:ff:ff:ff:ff 从第8行命令的输出可以看出:新增加了1个名为virbr1的网桥,其IP地址是192.168.100.1/24,它有一个名为virbr1nic的子接口。 接下来执行的命令如下: 9 #iptables -L -n -v Chain INPUT (policy ACCEPT 963 packets, 70270 Bytes) target prot opt inout sourcedestination ACCEPTudp -- virbr0 *0.0.0.0/00.0.0.0/0udp dpt:53 ACCEPTtcp -- virbr0 *0.0.0.0/00.0.0.0/0tcp dpt:53 ACCEPTudp -- virbr0 *0.0.0.0/00.0.0.0/0udp dpt:67 ACCEPTtcp -- virbr0 *0.0.0.0/00.0.0.0/0tcp dpt:67 Chain FORWARD (policy ACCEPT 0 packets, 0 Bytes) target prot opt inoutsourcedestination ACCEPT all-- *virbr00.0.0.0/0192.168.122.0/24ctstate RELATED,ESTABLISHED ACCEPT all-- virbr0 *192.168.122.0/240.0.0.0/0 ACCEPT all-- virbr0 virbr00.0.0.0/00.0.0.0/0 REJECT all-- * virbr00.0.0.0/00.0.0.0/0reject-with icmp-port-unreachable REJECT all-- virbr0 *0.0.0.0/00.0.0.0/0reject-with icmp-port-unreachable Chain OUTPUT (policy ACCEPT 508 packets, 62659 Bytes) target prot opt inoutsourcedestination ACCEPT udp -- *virbr00.0.0.0/00.0.0.0/0udp dpt:68 与路由模式不同,libvirt不会为开放模式的网络设置防火墙规则,所以不会在第9行命令的输出中看到与192.168.100.0/24和virbr1相关的策略。 接下来执行的命令如下: 10 #virsh edit centos6.10 …
… 11 #virsh start centos6.10 第10行命令用于修改虚拟机centos6.10的网卡属性,使其连接到open1这个开放的网络。 第11行命令用于启动虚拟机。 默认情况下,即使为open1网络配置DHCP地址范围(192.168.100.128至192.168.100.254),虚拟机centos6.10也无法得到IP地址,如图534所示。 图534开放模式网络中虚拟机无法通过DHCP获得IP地址 接下来执行的命令如下: 12 #virsh net-dhcp-leases open1 Expiry TimeMAC addressProtocolIP addressHostnameClient ID or DUID ---------------------------------------------------------------- 第12行命令的输出也显示了这个名为open1的网络并没有为虚拟机分配IP地址。 出现这种现象的原因是: libvirt并没有为192.168.100.0/24和virbr1设置允许DHCP数据的规则,所以虚拟机发出的DHCPDISCOVER包并没有被宿主机上的DNSMASQ组件收到。 如果希望为open1中的虚拟机自动分配IP地址,就需要手工添加防火墙规则。命令如下: 13 #firewall-cmd --list-all public (active) target: default icmp-block-inversion: no interfaces: ens32 sources: services: cockpit dhcpv6-client ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: 14 #firewall-cmd --add-interface=virbr1 15 #firewall-cmd --add-service=dhcp 16 #firewall-cmd --list-all public (active) target: default icmp-block-inversion: no interfaces: ens32 virbr1 sources: services: cockpit dhcp dhcpv6-client ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: RHEL/CentOS 8推荐使用firewall的firewallcmd命令来管理防火墙。通过第13行命令来获得当前防火墙配置的概要信息。 第14行命令向public区域添加了一个接口virbr1。第15行命令又允许DHCP服务,这样将允许来自open1网络的与DHCP相关的数据包到达宿主机,DNSMASQ收到后就会为其分配IP地址。 接下来执行的命令如下: 17 #virsh net-dhcp-leases open1 Expiry TimeMAC addressProtocol IP addressHostname Client ID or DUID ----------------------------------------------------------- 2020-12-0120:56:0352:54:00:32:f8:e2ipv4192.168.100.182/24 第17行命令的输出显示: 向虚拟机分配的IP地址是192.168.100.182/24。 后续的配置与路由模式类似,这里就不再赘述了。 提示: 如果需要使防火墙配置永久生效,还需要使用permanent选项来执行firewallcmd命令。 在配置路由模式时,libvirt会为其配置防火墙规则,例如允许DHCP、DNS等流量,而在配置开放模式时,libvirt不会为此虚拟网络生成任何iptables规则,这样就需要用户自行配置了。 5.10实现多VLAN支持 虚拟局域网(Virtual LAN,VLAN)是物理网络中的逻辑网络,它提高了网络管理的安全性与灵活性。通过使用VLAN标记,可以将每个以太网端口都视为包含许多逻辑端口。通过合理的规划与配置,可以在一台KVM宿主机中运行属于不同VLAN的虚拟机,如图535所示。 图535同一个宿主机中可以运行属于多个不同VLAN的虚拟机 图535中的物理网络有两个VLAN,其ID分别是11和12。虚拟机centos6.10属于ID为11的VLAN,虚拟机Win2k3则属于ID为12的VLAN。 首先,需要在宿主机现有接口(例如以太网卡、绑定网卡或网桥设备)上创建VLAN接口,在图535中这个接口是物理网卡ens32。在ens32上创建两个使用不同VLAN ID的虚拟网络接口VLAN11和VLAN12,ens32被称为VLAN11、VLAN12的“父”接口。 然后创建两个网桥virbr1和virbr2。其中virbr1的子接口是VLAN11,virbr2的子接口是VLAN12。 将虚拟机centos6.10桥接到virbr1,而虚拟机Win2k3则需要桥接到virbr2。 在宿主机所在的物理网络中也需要进行设置,主要就是将宿主机网卡ens32所连接的交换机端口配置为trunk模式。 5.10.1创建支持VLAN的网络接口 Linux通过在内核中加载8021q模块实现VLAN功能。在RHEL/CentOS 8中,默认情况下会根据需要自动加载8021q模块。在其他的Linux发版本中,可能需要使用modprobe命令来手工加载。 在RHEL/CentOS 8中,既可以通过iproute2、NetworkManager、Cockpit等多种工具来管理VLAN,也可以直接编辑/etc/sysconfig/networkscripts/目录下的网络接口脚本文件实现VLAN的管理。由于iproute2中的ip命令所创建的VLAN不是永久性的,所以不推荐使用。下面,我们通过nmcli和Cockpit这两种工具来创建和管理VLAN,命令如下: 1 #ip address 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens32: mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 00:0c:29:b3:73:36 brd ff:ff:ff:ff:ff:ff inet 192.168.1.231/24 brd 192.168.1.255 scope global noprefixroute ens32 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:feb3:7336/64 scope link valid_lft forever preferred_lft forever 3: virbr0: mtu 1500 qdisc noqueue state DOWN group default qlen 1000 link/ether 52:54:00:fd:b2:60 brd ff:ff:ff:ff:ff:ff inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0 valid_lft forever preferred_lft forever 4: virbr0-nic: mtu 1500 qdisc fq_codel master virbr0 state DOWN group default qlen 1000 link/ether 52:54:00:fd:b2:60 brd ff:ff:ff:ff:ff:ff 2 #ls /etc/sysconfig/network-scripts/ ifcfg-ens32 3 #cat /etc/sysconfig/network-scripts/ifcfg-ens32 TYPE=Ethernet NAME=ens32 DEVICE=ens32 ONBOOT=yes IPADDR=192.168.1.231 PREFIX=24 GATEWAY=192.168.1.1 DNS1=8.8.8.8 通过第1行命令查看当前网络接口的地址信息。 第2行命令显示在/etc/sysconfig/networkscripts/目录中仅包含ens32的接口配置文件ifcfgens32。通过第3行命令查看文件的内容,这是1个精简后的配置文件,仅保留必要的设置值。 接下来执行的命令如下: 4 #nmcli connection add type vlan con-name vlan11 ifname vlan11 vlan.parent ens32 vlan.id 11 Connection 'vlan11' (76131bf6-2889-4e44-9a4a-90281bd2e22a) successfully added. 5 #nmcli connection modify vlan11 ipv4.addresses '192.168.11.231/24' ipv4.gateway 192.168.11.1 ipv4.method manual 6 #nmcli connection up vlan11 Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/10) 我们先通过NetworkManager的命令行工具nmcli来创建新连接。 第4行命令创建了一个新的连接,通过type指定类型为vlan,通过conname指定新连接的名称为vlan11,通过ifname指定的接口名称也是vlan11,vlan.parent指定父接口是ens32,vlan.id指定VLAN的ID是11。 第5行命令用于设置VLAN网络接口的IPv4地址、网关和分配地址的模式。 第6行命令激活这个连接。 接下来执行的命令如下: 7 #ip -d address show vlan11 10: vlan11@ens32: mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:0c:29:b3:73:36 brd ff:ff:ff:ff:ff:ff promiscuity 0 minmtu 0 maxmtu 65535 vlan protocol 802.1Q id 11 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 inet 192.168.11.231/24 brd 192.168.11.255 scope global noprefixroute vlan11 valid_lft forever preferred_lft forever inet6 fe80::1db2:9a6c:6979:894e/64 scope link noprefixroute valid_lft forever preferred_lft forever 8 #ip -d address show ens32 2: ens32: mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 00:0c:29:b3:73:36 brd ff:ff:ff:ff:ff:ff promiscuity 0 minmtu 46 maxmtu 16110 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 inet 192.168.1.231/24 brd 192.168.1.255 scope global noprefixroute ens32 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:feb3:7336/64 scope link valid_lft forever preferred_lft forever 在第7行命令中使用了d选项,会显示连接的详细信息。自动生成的连接名称“vlan11@ens32”很直观,表示vlan11是在ens32之上实现的。除了IP地址等基本信息之外,“vlan protocol 802.1Q id 11”显示了VLAN的协议和ID号。 对比一下第8行命令的输出,会发现新创建的vlan11“借用”了ens32的MAC地址“00:0c:29:b3:73:36”。 接下来执行的命令如下: 9 #cat /etc/sysconfig/network-scripts/ifcfg-vlan11 VLAN=yes TYPE=Vlan PHYSDEV=ens32 VLAN_ID=11 REORDER_HDR=yes GVRP=no MVRP=no HWADDR= PROXY_METHOD=none BROWSER_ONLY=no BOOTPROTO=none DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=yes IPV6_AUTOCONF=yes IPV6_DEFROUTE=yes IPV6_FAILURE_FATAL=no IPV6_ADDR_GEN_MODE=stable-privacy NAME=vlan11 UUID=76131bf6-2889-4e44-9a4a-90281bd2e22a DEVICE=vlan11 ONBOOT=yes IPADDR=192.168.11.231 PREFIX=24 GATEWAY=192.168.11.1 NetworkManager创建新的VLAN接口,还会在/etc/sysconfig/networkscripts/目录中创建网络接口配置文件,第9行命令显示了这个配置文件的内容,其中最重要的属性有以下几种。 (1) VLAN=yes。 (2) TYPE=Vlan。 (3) PHYSDEV=ens32。 (4) VLAN_ID=11。 (5) DEVICE=vlan11。 (6) ONBOOT=yes。 提示: 可以通过man nmsettingsifcfgrh来获得/etc/sysconfig/networkscripts/ifcfg*设置的详细说明。 接下来执行的命令如下: 10 #lsmod | grep 8021q 8021q409600 garp 16384 18021q mrp 20480 18021q 当激活VLAN网络接口时,NetworkManager会自动将8021q模块加载到内核中,可以从第10行命令的输出中看到这个模块。 相对于nmcli,通过Cockpit来创建新的VLAN接口特别简单。 (1) 在Cockpit左边导航中单击Networking,会显示当前的所有网络接口,如图536所示。 图536Cockpit中的网络接口信息 (2) 单击Add VLAN按钮。 (3) 在VLAN Setting对话框中,选择要为其创建VLAN的物理接口ens32,将VLAN ID设置为12,将接口名称设置为vlan12,然后单击Apply按钮完成创建,如图537所示。 (4) 新VLAN创建完毕,如图538所示。单击Configure IP链接配置网络设置。 (5) 在IPv4 Setting对话框中设置IP地址及缺省网关等信息,然后单击Apply按钮保存配置,如图539所示。 图537设置新VLAN网络接口的信息 图538包括新网络接口的列表 图539为新的网络接口设置IP地址等信息 Cockpit还会在/etc/sysconfig/networkscripts/目录中创建网络接口配置文件ifcfgvlan12,命令如下: 11 #cat /etc/sysconfig/network-scripts/ifcfg-vlan12 VLAN=yes TYPE=Vlan PHYSDEV=ens32 VLAN_ID=12 REORDER_HDR=yes GVRP=no MVRP=no HWADDR= PROXY_METHOD=none BROWSER_ONLY=no BOOTPROTO=none DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=yes IPV6_AUTOCONF=yes IPV6_DEFROUTE=yes IPV6_FAILURE_FATAL=no IPV6_ADDR_GEN_MODE=stable-privacy NAME=vlan12 UUID=ae59cf5b-f088-4ba6-9f20-7eb2def383fe DEVICE=vlan12 ONBOOT=yes IPADDR=192.168.12.231 PREFIX=24 GATEWAY=192.168.12.1 PEERDNS=no PEERROUTES=no 提示: 也可以通过在/etc/sysconfig/networkscripts/目录中创建新的配置文件的方法来创建新的支持的VLAN接口。 5.10.2创建使用VLAN网络接口的网桥 有了两个支持VLAN的网络接口VLAN11和VLAN12,根据图535所示的拓扑,我们需要在宿主机上创建两个网桥virbr1和virbr2。VLAN11是virbr1的子接口,VLAN12是virbr2的子接口。 与前面创建网桥的方法类似,最简单的方法是通过Cockpit来创建。 (1) 在Cockpit左边导航中单击Networking,会显示当前的所有网络接口,如图540所示。 (2) 单击Add Bridge按钮。 图540Cockpit中的网络接口信息 (3) 在Bridge Setting对话框中,将网桥名设置为virbr1,选择子接口vlan11,然后单击Apply按钮完成创建,如图541所示。 图541设置新网桥的信息 (4) 类似地,再创建使用VLAN12的新网桥virbr2,最后的结果如图542所示。 图542包括新网桥的列表 5.10.3配置虚拟机使用VLAN 将虚拟机centos6.10桥接到virbr1,而虚拟机win2k3则需要桥接到virbr2。如果使用的是Cockpit,则可在Interface Type选择Bridge to LAN,在Source中选择适当的网桥,如图543所示。 图543使用Cockpit更新虚拟机的网络配置 也可以通过virsh的edit等子命令来修改虚拟机的配置文件,最重要的是这一行的设置,配置文件的内容如下:
在此实验环境中,我们可以使用Wireshark等协议分析工具在宿主机外面的网络中抓到来自虚拟机而且打有VLAN标记的数据包,如图544所示。 图544来自虚拟机centos6.10并带有VLAN标记的数据包 5.11通过网络过滤器提高安全性 网络过滤器(Network Filter)是libvirt的一个子系统,可以通过在其中配置过滤规则来对每个虚拟机网络接口的流量进行控制,从而提高安全性。libvirt会将这些过滤规则转换为宿主机上的防火墙规则,在虚拟机启动时自动添加与其网络接口有关的防火墙规则,而当其关闭时也会自动删除这些规则。 与虚拟机内部的防火墙不同,网络过滤规则应用于宿主机之上,所以无法从虚拟机内部规避这些过滤规则,因此从虚拟机用户的角度来看,这些规则是透明的、强制性的、无法“旁路”的,如图545所示。 图545网络过滤器原理 既可以针对特定虚拟机的某个网络接口配置网络过滤规则,也可以让多个虚拟机使用相同的过滤规则。 5.11.1网络过滤器基本原理 下面通过一个简单的实验来了解网络过滤器的基本原理。 在实验中,创建一个阻止所有ICMP流量的过滤器,然后将其应用于虚拟机centos6.10。 首先,查看虚拟机centos6.10的网络连通性,命令如下: 1 #virsh domifaddr centos6.10 NameMAC addressProtocolAddress ------------------------------------------------------------------ vnet0 52:54:00:27:5f:c9 ipv4 192.168.122.142/24 2 #ping -c 2 192.168.122.142 PING 192.168.122.142 (192.168.122.142) 56(84) Bytes of data. 64 Bytes from 192.168.122.142: icmp_seq=1 ttl=64 time=0.939 ms 64 Bytes from 192.168.122.142: icmp_seq=2 ttl=64 time=1.20 ms --- 192.168.122.142 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 3ms rtt min/avg/max/mdev = 0.939/1.071/1.204/0.136 ms 3 #iptables -L -n Chain INPUT (policy ACCEPT) targetprot opt sourcedestination ACCEPTudp -- 0.0.0.0/00.0.0.0/0udp dpt:53 ACCEPTtcp -- 0.0.0.0/00.0.0.0/0tcp dpt:53 ACCEPTudp -- 0.0.0.0/00.0.0.0/0udp dpt:67 ACCEPTtcp -- 0.0.0.0/00.0.0.0/0tcp dpt:67 Chain FORWARD (policy ACCEPT) targetprot opt sourcedestination ACCEPTall -- 0.0.0.0/0192.168.122.0/24ctstate RELATED,ESTABLISHED ACCEPTall -- 192.168.122.0/240.0.0.0/0 ACCEPTall -- 0.0.0.0/00.0.0.0/0 REJECTall -- 0.0.0.0/00.0.0.0/0reject-with icmp-port-unreachable REJECTall -- 0.0.0.0/00.0.0.0/0reject-with icmp-port-unreachable Chain OUTPUT (policy ACCEPT) targetprot opt sourcedestination ACCEPTudp -- 0.0.0.0/00.0.0.0/0udp dpt:68 通过第1行命令的输出可以看出: 虚拟机centos6.10网络接口在宿主机上的名称为vnet0,IP地址为192.168.122.142。 第2行命令的输出显示了可以在宿主机上ping通虚拟机,这说明虚拟机操作系统的防火墙没有阻止ICMP的echo请求与响应。 第3行命令的输出显示了宿主机上当前防火墙的配置,其中并没有针对vnet0或192.168.122.142的特别设置。 接下来执行的命令如下: 4 #vi new.xml 5 #virsh nwfilter-define new.xml Network filter blockicmp defined from new.xml 6 #virsh nwfilter-list UUID Name ------------------------------------------------------------------ 4b69faf1-fac2-4efe-9f30-d8bd12d0de87allow-arp bdaaee09-70ff-4bff-a0c5-f1d9313c19dfallow-dhcp 93a8a4ca-2714-4d93-8df3-1610bf0eac06allow-dhcp-server fe8d7784-7b2d-4d8e-9aa4-642ca8e282f4allow-incoming-ipv4 34ab7687-59b0-414e-9294-4884dfe7c111allow-ipv4 737777d6-1115-425a-9063-defc0e14b614blockicmp da713eaa-e490-4d61-8489-b62110795ce4clean-traffic 489f315a-4ed5-4fa3-8336-9acebc1dee83clean-traffic-gateway 843b6276-68a2-4bd8-8a31-76efe4ee7526no-arp-ip-spoofing 0c6a9780-f1e5-4181-a758-c1aa58321ff0no-arp-mac-spoofing e9dd8d7d-0fde-4cb5-9917-b192d761782bno-arp-spoofing 76da0b46-fc7c-4991-b421-f18210a4887ano-ip-multicast 724ec182-c6fe-4289-a1d3-8b0b4821a897no-ip-spoofing d8a940e2-ebdf-4ffd-9c85-75023362829fno-mac-broadcast 5036c658-6bea-4299-aff4-0bd53a9048ddno-mac-spoofing a4b3fc68-629e-45a3-b42a-73c6b1b19879no-other-l2-traffic 397ccccf-c425-4c93-98f9-35fb3870c61cno-other-rarp-traffic 746cf6aa-ff87-497d-a0f6-89352bde27b0qemu-announce-self a3b67cb4-e977-46db-a084-24e9b9e74b63qemu-announce-self-rarp 为了创建网络过滤器,需要创建一个XML格式的文件,其内容如第4行命令所示。指定新的过滤器的名称为blockicmp,并且通过来创建一个规则,action='drop'表示这是一个阻止规则,direction='in'表示只针对入站的流量,用于指定协议为icmp。 第5行命令使用virsh的nwfilterdefine子命令来创建网络过滤器。 第6行命令的输出显示了当前系统中网络过滤器的列表。除了新的网络过滤器blockicmp之外,还会看到多个预安装的过滤器。 提示: virsh有多个与网络过滤器有关的并以nwfilter开头的子命令,nwfilter是Network Filter的缩写。 接下来执行的命令如下: 7 #virsh shutdown centos6.10 8 #virsh edit centos6.10 …
… 9 #virsh start centos6.10 第7行命令用于关闭虚拟机。 第8行命令用于修改虚拟机的配置文件。通过将虚拟机的网络接口与网络过滤器blockicmp相关联。 第9行命令用于启动虚拟机。 接下来执行的命令如下: 10 #ping -c 2 192.168.122.142 PING 192.168.122.142 (192.168.122.142) 56(84) Bytes of data. --- 192.168.122.142 ping statistics --- 2 packets transmitted, 0 received, 100% packet loss, time 27ms 11 #ssh 192.168.122.142 root@192.168.122.142's password: Last login: Thu Dec 17 11:29:33 2020 from 192.168.122.1 [root@localhost ~]#exit logout Connection to 192.168.122.142 closed. 虚拟机启动之后,可在宿主机上测试其与虚拟机的连通性。从第10行命令的输出可以看出: 无法在宿主机上ping通虚拟机,这是由于网络过滤器blockicmp阻止了所有的ICMP流量。 不过,由于网络过滤器blockicmp仅仅阻止了ICMP流量,所以可以通过SSH访问这台虚拟机,如第11行命令的输出所示。 接下来执行的命令如下: 12 #iptables -L -n Chain INPUT (policy ACCEPT) targetprot opt sourcedestination libvirt-host-in all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0udp dpt:53 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0tcp dpt:53 ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0udp dpt:67 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0tcp dpt:67 Chain FORWARD (policy ACCEPT) targetprot opt sourcedestination libvirt-in all -- 0.0.0.0/0 0.0.0.0/0 libvirt-out all -- 0.0.0.0/0 0.0.0.0/0 libvirt-in-post all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 192.168.122.0/24ctstate RELATED,ESTABLISHED ACCEPT all -- 192.168.122.0/24 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 REJECT all -- 0.0.0.0/0 0.0.0.0/0reject-with icmp-port-unreachable REJECT all -- 0.0.0.0/0 0.0.0.0/0reject-with icmp-port-unreachable Chain OUTPUT (policy ACCEPT) targetprot opt source destination ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:68 Chain libvirt-in (1 references) targetprot opt sourcedestination FI-vnet0all -- 0.0.0.0/00.0.0.0/0[goto] PHYSDEV match --physdev-in vnet0 Chain libvirt-out (1 references) targetprot opt sourcedestination FO-vnet0 all -- 0.0.0.0/0 0.0.0.0/0[goto] PHYSDEV match --physdev-out vnet0 --physdev-is-bridged Chain libvirt-in-post (1 references) targetprot opt sourcedestination ACCEPTall -- 0.0.0.0/0 0.0.0.0/0PHYSDEV match --physdev-in vnet0 Chain libvirt-host-in (1 references) targetprot opt sourcedestination HI-vnet0 all -- 0.0.0.0/0 0.0.0.0/0[goto] PHYSDEV match --physdev-in vnet0 Chain FO-vnet0 (1 references) targetprot opt source destination DROP icmp -- 0.0.0.0/0 0.0.0.0/0 Chain FI-vnet0 (1 references) target prot opt source destination DROP icmp -- 0.0.0.0/0 0.0.0.0/0 Chain HI-vnet0 (1 references) target prot opt source destination DROP icmp -- 0.0.0.0/0 0.0.0.0/0 第12行命令的输出显示了当前宿主机上的防火墙的配置,增加了多个自定义的链。其中libvirthostin、libvirtin、libvirtinpost、libvirtout是当libvirt第一次加载网络过滤器时自动创建的,而FIvnet0、FOvnet0、HIvnet0是在初始化虚拟机centos6.10的网络接口时创建的(当前虚拟机centos6.10在宿主机网卡上的名称为vnet0)。 libvirt通过调用系统的iptables、ip6tables和ebtables命令完成防火墙的配置,这可以通过查看系统日志/var/log/messages得到印证。 可以将一个网络过滤器与多台虚拟机相关联,从而实现共享配置。例如: 修改虚拟机win2k3的配置文件,并且使用网络过滤器blockicmp,这样也可以阻止它的ICMP流量。 下面清除实验环境,命令如下: 13 #virsh shutdown centos6.10 14 #virsh edit centos6.10 删除 15 #virsh nwfilter-undefine blockicmp Network filter blockicmp undefined 只能删除未使用的网络过滤器。第13行命令先关闭虚拟机,然后编辑配置文件,删除。最后使用第15行命令取消网络过滤器的定义。 5.11.2网络过滤器的管理工具 目前还不能通过Cockpit、virtmanager来管理网络过滤器,所以我们主要通过virsh中nwfilter开头的子命令进行维护。 (1) nwfilterdefine: 根据XML文件定义或更新网络过滤器。 (2) nwfilterdumpxml: 输出XML格式的网络过滤器信息。 (3) nwfilteredit: 编辑网络过滤器的XML配置文件。 (4) nwfilterlist: 列出网络过滤器清单。 (5) nwfilterundefine: 取消网络过滤器的定义。 (6) nwfilterbindingcreate: 根据XML文件创建网络过滤器的绑定。 (7) nwfilterbindingdelete: 删除网络过滤器的绑定。 (8) nwfilterbindingdumpxml: 输出XML格式的网络过滤器所绑定的信息。 (9) nwfilterbindinglist: 列出网络过滤器绑定的清单。 执行的命令如下: 1 #virsh help filter Network Filter (help keyword 'filter'): nwfilter-definedefine or update a network filter from an XML file nwfilter-dumpxml network filter information in XML nwfilter-edit edit XML configuration for a network filter nwfilter-list list network filters nwfilter-undefine undefine a network filter nwfilter-binding-create create a network filter binding from an XML file nwfilter-binding-delete delete a network filter binding nwfilter-binding-dumpxml network filter information in XML nwfilter-binding-list list network filter bindings 2 #virsh nwfilter-define --help NAME nwfilter-define - define or update a network filter from an XML file SYNOPSIS nwfilter-define DESCRIPTION Define a new network filter or update an existing one. OPTIONS [--file] file containing an XML network filter description 5.11.3预安装的网络过滤器 在RHEL/CentOS 8中安装虚拟化组件时,会自动安装一些网络过滤器。与自定义的网络过滤器一样,都保存在/etc/libvirt/nwfilter/目录中。 这些过滤器的命名很直观,可以从名称猜测出其大概的用途。详细的描述如表514所示。 表514预安装的网络过滤器 名称描述 noarpspoofing 防止虚拟机欺骗ARP流量; 该过滤器仅允许ARP请求和答复消息,并强制这些数据包包含虚拟机的MAC和IP地址 allowarp 允许双向ARP流量 allowipv4 允许双向IPv4流量 allowipv6 允许双向IPv6流量 allowincomingipv4 允许传入的IPv4流量 allowincomingipv6 允许传入的IPv6流量 allowdhcp 允许虚拟机通过任何DHCP服务器获得IP地址 allowdhcpv6 与allowdhcp类似,但用于DHCPv6 allowdhcpserver 允许虚拟机从指定的DHCP服务器获得IP地址。必须对此过滤器提供DHCP服务器的IPv4地址。变量的名称必须为DHCPSERVER allowdhcpv6server 与allowdhcpserver类似,但用于DHCPv6 noipspoofing 防止虚拟机发送源IP地址与数据包中的源IP地址不同的IPv4数据包 noipv6spoofing 类似于noipspoofing,但用于IPv6 noipmulticast 防止虚拟机发送IP组播报文 noipv6multicast 类似于noipmulticast,但用于IPv6 cleantraffic 防止MAC、IP和ARP欺骗。该过滤器引用其他几个过滤器作为构建块 上述大多数网络过滤器只是构建块,需要与其他网络过滤器结合使用以提供有用的网络流量过滤。下面我们分析一下网络过滤器cleantraffic,它引用了多个其他的网络过滤器,代码如下: 1 #virsh nwfilter-dumpxml clean-traffic 1a4aadd7-62c0-47fe-a91b-6becc51fa549 第1行命令的输出是这个名为cleantraffic过滤器的XML定义。它引用了nomacspoofing、noipspoofing、allowincomingipv4、noarpspoofing、nootherl2traffic、qemuannounceself等6个子过滤器,还有两个流量过滤规则。cleantraffic过滤器的结构如图546所示。 图546cleantraffic过滤器结构 接下来执行的命令如下: 2 #virsh nwfilter-dumpxml no-mac-spoofing 5036c658-6bea-4299-aff4-0bd53a9048dd 3 #virsh nwfilter-dumpxml no-ip-spoofing 724ec182-c6fe-4289-a1d3-8b0b4821a897 第2行命令输出了网络过滤器nomacspoofing的定义。第3行命令输出了网络过滤器noipspoofing的定义。它们仅包含了流量过滤规则,而没有包含其他网络过滤器的引用。 提示: 虚拟机的使用者有可能通过修改IP和MAC地址的方式来伪造主机身份,这给网络安全防护带来了巨大的挑战。可以通过配置网络过滤器cleantraffic来检查出站的流量中的IP及MAC地址。如果不是宿主机分配给虚拟机的IP和MAC地址,则认为是伪造的地址从而可以进行阻断。 5.11.4网络过滤器语法基本格式 与libvirt管理的其他对象一样,网络过滤器也使用XML格式配置。从高层次看,格式如下: 链的UUID .... 每个网络过滤器都有一个名称和UUID,它们用作唯一标识符。网络过滤器可以具有0个或多个元素,它们用于定义网络控制。网络过滤器还可以通过filterref来引用其他的网络过滤器。 1. 链的类型 可以将过滤规则组织成链,从而形成树形结构。数据包从root链中开始进入评估流程,然后沿着分支链继续对其评估。既可以从这些分支链返回上一级链中,也可以被过滤规则直接丢弃或接收从而结束评估。 当激活网络过滤器时,libvirt会自动为每个虚拟机的网络接口创建独立的网络过滤的root链。用户创建自定义的网络过滤器时,默认的类型是root,也可以指定链的类型。 chain是一个可选属性。使用它可以更好地组织过滤器,从而可以被防火墙子系统进行更有效的处理。它必须是以mac、vlan、stp、arp、rarp、ipv4或ipv6开头的。 示例XML文件如下: #grep -h "chain" /etc/libvirt/nwfilter/*.xml 2. 过滤规则 下面是一个简单的网络过滤器示例。它有这样一个规则,如果入站IP数据包中源IP地址是192.168.122.21,则丢弃此数据包,示例代码如下: ebcdaeg1-a35f-62be-124e-208dadf2345a rule元素可包含如下属性。 (1) action: 强制性的属性。必须是drop、reject、accept、return或continue中的一种。其中drop匹配规则无须进一步分析就静默丢弃数据包; reject匹配规则将生成没有进一步分析结果的ICMP拒绝消息; accept匹配规则接收无须进一步分析的数据包; return匹配规则通过此过滤器,但将控制权返回给调用过滤器以进一步分析; continue匹配规则继续到下一个规则以进一步分析。 (2) direction: 强制性的属性。必须为in、out或者inout中的一种,分别针对入站、出站或出入站的流量。 (3) priority: 可选的属性。它控制着规则相对于其他规则的实例化顺序。值较低的规则将在值较高的规则之前实例化。有效值的范围为-1000~1000,默认值是500。 (4) statematch: 可选的属性。如果值是0或false,则会关闭基于连接状态匹配。默认值为true。 在本示例中的,表示对入站的流量进行drop操作,其优先级为500。 在rule中,需要设置与特定协议相关的匹配条件。一般模式是: <协议名称 match='yes|no' attribute1='value1' attribute2='value2'/> 目前支持的协议包括mac、arp、rarp、ip、ipv6、tcp/ip、icmp/ip、igmp/ip、udp/ip、udplite/ip、esp/ip、ah/ip、sctp/ip、tcp/ipv6、icmp/ipv6、igmp/ipv6、udp/ipv6、udplite/ipv6、esp/ipv6、ah/ipv6、sctp/ipv6。 match的默认值是yes。 在本示例中的,表示“如果源地址匹配192.168.122.21”的过滤条件。 libvirt所支持的协议及属性的表示方法,可参见https://libvirt.org/formatnwfilter.html。 3. 变量的使用 为了提高网络过滤器的灵活性,可以在其中使用变量来替换固定的值。例如可以将上述示例中的网络过滤器进行修改,示例代码如下: ebcdaeg1-a35f-62be-124e-208dadf2345a 示例中的使用了一个名称为IP的变量。引用的变量始终要以$符号为前缀。变量值的格式需要与属性的类型相匹配,例如IP参数必须包含点分十进制格式的IP地址。如果格式不正确,将会造成网络过滤器无法实例化,从而导致无法启动虚拟机或网络接口。 虚拟机XML文件引用这些过滤器的时候,可以提供变量名和值。下面的示例中,虚拟机在调用过滤器blockip时,提供了3次变量名IP和IP地址。libvirt会创建3个单独的过滤规则,每个IP地址对应一个。这样会阻断来自这3个IP地址主机的访问。 示例代码如下: … … 网络过滤器有一些保留的变量,其名称及含义如表515所示。 表515网络过滤器的保留变量 变量名称含义 MAC 接口的MAC地址 IP 接口使用的IP地址列表 IPV6 接口使用的IPV6地址列表 DHCPSERVER 受信任的DHCP服务器的IP地址列表 DHCPSERVERV6 受信任的DHCP服务器的IPv6地址列表 CTRL_IP_LEARNING IP地址检测方式的选择 最常用的保留变量是MAC和IP,在预安装的网络过滤器中使用了它们。 变量MAC表示网络接口的MAC地址。如果未显式地提供,则libvirt守护程序会自动将其设置为网络接口的MAC地址。 变量IP表示虚拟机内部的操作系统应在给定接口上使用的IP地址。如果未显式地提供,则libvirt守护程序将尝试确定接口上正在使用的IP地址。 提示: 如果网络过滤器中使用变量IP但未为其分配任何值,则将自动激活libvirt对虚拟机接口上使用的IP地址的检测。可以通过变量CTRL_IP_LEARNING来控制IP地址的学习方法,其有效值为any、dhcp或none。默认值是any,它表示libvirt可以使用任何数据包来确定虚拟机正在使用的地址。 5.11.5自定义网络过滤器示例 下面我们通过示例来学习自定义过滤器的创建。假设现在要构建一个满足以下要求的网络过滤器: (1) 防止虚拟机的MAC、IP和ARP欺骗。 (2) 仅打开虚拟机网络接口的TCP 22和80端口。 (3) 允许虚拟机向外发送ping流量,但不允许从外部ping虚拟机。 (4) 允许虚拟机执行DNS查询(UDP 53的出站)。 示例XML文件如下: 预安装的cleantraffic网络过滤器已满足防止欺骗的要求,因此可以直接引用它,然后通过前两条规则分别允许TCP端口22和80的入站,接下来的2条规则用于控制ping,随后是允许DNS查询。为了禁止所有其他流量出入站,最后添加一条丢弃所有其他流量的规则。 这个过滤器被命令为testfilter1,在虚拟机的网络接口XML中可以这样来引用它,代码如下: […]
[…] 5.12本章小结 本章讲解了虚拟网络的管理,包括隔离、NAT、桥接、路由、开放等网络类型的原理与配置,以及VLAN和网络过滤器的原理与配置。 第6章将讲解管理虚拟存储。