背景
为了 实现 uboot 中连接上 QEMU-host 的网络。
概念
QEMU中的网络,包含两部分的内容:
- 客户机使用的虚拟网络设备
- 和上述虚拟设备通信的网络后端,这些后端负责把虚拟设备的数据包发到宿主机的网络中
要创建一个网络后端,可以指定如下选项:
# 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
在客户机看来:
- 本身的IP地址被分配为 10.0.2.15+
- 分配IP的虚拟DHCP为 10.0.2.2
- 虚拟DNS服务器为 10.0.2.3
- 虚拟Samba服务器为 10.0.2.4,客户机可以通过此服务器访问宿主机的文件系统
用户模式网络可以很方便的访问网络资源。但是它有很多限制:
- 默认的,它运作方式类似于防火墙,且不允许任何入站流量。这个限制可以通过端口重定向解决
- 仅仅支持TCP、UDP协议,对于ICMP则不支持
- 性能比较差
为了支持入站请求,你可以使用端口重定向(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 [email protected] -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后端还具有以下优势:
- 非常好的性能
- 可以配置以支持各种网络拓扑
但是,你需要在宿主机上进行网络拓扑的配置,而且各种系统的配置不同。
使用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\n' $((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的私有桥接网络,可以让客户机、宿主机相互连通,但是客户机无法访问互联网。
要解决此问题,你可以选择以下方法之一:
- 让客户机通过宿主机暴露的HTTP/SOCKS代理上网
- 配置宿主机的路由规则,设置好源地址转换即可:
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地址不需要静态设置。
原文地址:https://www.cnblogs.com/schips/p/12350122.html