强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

05 - 网络配置

05 - 网络配置

掌握 QEMU 的各种网络模式:用户模式、桥接、TAP、NAT、多网卡配置与 PCI 网络直通。


5.1 QEMU 网络模式概览

模式性能外部访问配置难度适用场景
用户模式 (SLIRP)❌ 虚拟机不可被外部访问最简单快速测试
TAP/桥接中等生产环境
Socket中等局域网内中等虚拟机间通信
多播中等局域网内中等虚拟机组通信
PCI 直通最高复杂高性能网络

5.2 用户模式网络(User Mode / SLIRP)

用户模式是 QEMU 默认的网络模式,无需任何特权配置:

# 基本用户模式网络
qemu-system-x86_64 \
  -enable-kvm -cpu host -m 2G \
  -drive file=vm.qcow2,format=qcow2 \
  -netdev user,id=net0 \
  -device virtio-net-pci,netdev=net0

# 等价的旧语法
qemu-system-x86_64 ... -net nic -net user

用户模式网络特性

用户模式网络架构:
  ┌─────────────────┐
  │    Guest VM      │
  │  10.0.2.15       │
  │  网关: 10.0.2.2  │
  │  DNS: 10.0.2.3   │
  └────────┬────────┘
           │ SLIRP (用户态网络栈)
  ┌────────┴────────┐
  │   QEMU 进程      │
  └────────┬────────┘
           │ NAT
  ┌────────┴────────┐
  │   宿主机网络      │
  └─────────────────┘
特性
虚拟机 IP10.0.2.15(固定)
网关10.0.2.2
DNS10.0.2.3
DHCP内置(自动分配 10.0.2.15)
外部访问✅ 可以访问外部网络
外部访问虚拟机❌ 需要端口转发

端口转发

# SSH 端口转发
qemu-system-x86_64 \
  -netdev user,id=net0,hostfwd=tcp::2222-:22 \
  -device virtio-net-pci,netdev=net0

# 连接: ssh -p 2222 user@localhost
# 多端口转发
qemu-system-x86_64 \
  -netdev user,id=net0,\
    hostfwd=tcp::2222-:22,\
    hostfwd=tcp::8080-:80,\
    hostfwd=tcp::8443-:443,\
    hostfwd=udp::5353-:53 \
  -device virtio-net-pci,netdev=net0

# 反向端口转发(虚拟机访问宿主机端口)
qemu-system-x86_64 \
  -netdev user,id=net0,\
    hostfwd=tcp::2222-:22,\
    guestfwd=tcp:10.0.2.100:80-tcp:192.168.1.50:8080 \
  -device virtio-net-pci,netdev=net0

自定义 DHCP 与 TFTP

# 自定义 DHCP 范围
qemu-system-x86_64 \
  -netdev user,id=net0,\
    net=192.168.100.0/24,\
    dhcpstart=192.168.100.100,\
    host=192.168.100.1 \
  -device virtio-net-pci,netdev=net0

# 启用内置 TFTP 服务器(PXE 启动用)
qemu-system-x86_64 \
  -netdev user,id=net0,tftp=/var/lib/tftpboot,bootfile=/pxelinux.0 \
  -device virtio-net-pci,netdev=net0

# 指定 DNS 和域名
qemu-system-x86_64 \
  -netdev user,id=net0,dnssearch=example.com,dns=8.8.8.8 \
  -device virtio-net-pci,netdev=net0

用户模式网络限制

性能瓶颈: 用户模式网络运行在用户态,所有网络包需要经过内核→用户态→内核的转换,吞吐量通常只有 200-500 Mbps。

不支持多播: 用户模式不支持多播和广播,某些依赖这些特性的协议无法正常工作。

不支持 ICMP: 无法在虚拟机内 ping 外部主机(可以使用 TCP/UDP)。


5.3 TAP 网络

TAP 设备是最灵活和高性能的网络方案,它创建一个虚拟的以太网设备,可以与桥接配合使用:

