qemu虚拟机与外部网络的通信

一、基本概念

为了使虚拟机能够与外界通信,Qemu需要为虚拟机提供网络设备。Qemu支持的常用网卡包括NE2000、rtl8139、pcnet32等。命令行上用-net nic为虚拟机创建虚拟机网卡。例如,qemu的命令行选项
                            -net nic,model=pcnet
表示为虚拟机添加一块pcnet型的以太网卡。如果省略model参数则qemu会默认选择一种网卡类型,目前采用的是Intel 82540EM(手册里说明的是e1000),可以在虚拟机启动后执行lspci命令查看。有了虚拟网络设备,下面的问题是如何用这些设备来联网。

首先,虚拟机的网络设备连接在qemu虚拟的VLAN中。每个qemu的运行实例是宿主机中的一个进程,而每个这样的进程中可以虚拟一些VLAN,虚拟机网络设备接入这些VLAN中。当某个VLAN上连接的网络设备发送数据帧,与它在同一个VLAN中的其它网路设备都能接收到数据帧。上面的例子中对虚拟机的pcnet网卡没有指定其连接的VLAN号,那么qemu默认会将该网卡连入vlan0。下面这个例子更具一般性:
      -net nic,model=pcnet -net nic,model=rtl8139,vlan=1, -net nic,model=ne2k_pci,vlan=1
该命令为虚拟机创建了三块网卡,其中第一块网卡类型是pcnet,连入vlan0;第二块网卡类型是 rtl8139,第三块网卡类型是ne2k_pci,这两块都连入vlan1,所以第二块网卡与第三块网卡可以互相通信,但它们与第一块网卡不能直接通信。

接下来,各个VLAN再通过qemu提供的4种通信方式与外界联网。

  1. User mode stack:这种方式在qemu进程中实现一个协议栈,负责在虚拟机VLAN和外部网络之间转发数据。可以将该协议栈视为虚拟机与外部网络之间的一个NAT服务器,外部网络不能主动与虚拟机通信。虚拟机VLAN中的各个网络接口只能置于10.0.2.0子网中,所以这种方式只能与外部网络进行有限的通信。此外,可以用-redir选项为宿主机和虚拟机的两个TCP或UDP端口建立映射,实现宿主机和虚拟机在特殊要求下的通信(例如X-server或ssh)。User mode stack通信方式由-net user选项启用,如果不显式指定通信方式,则这种方式是qemu默认的通信方式。
  2. socket:这种方式又分为TCP和UDP两种类型。
    (1)TCP:
    为一个VLAN创建一个套接字,让该套接字在指定的TCP端口上监听,而其他VLAN连接到该套接字上,从而将多个VLAN连接起来。缺点在于如果监听套接字所在qemu进程崩溃,整个连接就无法工作。监听套接字所在VLAN通过-net socket,listen选项启用,其他VLAN通过-net socket,connect选项启用。
    (2)UDP:所有VLAN连接到一个多播套接字上,从而使多个VLAN通过一个总线通信。所有VLAN都通过-net socket,mcast选项启用。
  3. TAP:这种方式首先需要在宿主机中创建并配置一个TAP设备,qemu进程将该TAP设备连接到虚拟机VLAN中。其次,为了实现虚拟机与外部网络的通信,在宿主机中通常还要创建并配置一个网桥,并将宿主机的网络接口(通常是eth0)作为该网桥的一个接口。最后,只要将TAP设备作为网桥的另一个接口,虚拟机VLAN通过TAP设备就可以与外部网络完全通信了。这是因为,宿主机的eth0接口作为网桥的接口,与外部网络连接;TAP设备作为网桥的另一个接口,与虚拟机VLAN连接,这样两个网络就连通了。此时,网桥在这两个网络之间转发数据帧。
    这里有两个问题需要注意:
    (1)网桥的转发工作需要得到内核的支持,所以在编译宿主机内核时需要选择与桥接相关的配置选项。
    (2)当宿主机eth0接口作为网桥接口时,不能为其配置IP地址,而要位将IP地址配置给网桥。
    TAP方式由-net tap选项启用。
  4. VDE:这种方式首先要启动一个VDE进程,该进程打开一个TAP设备,然后各个虚拟机VLAN与VDE进程连接,这样各个VLAN就可以通过TAP设备连接起来。VDE进程通过执行vde_switch命令启动,各个VLAN所在qemu进程通过执行veqe命令启动,这些VLAN就可以与VDE进程连接了。

以上四种通信方式中,socket方式和VDE方式用于虚拟机VLAN之间的连接,而user mode stack方式与外部网路的通信比较有限,所以下面主要讨论TAP方式的配置。

在没有做配置之前,首先需要对TAP设备有所认识。TUN/TAP是内核支持的网络虚拟设备,这种网络设备完全由的软件实现。与网络硬件设备不同,TUN/TAP负责在内核协议栈与用户进程之间传送协议数据单元。TUN与TAP的区别在于,TUN工作在网络层,而TAP则工作在数据链路层。具体在运行TCP/IP的以太网中,TUN与应用程序交换IP包,而TAP与应用程序交换以太帧。所以TUN通常涉及路由,而TAP则常用于网络桥接。TUN/TAP的典型应用包括:OpenVPN、OpenSSH 以及虚拟机网络。


