1、QEMU支持的网络模式
-
基于网桥(bridge)的虚拟网络
-
基于NAT的虚拟网络
-
QEMU内置的用户模式网络
-
直接分配网络设备从而直接接入物理网络(包括VT-d和SR-IOV)
在 qemu 命令行中,对客户机网络的配置通常用 -net
参数进行配置,如果没有设置任何的 -net
参数,则默认使用 -net nic-net user 参数,进而使用完全基于 QEMU 内部实现的用户模式下的网络协议栈。推荐用 -device
+ -netdev
组合的方式进行网络配置
QEMU 提供了对一系列主流和兼容性良好的网卡的模拟,通过 net nic,model=?
参数可以查询到当前的QEMU工具实现了哪些网卡的模拟
[root@kvm ~]# qemu-system-x86_64 -net nic,model=?
Supported NIC models:
e1000、e1000-82544gc、e1000-82545em、e1000e、i82550、i82551、i82557a、i82557b、i82557c、i82558a、i82558b、i82559a、i82559b、i82559c、i82559er、i82562、i82801、ne2k_pci、pcnet、rtl8139、tulip、virtio-net-pci、virtio-net-pci-non-transitional、virtio-net-pci-transitional、vmxnet3
e1000 是提供 Intel e1000 系列的网卡模拟,如果不显式指定,QEMU 默认模拟 Intel e1000 系列的虚拟网卡。而 virtio 类型是 QEMU 对半虚拟化 I/O(virtio)驱动的支持
qemu 命令行在不加任何网络相关的参数启动客户机后,在客户机中可以看到它有一个默认的 e1000 系列的网卡,由于没有进行更多的网络配置,这个模拟的网卡虽然在客户机中可见,但是它使用的是用户模式的网络,其功能非常有限
-
-net 参数的使用
-net nic[,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]
- -net nic:必需参数,表明这是一个网卡的配置
- macaddr:设置网卡的 MAC 地址,默认根据宿主机中网卡的地址来分配。若局域网中客户机太多,建议自己设置 MAC 地址,以防止 MAC 地址冲突
- model:设置模拟的网卡的类型,默认为 e1000
- name:为网卡设置一个易读的名称,该名称仅在 QEMU monitor 中可能用到
- addr:设置网卡在客户机中的 PCI 设备地址
- vectors:设置该网卡设备的 MSI-X 向量的数量,该选项仅对使用 virtio 驱动的网卡有效。设置为 vectors=0 则关闭 virtio 网卡的 MSI-X 中断方式
在宿主机中用如下命令行启动一个客户机
[root@kvm qemu]# qemu-system-x86_64 -m 1024 /img_dir/centos7.qocw2 -net nic,macaddr=52:54:00:12:34:22,model=e1000,addr=08 -net user -monitor stdio
2、网桥模式
在 QEMU/KVM 的网络使用中,网桥(bridge)模式可以让客户机和宿主机共享一个物理网络设备连接网络,客户机有自己的独立 IP 地址,可以直接连接与宿主机一模一样的网络,客户机可以访问外部网络,外部网络也可以直接访问客户机。也就是说宿主机只有一个网卡设备,使用 bridge 模式也可让多个客户机与宿主机共享网络设备
在 qemu 命令行中,配置 bridge 模式网络参数格式
-netdev tap,id=str[,fd=h][,fds=x:y:...:z][,ifname=name][,script=file][,downscript=dfile] [,br=bridge][,helper=helper]
参数说明
tap:使用 TAP 虚拟网络设备(2层设备)
id:网桥名称
fd:连接到已经打开的 TAP 接口
fds:连接到已经打开的支持多队列的 TAP 接口
ifname:设置在宿主机中添加的 TAP 虚拟设备的名称
script:设置宿主机在启动客户机时自动执行的网络配置脚本。如果不指定,其默认值为:/etc/qemu-ifup;如果不需要执行脚本,则设置为:script=no
downscript:设置宿主机在客户机关闭时自动执行的网络配置脚本。如果不设置,其默认值为:/etc/qemu-ifdown;若客户机关闭时宿主机不需要执行脚本,则设置为:downscript=no
helper:使用网络助手 helper 配置
2.1、配置网桥
该文档是基于 centos7 环境编写,如果是在 RHEL9 或者 rocky Linux9中创建网桥,请参见:RHEL9 配置网络桥接
2.1.1、安装软件包
要采用 bridge 模式的网络配置,首先需要安装 bridge-utils 软件包,它提供 brctl 工具,用于配置网桥
[root@kvm ~]# yum install bridge-utils -y
2.1.2、查看tun模块和bridge模块是否加载
[root@kvm ~]# lsmod | grep tun
tun 65536 1
[root@kvm ~]# lsmod | grep bridge
bridge 327680 0
stp 16384 1 bridge
llc 16384 2 bridge,stp
2.1.3、brctl常用命令
brctl 用于设置、维护和检查 linux 内核中的网桥配置
-
新建网桥
brctl addbr <name>
-
删除网桥
brctl delbr <name>
-
查看网桥信息
brctl delbr <name>
-
创建桥接
使接口 <ifname> 成为网桥 < brname > 的端口,并将< ifname >上收到的所有帧都将被发往网桥。此外,在 < brname > 上发送帧时,< ifname > 将被视为潜在的输出接口
brctl addif <brname> <ifname>
brname:网桥名称
ifname:网络接口
-
删除桥接
使接口 < ifname > 与网桥 < brname > 分离
brctl delif <brname> <ifname >
-
设置网桥转发延迟
brctl setfd <bridge> <time>
2.1.4、检查/dev/net/tun的权限
[root@kvm ~]# ls -la /dev/net/tun
crw-rw-rw-. 1 root root 10, 200 11月 22 15:16 /dev/net/tun
2.1.5、创建bridge
网络桥接配置可参考:官方文档
建立一个 bridge,并将其绑定到一个可以正常工作的网络接口上,同时让 bridge 成为连接本机与外部网络的接口
-
创建bridge
[root@kvm ~]# brctl addbr virbr0
-
创建virbr0配置文件
[root@kvm ~]# vim /etc/sysconfig/network-scripts/ifcfg-virbr0 DEVICE=virbr0 STP=yes TYPE=Bridge BOOTPROTO=none NAME=virbr0 ONBOOT=yes IPADDR=192.168.1.10 PREFIX=24 GATEWAY=192.168.1.1 DNS1=61.139.2.29 DNS2=114.114.114.114
-
修改需要绑定到网桥的物理接口的配置文件
[root@kvm ~]# vim /etc/sysconfig/network-scripts/ifcfg-enp5s0 TYPE=Ethernet BOOTPROTO=none DEFROUTE=no IPV4_FAILURE_FATAL=no NAME=enp5s0 UUID=88fda120-e410-451b-aabb-1234567890ab DEVICE=enp5s0 ONBOOT=yes # 将本网卡桥接到virbr0上 BRIDGE=virbr0
-
查看网桥信息
[root@kvm ~]# brctl show bridge name bridge id STP enabled interfaces virbr0 8000.000000000000 yes
-
将virbr0绑定到物理网卡
[root@kvm ~]# brctl addif virbr0 enp5s0 [root@kvm ~]# brctl show bridge name bridge id STP enabled interfaces virbr0 8000.22135c0309fc yes enp5s0
-
重启网络服务
[root@kvm ~]# systemctl restart network
-
查看网络配置
[root@kvm ~]# nmcli virbr0: 已连接 to virbr0 "virbr0" bridge, 22:13:5C:01:23:AB, 软件, mtu 1500 ip4 默认 inet4 192.168.1.10/24 route4 192.168.1.0/24 route4 0.0.0.0/0 inet6 fe80::2013:1234:5678:123/64 route6 fe80::/64 enp5s0: 已连接 to enp5s0 "Realtek RTL8111/8168/8411" ethernet (r8169), 22:13:11:11:11:11, 硬件, mtu 1500 主连接 virbr0 DNS configuration: servers: 61.139.2.29 114.114.114.114 interface: virbr0
需要注意的是,作为网桥接口的附属(slave),enp5s0 接口是没有自己的 IP 地址的,网桥寄生在它身上(与它的MAC地址相同)与外界通讯
图:创建virbr0后接口示意图
2.1.6、准备qemu-ifup和qemu-ifdown脚本
在客户机启动网络前执行的脚本是由 script 选项配置的(默认为/etc/qemu-ifup)。该脚本的内容就是将 QEMU自动创建的 TAP 设备绑定到上一步创建好的网桥上
[root@kvm ~]# vim /etc/qemu-ifup
#!/usr/bin/bash
switch=$(brctl show| sed -n 2p |awk '{print $1}')
/sbin/ifconfig $1 0.0.0.0 up
/usr/sbin/brctl addif ${switch} $1
[root@kvm ~]# vim /etc/qemu-ifdown
#!/usr/bin/bash
switch=$(brctl show| sed -n 2p |awk '{print $1}')
if [ -n "$1" ]; then
tunctl -d $1
brctl delif ${switch} $1
ip link set $1 down
exit 0
else
echo "Error: no interface specified"
exit 1
fi
[root@kvm ~]# chmod +x /etc/qemu-ifup
[root@kvm ~]# chmod +x /etc/qemu-ifdown
$1 是 QEMU 调用脚本时传入的参数,它是 QEMU 为客户机创建的 TAP 设备名称。由于 QEMU 在客户机关闭时会解除 TAP 设备的 bridge 绑定,也会自动删除已不再使用的 TAP 设备,所以 qemu-ifdown 这个脚本不是必需的,最好设置为 downscript=no
2.2、使用bridge网络
2.2.1、通过客户机配置文件使用
修改配置文件时,不建议直接修改源文件,而是使用 virsh edit 客户机名称
的方式修改,该命令等同于 vim /etc/libvirt/qemu/客户机名称.xml
,然后增加了配置验证功能
[root@kvm ~]# virsh edit centos7
<!-- 修改网络方式为bridge -->
<interface type='bridge'>
<mac address='52:54:00:32:7d:f6'/>
<!-- 使用的网络配置 -->
<source bridge='virbr0'/>
<!-- 虚拟的网卡 -->
<model type='rtl8139'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/></interface>
2.2.2、在virt-manager中使用
在 virt-manager 中修改配置后,最终还是将配置同步到 /etc/libvirt/qemu/客户机名称.xml 配置文件中
2.2.3、命令方式使用
[root@kvm ~]# qemu-system-x86_64 /img_dir/centos7.qocw2 -enable-kvm -smp 4 -m 8G -net nic -net tap,script=/etc/qemu-ifup
# 查看客户机网络
[root@localhost ~]# nmcli
ens3: 已连接 to ens3
"Intel 82540EM"
ethernet (e1000), 52:54:00:12:34:56, 硬件, mtu 1500
ip4 默认
inet4 192.168.1.111/24
route4 0.0.0.0/0
route4 192.168.1.0/24
DNS configuration:
servers: 61.139.2.69 114.114.114.114
interface: ens3
图:启动客户机后网桥拓扑示意图
3、NAT模式
NAT(网络地址转换)属于广域网接入技术的一种,它将内网地址转化为外网的合法 IP 地址,它被广泛应用于各种类型的 Internet 接入方式和各种类型的网络之中
在 KVM 中配置客户机的 NAT 网络方式,需要在宿主机中运行一个 DHCP 服务器给宿主机分配 NAT 内网的 IP 地址,可以使用 dnsmasq 工具来实现
3.1、配置NAT网络
-
安装必要的软件包
要使用 NAT 网络,需要安装 bridge-utils、iptables 和 dnsmasq 等软件包。其中 bridge-utils 包含管理 bridge 的工具 brctl,iptables 是对内核网络协议栈中 IPv4 包的过滤工具和 NAT 管理工具,dnsmasq 是一个轻量级的 DHCP 和 DNS 服务器软件
[root@kvm ~]# rpm -q bridge-utils iptables dnsmasq bridge-utils-1.5-9.el7.x86_64 iptables-1.4.21-35.el7.x86_64 dnsmasq-2.76-17.el7_9.3.x86_64
3.1.1、使用脚本方式启动
-
创建相关脚本
准备一个为客户机建立 NAT 用的 qemu-ifup 脚本及关闭网络用的 qemu-ifdown 脚本,这两个脚本中的 $1 就是在客户机中使用的网络接口在宿主机中的虚拟网络名称(如tap0、tap1等)
客户机启动时调用的 qemu-ifup-NAT 脚本的主要功能是:建立 bridge,设置 bridge 的内网 IP,并且将客户机的网络接口与其绑定,然后打开系统中网络 IP 包转发的功能,设置 iptables 的 NAT 规则,最后启动 dnsmasq 作为一个简单的 DHCP 服务器
[root@kvm ~]# vim /etc/qemu-ifup-NAT #!/bin/bash # 设置 bridge 名称 BRIDGE=natnet # 设置网络信息 NETWORK=192.168.137.0 NETMASK=255.255.255.0 GATEWAY=192.168.137.1 DHCPRANGE=192.168.137.100,192.168.137.200 # 启用PXE支持的可选参数 TFTPROOT= BOOTP= function check_bridge() { if brctl show | grep "^$BRIDGE" &> /dev/null; then return 1 else return 0 fi } function create_bridge() { brctl addbr "$BRIDGE" brctl stp "$BRIDGE" on brctl setfd "$BRIDGE" 0 ifconfig "$BRIDGE" "$GATEWAY" netmask "$NETMASK" up } function enable_ip_forward() { echo 1 > /proc/sys/net/ipv4/ip_forward } function add_filter_rules() { iptables -t nat -A POSTROUTING -s "$NETWORK"/"$NETMASK" \ ! -d "$NETWORK"/"$NETMASK" -j MASQUERADE } function start_dnsmasq() { # 禁止重复运行dnsmasq ps -ef | grep "dnsmasq" | grep -v "grep" &> /dev/null if [ $? -eq 0 ]; then echo "dnsmasq 已经在运行" return 1 fi dnsmasq \ --strict-order \ --except-interface=lo \ --interface=$BRIDGE \ --listen-address=$GATEWAY \ --bind-interfaces \ --dhcp-range=$DHCPRANGE \ --conf-file="" \ --pid-file=/var/run/qemu-dhcp-$BRIDGE.pid \ --dhcp-leasefile=/var/run/qemu-dhcp-$BRIDGE.leases \ --dhcp-no-override \ ${TFTPROOT:+"--enable-tftp"} \ ${TFTPROOT:+"--tftp-root=$TFTPROOT"} \ ${BOOTP:+"--dhcp-boot=$BOOTP"} } function setup_bridge_nat() { check_bridge "$BRIDGE" if [ $? -eq 0 ]; then create_bridge fi enable_ip_forward add_filter_rules "$BRIDGE" start_dnsmasq "$BRIDGE" } # 安装前需要检查$1参数 if [ -n "$1" ]; then setup_bridge_nat ifconfig "$1" 0.0.0.0 up brctl addif "$BRIDGE" "$1" exit 0 else echo "发现错误:没有指定接口" exit 1 fi [root@kvm ~]# chmod +x /etc/qemu-ifup-NAT
关闭客户机时调用的网络脚本 qemu-ifdown-NAT 的主要功能是要完成解除 bridge 绑定、删除 bridge 和清空 iptalbes 的 NAT 规则
[root@kvm ~]# vim /etc/qemu-ifdown-NAT [root@kvm ~]# cat /etc/qemu-ifdown-NAT #!/bin/bash BRIDGE=natnet if [ -n "$1" ]; then echo "正在断开接口 $1" ip link set $1 down brctl delif "$BRIDGE" $1 tap=`brctl show | grep natnet | awk '{print $4}'` if [[ $tap != tap* ]];then ip link set "$BRIDGE" down brctl delbr "$BRIDGE" iptables -t nat -F kill `ps aux | grep dnsmasq | grep -v grep | awk '{print $2}'` echo "断开接口 $1 成功" echo "网桥 $BRIDGE 卸载成功" echo "dnsmasq 服务停止成功" exit 0 else echo "断开接口 $1 成功" exit 0 fi else echo "删除错误:未指定接口" exit 1 fi [root@kvm ~]# chmod +x /etc/qemu-ifdown-NAT
-
使用以上两个脚本启动客户机
[root@kvm ~]# qemu-system-x86_64 -enable-kvm -smp 2 -m 4G -net nic,netdev=nic0 -netdev tap,id=nic0,script=/etc/qemu-ifup-NAT,downscript=/etc/qemu-ifdown-NAT /img_dir/centos7.qocw2
-
查看网络信息
[root@kvm ~]# brctl show bridge name bridge id STP enabled interfaces nat_net 8000.46e1f431817e yes tap0 virbr0 8000.22135c0309fc yes enp5s0
-
配置端口转发
[root@kvm ~]# iptables -t nat -A PREROUTING -p tcp -d 192.168.1.10 --dport 2222 -j DNAT --to 192.168.0.157:22
3.1.2、使用网络配置文件方式启动
-
修改(创建)NAT网络配置文件
NAT 的网络配置文件默认存放路径为 /etc/libvirt/qemu/networks/ ,默认的 NAT 配置文件名称为 default.xml,我们可以修改原有的配置文件,也可以在该目录下重新创建一个新的网络配置文件
[root@kvm ~]# virsh net-edit --network default <network> <!-- 配置文件名称 --> <name>default</name> <uuid>8c1240ab-bf0e-44ae-bf8d-87c554b49e29</uuid> <!-- 网络模式,这里使用NAT模式--> <forward mode='nat'/> <!-- 配置网络名称、是否启用STP、转发延迟 --> <bridge name='nat_net' stp='on' delay='1'/> <mac address='52:54:00:f2:80:c2'/> <!-- 配置网络信息 --> <ip address='192.168.137.1' netmask='255.255.255.0'> <dhcp> <!-- 配置DHCP地址池--> <range start='192.168.137.2' end='192.168.137.254'/> </dhcp> </ip> </network>
-
激活NAT网络
[root@kvm ~]# virsh net-start --network default
3.2、使用NAT网络
3.2.1、通过客户机配置文件使用
[root@kvm ~]# vim /etc/libvirt/qemu/centos7.xml
<!-- 修改网络方式为NAT -->
<interface type='network'>
<mac address='52:54:00:32:7d:f6'/>
<!-- 使用的网络配置 -->
<source network='default'/>
<!-- 虚拟的网卡 -->
<model type='rtl8139'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
3.2.2、在virt-manager中使用
4、用户模式
在没有任何 -net 参数时,QEMU 默认使用的是 -net nic-net user 的参数,提供了一种用户模式的网络模拟。使用用户模式的网络的客户机可以连通宿主机及外部的网络。用户模式网络完全是由 QEMU 自身实现的,不依赖于其他的工具,而且不需要 root 用户权限。QEMU 使用 Slirp 实现了一整套 CP/IP 协议栈,并且使用这个协议栈实现了一套虚拟的 NAT 网络
-
优点
由于其使用简单、独立性好、不需 root 权限、客户机网络隔离性好等优势,用户模式网络是 QEMU 的默认网络配置
-
缺点
-
由于其在 QEMU 内部实现所有网络协议栈,因此其性能较差
-
不支持部分网络功能(如ICMP),所以不能在客户机中使用 ping 命令测试外网连通性
-
不能从宿主机或外部网络直接访问客户机
-
4.1、配置用户模式
-
语法
-netdev user,id=str[,ipv4=on|off][,net=addr[/mask]][,host=addr] [,restrict=on|off][,hostname=host][,dhcpstart=addr] [,dns=addr][,dnssearch=domain][,domainname=domain][,hostfwd=rule] ...
-
常用参数解释
- id:网桥名称
- ipv4:使用ipv4网络
- net:网络地址
- host:配置主机的网络地址
- restrict:如果将此选项设置为 on,则客户机将会被隔离,客户机不能与宿主机通信,其 IP 数据包也不能通过宿主机而路由到外部网络中。默认值为 no,不会隔离客户机
- hostname:设置在内置的DHCP服务器中保存的客户机主机名
- dhcpstart:设置能够分配给客户机的第1个 IP
- dns:指定虚拟 DNS 的地址,这个地址必须与宿主机地址不相同,其默认值是网络中的第3个 IP 地址
- dnssearch:内置的 DHCP server 在分配IP给客户机的时候,会附带 DNS 域的信息
- domainname:DNS 域名
- hostfwd:端口转发,其格式为
hostfwd=[tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport
4.2、使用用户模式网络
-
在命令行中使用
[root@kvm ~]# qemu-system-x86_64 -smp 4 -m 4G -enable-kvm /img_dir/centos7.qocw2 -device e1000,netdev=usernet0 -netdev user,id=usernet0,net=192.168.0.0/24,host=192.168.0.10,hostfwd=tcp::2201-:22
-
测试外网访问客户机
[root@centos ~]# ssh root@192.168.10.100 -p 2201 root@192.168.10.100's password: Last login: Thu Nov 24 13:19:58 2022 [root@localhost ~]# nmcli ens3: 已连接 to ens3 "Intel 82540EM" ethernet (e1000), 52:54:00:12:34:56, 硬件, mtu 1500 ip4 默认 inet4 192.168.0.15/24 route4 0.0.0.0/0 route4 192.168.0.0/24 DNS configuration: servers: 192.168.0.3 interface: ens3
-
测试访问外网
[root@localhost ~]# ping www.baidu.com PING www.a.shifen.com (14.215.177.38) 56(84) bytes of data. 64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=1 ttl=255 time=229 ms 64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=2 ttl=255 time=38.1 ms 64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=3 ttl=255 time=368 ms --- www.a.shifen.com ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2003ms rtt min/avg/max/mdev = 38.108/212.028/368.314/135.382 ms