# 创建 TAP 设备
sudo ip tuntap add dev tap0 mode tap user $(whoami)
sudo ip link set tap0 up

# 将 TAP 设备加入桥接
sudo ip link set tap0 master br0

使用 TAP 设备启动 QEMU

# 方法 1:手动管理 TAP 设备
qemu-system-x86_64 \
  -enable-kvm -cpu host -m 2G \
  -drive file=vm.qcow2,format=qcow2 \
  -netdev tap,id=net0,ifname=tap0,script=no,downscript=no \
  -device virtio-net-pci,netdev=net0,mac=52:54:00:12:34:56

使用自动脚本管理 TAP

# /etc/qemu-ifup
#!/bin/bash
switch=br0
if [ -n "$1" ]; then
    # 创建或使用已有的 TAP 设备
    ip link set $1 up
    ip link set $1 master ${switch}
    echo "TAP 设备 $1 已加入桥接 ${switch}"
fi
# /etc/qemu-ifdown
#!/bin/bash
switch=br0
if [ -n "$1" ]; then
    ip link set $1 nomaster
    ip link set $1 down
    echo "TAP 设备 $1 已从桥接 ${switch} 移除"
fi
# 使用自动脚本(默认脚本路径)
qemu-system-x86_64 \
  -enable-kvm -cpu host -m 2G \
  -drive file=vm.qcow2,format=qcow2 \
  -netdev tap,id=net0,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown \
  -device virtio-net-pci,netdev=net0

多 TAP 设备

# 启动多个虚拟机,每个使用不同的 TAP 设备
# VM1: tap0
qemu-system-x86_64 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no \
  -device virtio-net-pci,netdev=net0 &

# VM2: tap1
qemu-system-x86_64 -netdev tap,id=net0,ifname=tap1,script=no,downscript=no \
  -device virtio-net-pci,netdev=net0 &

5.4 桥接网络

桥接网络让虚拟机像物理机一样直接接入局域网:

桥接网络架构:
  ┌───────────────┐    ┌───────────────┐
  │    VM1         │    │    VM2         │
  │  192.168.1.101 │    │  192.168.1.102 │
  │   (tap0)       │    │   (tap1)       │
  └───────┬───────┘    └───────┬───────┘
          │                    │
  ┌───────┴────────────────────┴───────┐
  │           桥接 br0                  │
  │        192.168.1.100               │
  └───────────────┬───────────────────┘
  ┌───────────────┴───────────────────┐
  │         物理网卡 eth0              │
  └───────────────┬───────────────────┘
          ┌───────┴───────┐
          │   交换机/路由器 │
          │  192.168.1.1   │
          └───────────────┘

完整桥接配置脚本

#!/bin/bash
# setup-bridge.sh - 配置 QEMU 桥接网络

PHYS_IF="enp0s3"      # 物理网卡
BRIDGE_IF="br0"        # 桥接接口
BRIDGE_IP="192.168.1.100/24"
BRIDGE_GW="192.168.1.1"

# 安装依赖
# sudo apt install bridge-utils

# 创建桥接
sudo ip link add name ${BRIDGE_IF} type bridge
sudo ip link set ${BRIDGE_IF} up

# 将物理网卡的 IP 移到桥接
sudo ip addr flush dev ${PHYS_IF}
sudo ip addr add ${BRIDGE_IP} dev ${BRIDGE_IF}
sudo ip route add default via ${BRIDGE_GW} dev ${BRIDGE_IF}

# 将物理网卡加入桥接
sudo ip link set ${PHYS_IF} master ${BRIDGE_IF}

echo "桥接配置完成"
ip addr show ${BRIDGE_IF}

使用 systemd-networkd 配置桥接

# /etc/systemd/network/10-br0.netdev
[NetDev]
Name=br0
Kind=bridge
# /etc/systemd/network/20-br0-enp0s3.network
[Match]
Name=enp0s3

[Network]
Bridge=br0
# /etc/systemd/network/30-br0.network
[Match]
Name=br0