二、在Ubuntu 10.04中配置qemu虚拟网络

  1. 内核支持需要对TUN/TAP设备和虚拟网桥提供支持:
    (1)Device Drivers
                --> Network device support
                            --> Universal TUN/TAP device driver support
    (2)Networking support
                --> Networking options
                            --> 802.1d Ethernet Bridging
  2. 安装两个配置网络所需软件包:
    apt-get install bridge-utils        # 虚拟网桥工具
    apt-get install uml-utilities       # UML(User-mode linux)工具
  3. 配置虚拟网桥的操作(假设系统启动后eth0已经启动,并且从DHCP获得IP地址)。
    ifconfig eth0 down                  # 先关闭eth0接口
    brctl addbr br0                     # 增加一个虚拟网桥br0
    brctl addif br0 eth0                # 在br0中添加一个接口eth0
    brctl stp br0 off                   # 只有一个网桥,所以关闭生成树协议
    brctl setfd br0 1                   # 设置br0的转发延迟
    brctl sethello br0 1                # 设置br0的hello时间
    ifconfig br0 0.0.0.0 promisc up     # 打开br0接口
    ifconfig eth0 0.0.0.0 promisc up    # 打开eth0接口
    dhclient br0                        # 从dhcp服务器获得br0的IP地址
    brctl show br0                      # 查看虚拟网桥列表
    brctl showstp br0                   # 查看br0的各接口信息
    在没有dhcp服务器的网络中也可以用ifconfig命令为br0接口配置一个静态IP地址:
    ifconfig br0 192.168.0.22 netmask 255.255.255.0
    route add -net 0.0.0.0 netmask 0.0.0.0 gw 192.168.0.254
  4. 配置TAP设备的操作:
    tunctl -t tap0 -u root              # 创建一个tap0接口,只允许root用户访问
    brctl addif br0 tap0                # 在虚拟网桥中增加一个tap0接口
    ifconfig tap0 0.0.0.0 promisc up    # 打开tap0接口
    brctl showstp br0                   # 显示br0的各个接口
  5. 假设内核的顶层目录在/usr/src/linux,且内核已经编译完毕。启动qemu的操作:
    cd /usr/src/linux
    qemu -kernel arch/x86/boot/bzImage -net nic -net tap,ifname=tap0,script=no,downscript=no 
    如果省略script和downscript参数,qemu在启动时会以第一个不存在的tap接口名(通常是tap0)为参数去调用/etc/qemu-ifup脚本,而在退出时调用/etc/qemu-ifdown脚本。这两个脚本需要用户自行编写,其主要作用通常是:在启动时创建和打开指定的TAP接口,并将该接口添加到虚拟网桥中;退出时将该接口从虚拟网桥中移除,然后关闭该接口。由于配置TAP设备的操作前面已经做过了,所以启动qemu时显式地告诉qemu不要执行这两个脚本。这里需要严重注意:-net tap的各参数之间不要有空格!为了这个问题花了半个小时 :-(。
  6. 为了在系统启动时能够自动配置虚拟网桥和TAP设备,编写/etc/network/interfaces文件的内容如下:
    auto lo
    iface lo inet loopback

    # The eth0 network interface(s)
    # auto eth0
    # iface eth0 inet dhcp

    # The bridge network interface(s)
    auto br0
    iface br0 inet dhcp
    # iface br0 inet static
    # address 192.168.0.1
    # netmask 255.255.255.0
    # gateway 192.168.0.254
    bridge_ports eth0
    bridge_fd 9
    bridge_hello 2
    bridge_maxage 12
    bridge_stp off

    # The tap0 network interface(s)
    auto tap0
    iface tap0 inet manual
    # iface tap0 inet static
    # address 192.168.0.2
    # netmask 255.255.255.0
    # gateway 192.168.0.254
    pre-up tunctl -t tap0 -u root
    pre-up ifconfig tap0 0.0.0.0 promisc up
    post-up brctl addif br0 tap0

    注意:此时应该将配置文件中的eth0关闭(相应的文本行注释掉)。


三、在gentoo中配置qemu虚拟网络

  1. 内核支持需要对TUN/TAP设备和虚拟网桥提供支持:
    与ubuntu的配置相同
  2. 安装两个配置网络所需软件包:
    emerge 
    bridge-utils            # 虚拟网桥工具
    emerge usermod-utilities       # UML(User-mode linux)工具
  3. 配置虚拟网桥的操作(假设系统启动后eth0已经启动,并且从DHCP获得IP地址)。
    与ubuntu的配置基本相同,指示gentoo默认采用的dhcp客户端是dhcpcd,所以相应的命令行应改为:
    dhcpcd br0
  4. 配置TAP设备的操作:
    与ubuntu的配置相同。
  5. 启动qemu。
    与ubuntu的配置相同。
  6. 为了在系统启动时能够自动配置虚拟网桥和TAP设备,编写/etc/conf.d/net文件的内容如下:
    bridge_br0="eth0 tap0"
    config_eth0=( "null" )
    config_tap0="null"
    tuntap_tap0="tap"
    tunctl_tap0="-u root"
    config_br0=( "dhcp" )
    rc_need_br0="net.eth0 net.tap0"
    brctl_br0=( "setfd 0" "sethello 1" "stp off" )

    此外,还要让gentoo在启动时知道需要启动哪些网络接口:
    cd /etc/init.d
    ln -s net.lo net.br0
    ln -s net.lo net.tap0


四、参考文献
  1. Universal TUN/TAP device driver
  2. Tun/Tap interface tutorial
  3. QEMU Emulator User Documentation
  4. QEMU Networking
  5. QEMU on Windows
  6. The Linux Foundation -- bridge
  7. QEMU - Debian - Linux - TUN/TAP - network bridge
  8. Debian Lenny Tun/Tap Bridge Setup
  9. QEmu -- wiki
  10. Ubuntu Documentation -- KVM

你可能感兴趣的:(网络编程)