QEMU 配置网络

Posted schips

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了QEMU 配置网络相关的知识,希望对你有一定的参考价值。

背景

为了 实现 uboot 中连接上 QEMU-host 的网络。

概念

QEMU中的网络,包含两部分的内容:

  1. 客户机使用的虚拟网络设备
  2. 和上述虚拟设备通信的网络后端,这些后端负责把虚拟设备的数据包发到宿主机的网络中

要创建一个网络后端,可以指定如下选项:

# TYPE为后端类型:user、tap、bridge、socket、vde等
# id为一个标识符,将虚拟网络设备和网络后端关联在一起
# 如果客户机有多个虚拟网络设备,则每一个都需要自己的网络后端
-netdev TYPE,id=NAME,...

QEMU 两种上网方式(不同的网络后端):

user mode network :

这种方式实现虚拟机上网很简单,类似vmware里的nat,qemu启动时加入-user-net参数,虚拟机里使用dhcp方式,即可与互联网通信,但是这种方式虚拟机与主机的通信不方便。

tap/tun network :

这种方式要比user mode复杂一些,但是设置好后 虚拟机<-->互联网 虚拟机<-->主机 通信都很容易

这种方式设置上类似vmware的host-only,qemu使用tun/tap设备在主机上增加一块虚拟网络设备(tun0),然后就可以象真实网卡一样配置它。

QEME支持多种网络后端:

USER后端

如果没有指定网络选项,QEMU默认会模拟单张Intel e1000 PCI网卡,该网卡基于user后端(SLIRP)连接到宿主机:

# 不指定网络
qemu 
# 等价配置。自0.12开始废弃的配置方式 -net nic相当于-device DEVNAME;-net TYPE相当于-netdev TYPE
qemu -hda disk.img -net nic -net user
# 等价配置。-netdev指定网络后端,-device指定虚拟网络设备,后者通过netdev字段引用后端的ID
qemu -netdev user,id=network0 -device e1000,netdev=network0

在客户机看来:

  1. 本身的IP地址被分配为 10.0.2.15+
  2. 分配IP的虚拟DHCP为 10.0.2.2
  3. 虚拟DNS服务器为 10.0.2.3
  4. 虚拟Samba服务器为 10.0.2.4,客户机可以通过此服务器访问宿主机的文件系统

用户模式网络可以很方便的访问网络资源。但是它有很多限制:

  1. 默认的,它运作方式类似于防火墙,且不允许任何入站流量。这个限制可以通过端口重定向解决
  2. 仅仅支持TCP、UDP协议,对于ICMP则不支持
  3. 性能比较差

为了支持入站请求,你可以使用端口重定向(Redirecting ports)——把针对宿主机某个端口的请求转发给客户机的某个端口。映射后,客户机可以对外提供SSH、HTTP等服务:

# 把宿主机的7080端口重定向到客户机的80端口;把宿主机的7022端口重定向到客户机的22端口
qemu-system-x86_64 -redir tcp:7080::80 -redir tcp:7022::22 -hda ~/Vmware/KVM/centos7-base.img -m 512 
 
# 从宿主机SSH到客户机
ssh root@127.0.0.1 -p 7022

你可以不使用默认的10.0.2网段:

Shell
1
-netdev user,id=network0,net=192.168.5.0/24,dhcpstart=192.168.5.9 

客户机OS配置

依据客户机安装的操作系统,可能需要进行一些配置,才能正常使用网络。以CentOS 7 Minimal + 用户模式网络为例,需要修改以下配置文件:

NETWORKING=yes
# 如果不使用IPV6
NETWORKING_IPV6=no

# 如果不使用IPV6

IPV6INIT=no

# 开机启动此网卡,默认不启动

ONBOOT=yes

网关、DNS不需要设置。修改完这些配置文件后,重启客户机网络: /etc/init.d/network restart 。然后执行yum update 测试一下能否正常联网(不要使用ping测试)

TAP后端

QEMU的TAP后端利用宿主机的TAP设备,为客户机提供完整的桥接网络支持,如果外部需要使用标准端口连接到客户机, 或者多个客户机需要相互通信,可以使用该方式。 TAP后端还具有以下优势:

  1. 非常好的性能
  2. 可以配置以支持各种网络拓扑