[Network]
DHCP=yes
# 或者静态 IP
# Address=192.168.1.100/24
# Gateway=192.168.1.1
# DNS=8.8.8.8
sudo systemctl restart systemd-networkd

5.5 NAT 网络

NAT 网络让虚拟机通过 NAT 访问外部网络,但外部无法主动访问虚拟机:

# 创建 NAT 网络桥接
sudo ip link add virbr0 type bridge
sudo ip addr add 192.168.122.1/24 dev virbr0
sudo ip link set virbr0 up

# 启用 IP 转发
sudo sysctl -w net.ipv4.ip_forward=1

# 配置 iptables NAT 规则
sudo iptables -t nat -A POSTROUTING -s 192.168.122.0/24 -o enp0s3 -j MASQUERADE
sudo iptables -A FORWARD -i virbr0 -o enp0s3 -j ACCEPT
sudo iptables -A FORWARD -i enp0s3 -o virbr0 -m state --state RELATED,ESTABLISHED -j ACCEPT

# 启动虚拟机,使用 NAT 桥接
qemu-system-x86_64 \
  -enable-kvm -cpu host -m 2G \
  -drive file=vm.qcow2,format=qcow2 \
  -netdev tap,id=net0,ifname=tap0,script=no,downscript=no \
  -device virtio-net-pci,netdev=net0

# 配置 TAP 设备
sudo ip link set tap0 master virbr0
sudo ip link set tap0 up

# 在虚拟机中配置 IP 192.168.122.x,网关 192.168.122.1

使用 dnsmasq 提供 DHCP/DNS

# 安装 dnsmasq
sudo apt install dnsmasq

# 配置 dnsmasq
cat > /etc/dnsmasq.d/qemu-nat.conf << 'EOF'
interface=virbr0
bind-interfaces
dhcp-range=192.168.122.100,192.168.122.200,255.255.255.0,12h
dhcp-option=option:router,192.168.122.1
dhcp-option=option:dns-server,8.8.8.8,8.8.4.4
domain=qemu.local
EOF

sudo systemctl restart dnsmasq

5.6 多网卡配置

# 虚拟机配置多个网卡
qemu-system-x86_64 \
  -enable-kvm -cpu host -m 4G \
  -drive file=vm.qcow2,format=qcow2 \
  -netdev user,id=mgmt,hostfwd=tcp::2222-:22 \
  -device virtio-net-pci,netdev=mgmt,mac=52:54:00:00:00:01 \
  -netdev tap,id=data0,ifname=tap0,script=no,downscript=no \
  -device virtio-net-pci,netdev=data0,mac=52:54:00:00:00:02 \
  -netdev tap,id=data1,ifname=tap1,script=no,downscript=no \
  -device virtio-net-pci,netdev=data1,mac=52:54:00:00:00:03

网络用途划分示例

多网卡典型架构:
  ┌───────────────────────────────────────────┐
  │               Virtual Machine             │
  │                                           │
  │  eth0 (管理网)     eth1 (业务网)          │
  │  10.0.0.10         192.168.100.10         │
  │  NAT/用户模式      TAP/桥接               │
  ├───────────────────────────────────────────┤
  │  用于 SSH 管理     用于数据传输            │
  └───────────────────────────────────────────┘
网卡模式用途安全
eth0用户模式管理(SSH)仅本机访问
eth1TAP/桥接业务数据局域网访问
eth2TAP/桥接存储网络专用网络

5.7 网络性能优化

vhost-net 加速

vhost-net 将网络数据处理从用户态移到内核态,大幅提升性能:

# 加载 vhost_net 模块
sudo modprobe vhost_net

# 使用 vhost-net 启动
qemu-system-x86_64 \
  -enable-kvm -cpu host -m 2G \
  -drive file=vm.qcow2,format=qcow2 \
  -netdev tap,id=net0,vhost=on,script=no,downscript=no \
  -device virtio-net-pci,netdev=net0