但是,你需要在宿主机上进行网络拓扑的配置,而且各种系统的配置不同。

使用TAP后端前,你需要确认你的宿主机的内核支持TAP网络接口: /dev/net/tun 文件存在则说明支持。如果没有这样的文件,可以尝试手工创建:

sudo mkdir /dev/net
sudo mknod /dev/net/tun c 10 200
sudo /sbin/modprobe tun

如果你想创建几个客户机之间的私有网络,可以使用该方式。未参与进来的客户机、真实网络无法看到此网络。基于TAP的私有桥接网络

如果你不是root,则你需要 /dev/kvm 的读写权限。

首先,添加一个以太网桥设备:

sudo ip link add br0 type bridge
# 也可以使用:sudo brctl addbr br0添加网桥
# 要删除网桥,执行: ip link delete br0
# 注意:网桥会在重启后消失
 
# 启用此网桥
sudo ip link set br0 up
 
# 为网桥分配IP地址
sudo ip addr add 10.0.0.1 dev br0
 
# 在宿主机添加一条直接路由,便于它能和客户机通信
sudo ip route add 10.0.0.0/8 dev br0

创建一个创建TAP设备并桥接到网桥的脚本:

#!/bin/sh
 
switch=br0
 
if [ -n "$1" ];then
        # tunctl -u `whoami` -t $1
        # 添加一个tap设备,在我的机器上不需要,原因见下面
        # ip tuntap add $1 mode tap user `whoami`
        # 不知道从什么时候开始,QEMU会在执行此脚本之前就创建好tap设备,因此会报下面的错误
        # ioctl(TUNSETIFF): Device or resource busy
        # 启动tap设备
        ip link set $1 up
        # brctl addif $switch $1
        # 将网桥和tap设备进行桥接
        ip link set $1 master $switch
        exit 0
else
        echo "Error: no interface specified"
        exit 1
fi

创建一个生成随机MAC地址的脚本:

    #!/bin/bash
    # generate a random mac address for the qemu nic
    printf 'DE:AD:BE:EF:%02X:%02X
' $((RANDOM%256)) $((RANDOM%256))

启动客户机的脚本:

#!/bin/bash
# $1 base name of virtual disk
# $2 memory size
# $3 tap device id
 
mac=`/usr/bin/qemu-genmac`
src=/usr/bin/qemu-ifup
sudo qemu-system-x86_64 -enable-kvm -device e1000,netdev=$3,mac=$mac -netdev tap,id=$3,script=$src,downscript=no                         -hda ~/Vmware/KVM/$1.img -m $2

为上面的脚本文件添加可执行权限:

sudo chmod +x /usr/bin/qemu-ifup-br0
sudo chmod +x /usr/bin/qemu-genmac
sudo chmod +x /usr/bin/qemu-start-br0

执行下面的命令,启动一台客户机(或者更多虚拟机,但是命令中的tap0要更换为不同的名字):

/usr/bin/qemu-start centos7-base 512 tap0

修改客户机的IP地址,使用10.0.0.0/8网段:

TYPE=Ethernet
BOOTPROTO=static
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=no
NAME=ens3
UUID=d9f47102-b177-4a27-ae98-86f6939d6680
DEVICE=ens3
ONBOOT=yes
IPADDR=10.0.0.10
PREFIX=8
GATEWAY=10.0.0.1

现在可以互相ping客户机和宿主机,应该可以正常连通了。

私有桥接下访问互联网

上一节介绍的这种基于TAP的私有桥接网络,可以让客户机、宿主机相互连通,但是客户机无法访问互联网。

要解决此问题,你可以选择以下方法之一:

  1. 让客户机通过宿主机暴露的HTTP/SOCKS代理上网
  2. 配置宿主机的路由规则,设置好源地址转换即可:
sudo sysctl -w net.ipv4.ip_forward=1 
# 对客户机网段进行源地址转换
sudo iptables -t nat -A POSTROUTING  -s 10.0.0.0/255.0.0.0 ! -d 10.0.0.0/255.0.0.0 -j MASQUERADE 

公共桥接网络

此方式和私有桥接网络类似,主要区别是,除了TAP设备桥接到网桥之外,以太网卡(例如eth0)也桥接到网桥(例如br1)。