# 或使用 vhost-user(需 DPDK/OVS 支持)
qemu-system-x86_64 \
  -netdev type=vhost-user,id=net0,chardev=char0,vhostforce=on \
  -chardev socket,id=char0,path=/var/run/openvswitch/vhost-user0 \
  -device virtio-net-pci,netdev=net0

网络多队列

# 使用多队列提高多核 CPU 的网络吞吐
qemu-system-x86_64 \
  -smp 4 \
  -netdev tap,id=net0,vhost=on,queues=4,script=no,downscript=no \
  -device virtio-net-pci,netdev=net0,mq=on,vectors=8

# 在客户机中启用多队列
# 对于 eth0
ethtool -L eth0 combined 4

网络性能对比

方案吞吐量 (Gbps)CPU 开销延迟
用户模式0.2-0.5
TAP + virtio5-10中等
TAP + vhost-net10-20最低
PCI 直通20+ (线速)最低最低

5.8 网络故障排查

检查网络连通性

# 在宿主机检查 TAP 设备
ip link show tap0

# 检查桥接状态
bridge link show
brctl show  # 旧命令

# 在虚拟机内检查
ip addr show
ip route show
ping -c 3 192.168.1.1   # ping 网关
ping -c 3 8.8.8.8       # ping 外部
nslookup google.com     # DNS 解析测试

常见问题

问题原因解决方案
虚拟机无法上网网关或 DNS 配置错误检查 IP/网关/DNS 配置
无法 SSH 到虚拟机端口转发未配置添加 hostfwd 参数
TAP 设备无法通信桥接未正确配置检查 ip link set master
性能很差未使用 vhost-net添加 vhost=on 参数
MAC 地址冲突多个虚拟机使用相同 MAC为每个网卡指定唯一 MAC

tcpdump 抓包

# 在宿主机抓取 TAP 设备的包
sudo tcpdump -i tap0 -nn -vv

# 抓取桥接上的包
sudo tcpdump -i br0 -nn -vv

# 保存到文件用 Wireshark 分析
sudo tcpdump -i tap0 -w /tmp/qemu-traffic.pcap

5.9 PCI 网络直通

将物理网卡直通给虚拟机,获得接近原生的网络性能:

# 查找网卡的 PCI 地址
lspci | grep -i ethernet

# 将网卡绑定到 vfio-pci 驱动
# 假设网卡 PCI 地址为 03:00.0
echo "vfio-pci" | sudo tee /sys/bus/pci/devices/0000:03:00.0/driver_override
echo "0000:03:00.0" | sudo tee /sys/bus/pci/devices/0000:03:00.0/driver/unbind
echo "0000:03:00.0" | sudo tee /sys/bus/pci/drivers/vfio-pci/bind

# 启动虚拟机并直通网卡
qemu-system-x86_64 \
  -enable-kvm -cpu host -m 4G \
  -drive file=vm.qcow2,format=qcow2 \
  -device vfio-pci,host=03:00.0

详细的设备直通配置请参见 第 10 章 - 设备直通


要点回顾

要点核心内容
用户模式最简单,无需特权,性能低,适合测试
TAP/桥接高性能,需要 root 权限,适合生产
NAT通过 iptables 实现,虚拟机不暴露给外部
多网卡管理网 + 业务网分离,增强安全性
vhost-net将网络处理移入内核,性能提升 2-3 倍

注意事项

MAC 地址管理: 如果不指定 MAC 地址,QEMU 会随机生成。在桥接网络中,建议固定 MAC 地址以获得稳定的 DHCP 分配。

防火墙规则: 桥接网络可能被 iptables/nftables 规则阻挡。检查 iptables -L -n 确保桥接流量被正确放行。

MTU 配置: 使用巨帧(Jumbo Frame)时,宿主机网卡、桥接接口、TAP 设备和虚拟机网卡的 MTU 必须一致。


扩展阅读


下一步

06 - 快照管理:深入学习内部快照、外部快照、实时快照与自动化管理。