你可以通过发行版的配置文件来配置网桥:

# 注意网络管理器组件的影响
# 去掉 auto eth0,改为:
auto br1
 
# 配置br1
iface br1 inet dhcp
    bridge_ports    eth0
    bridge_stp      off
    bridge_maxwait  0
    bridge_fd       0
    # 这里附加上原来属于eth0的配置

或者基于脚本来配置:

sudo ip link add br1 type bridge
sudo ip link set br1 up
sudo ip link set eth0 master br1 
 
# DHCP
sudo killall dhclient && sudo ip addr flush dev eth0
sudo dhclient br1

无论用哪种方式,都应该注意到eth0的IP地址需要转移给br1,这样才能确保网络正常运作——br1必须在链路层接收到相关ARP请求,并决定是否需要转发给客户机,eth0没有这种转发能力。

如果eth0所在网络是基于DHCP的,那么客户机配置为DHCP后,会自动获取公共IP地址。否则,需要手工设置客户机的IP地址。

基于TAP的桥接的简化配置

现在QEMU支持自动桥接TAP设备到宿主机的一个网桥,因此你不再需要编写脚本,修改网络后端为bridge即可:

-netdev bridge,id=tap0,br=br0

注意,使用上述选项时,QEMU需要读取配置文件/etc/qemu/bridge.conf,你只需在此文件中添加一行代码:

allow br0

你可以编写如下脚本自动创建网桥、配置iptables规则。示例:

# Create private bridge link
 for QEMU
 
/sbin/ip
link
add
br0
type
bridge
 
/sbin/ip
link
set
br0
up
 
/sbin/ip
addr
add
10.0.0.1
dev
br0
 
/sbin/ip
route
add
10.0.0.0/8
dev
br0
 
# NAT for 10.0.0.0/8
 
/sbin/iptables
-t
nat
-A
POSTROUTING  -s
10.0.0.0/255.0.0.0
!
-d
10.0.0.0/255.0.0.0  -j
MASQUERADE
 
 
 
 
 
# Create public bridge link
 for QEMU
 
/sbin/ip
link
add
br1
type
bridge
 
/sbin/ip
link
set
br1
up
 
/sbin/ip
link
set
eth0
master
br1
 
/usr/bin/killall
dhclient
&&
/sbin/ip
addr
flush
dev
eth0
 
/sbin/dhclient
br1

macvtap直连

关于MacVTap的相关知识,参考Linux知识集锦。建议和libvirt一起使用macvtap。

基于libvirt的桥接

在使用libvirt时,客户机(Domain)的网络接口配置可以简化为:

<interface type='bridge'>
    <mac address='DE:AD:BE:EF:F1:00'/>
    <source bridge='br0'/>
    <target dev='tap0'/>
    <model type='virtio'/>
</interface>

基于libvirt VLAN的桥接

可以使用libvrit的虚拟局域网,这样宿主机上不会为客户机创建专门的tap设备,那些手工编写的脚本也全都不需要了。虚拟网络配置示例:

<network>
  <name>default</name>
  <uuid>9bae4de8-ca58-48c5-ba58-109aebf8b954</uuid>
  <forward mode='nat'>
  </forward>
  <bridge name='virbr0' stp='on' delay='0'/>
  <ip address='10.0.0.1' netmask='255.0.0.0'>
    <dhcp>
      <range start='10.0.0.100' end='10.0.0.200'/>
    </dhcp>
  </ip>
</network>

客户机(Domain)的网络接口配置示例:

<interface type='network'>
    <mac address='DE:AD:BE:EF:F1:00'/>
    <source network='default'/>
    <model type='virtio'/>
</interface>

另外,libvirt的虚拟网络提供了DHCP功能,因此客户机的IP地址不需要静态设置。

以上是关于QEMU 配置网络的主要内容,如果未能解决你的问题,请参考以下文章

UEFI实战Windows版本QEMU网络配置

QEMU命令配置虚拟机网络的用户模式

路由器逆向分析------MIPS系统网络的配置(QEMU)

关于路由器漏洞利用,qemu环境搭建,网络配置的总结

操作记录:在ubuntu16.04.1配置qemu-img,qemu-nbd

KVM中的网络简介(qemu-kvm)