BruceFan's Blog

Stay hungry, stay foolish

0%

Ubuntu下SSH登录Qemu虚拟机

宿主机要通过ssh访问虚拟机有两种网络配置方式,一种是用户模式网络,另一种是网桥网络模式。

qemu内部的用户模式网络

在没有任何-net参数时,qemu默认使用的是-net nic -net user参数,提供了一种用户模式(user-mode)的网络模拟。使用用户模式网络的虚拟机可以连通宿主机及外部网络,用户模式网络是完全由qemu自身实现,不依赖于其他工具,而且不需要root权限。qemu使用Slirp实现了一整套TCP/IP协议栈,并且使用这个协议栈实现了一套虚拟的NAT网络。

优点:

  • 使用简单
  • 独立性好
  • 虚拟机网络隔离性好

缺点:

  • 由于其在qemu内部实现所有网络协议栈,因此其性能较差
  • 不支持部分网络功能(如ICMP),所以不能在虚拟机中使用ping命令
  • 不能从宿主机或外部网络直接访问客户机

命令举例:

1
2
3
4
5
6
7
8
9
10
11
12
$ qemu-system-x86_64 \
-kernel $KERNEL/arch/x86/boot/bzImage \
-append "console=ttyS0 root=/dev/sda debug earlyprintk=serial slub_debug=QUZ" \
-hda $IMAGE/stretch.img \
-net user,hostfwd=tcp::10021-:22 \
-net nic,model=e1000 \
-enable-kvm \
-nographic \
-m 1G \
-smp 2 \
-pidfile vm.pid \
2>&1 | tee vm.log

-net user表示使用的是用户模式,hostfwd=tcp::10021-:22表示将虚拟机22端口转发到宿主机的10021端口。
-net nic表示为虚拟机创建虚拟机网卡,model=e1000表示为虚拟机添加一块e1000型的网卡,这也是qemu的默认类型。
查看qemu支持的NIC类型:

1
2
3
$ qemu-system-x86_64 -net nic,model=?
warning: TCG doesn't support requested feature: CPUID.01H:ECX.vmx [bit 5]
qemu: Supported NIC models: ne2k_pci,i82551,i82557b,i82559er,rtl8139,e1000,pcnet,virtio

这样配置好目录和参数以后启动qemu,有可能会遇到如下错误:

1
[FAILED] Failed to start Raise network interfaces.

这是虚拟机网络配置有问题,使用ip命令查看虚拟机使用的网卡,在虚拟机里执行:

1
2
3
4
5
6
7
8
9
10
11
# ip a s
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff
3: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
link/sit 0.0.0.0 brd 0.0.0.0

可以看到有一个enp0s3网卡,查看网络配置文件:

1
2
3
# vi /etc/network/interfaces
auto eth0
iface eth0 inet dhcp

网络配置文件中的网卡和实际的网卡不一样,修改eth0enp0s3,重启网络:

1
2
3
4
5
6
# /etc/init.d/networking restart
Restarting networking (via systemctl): networking.service[ 287.214196] e1000: enp0s3 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: RX
[ 287.227353] IPv6: ADDRCONF(NETDEV_CHANGE): enp0s3: link becomes ready
[ 287.446498] audit: type=1107 audit(1559202014.248:8): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:kernel_t:s0 msg='avc: denied { reload } for auid=n/a uid=0 gid=0 path="/lib/systemd/system/ssh.service" cmdline="systemctl reload --no-block ssh.service" scontext=system_u:system_r:kernel_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=service
[ 287.446498] exe="/lib/systemd/systemd" sauid=0 hostname=? addr=? terminal=?'
.

启动网卡成功,可以在宿主机ssh连接虚拟机了:

1
$ ssh -i identity_file -p 10021 root@localhost

使用网桥模式

网桥(bridge)模式可以让虚拟机和宿主机共享一个物理网络设备连接网络,虚拟机有自己的独立IP地址,可以直接连接与宿主机一样的网络,虚拟机可以访问外部网络,外部网络也可以直接访问客户机(就像访问普通物理主机一样)。即使宿主机只有一个网卡设备,使用bridge方式也可以让多个虚拟机与宿主机共享网络设备。
bridge模式需要添加-net tap参数,表明使用TAP设备。TAP是虚拟网络设备,它仿真了一个数据链路层设备(ISO七层网络结构的第二层),它像以太网的数据帧一样处理第二层数据包。TUN与TAP类似,也是一种虚拟网络设备,它是对网络层的仿真。TAP被用于创建一个网桥,而TUN与路由相关。

第一种linux下tap网络配置方法:

建立网桥:Ubuntu上需要安装建立虚拟网络设备的工具uml-utilities和桥接工具bridge-utils:

1
$ sudo apt install uml-utilities bridge-utils

创建一个bridge

1
$ sudo brctl addbr br0

清空网卡的IP

1
$ sudo ip addr flush dev eth0

添加网卡到bridge

1
$ sudo brctl addif br0 eth0

创建tap接口

1
$ sudo tunctl -t tap0 -u fanrong

添加tap0到bridge

1
$ sudo brctl addif br0 tap0

确定都已启动

1
2
3
$ sudo ifconfig eth0 up
$ sudo ifconfig tap0 up
$ sudo ifconfig br0 up

检查桥接是否恰当

1
$ sudo brctl show

为br0分配ip

1
2
$ brctl stp br0 on # 待定
$ sudo dhclient br0

启动命令

1
$ sudo qemu-system-i386 -cdrom Core-current.iso -boot d -netdev tap,id=mynet0,ifname=tap0,script=no,downscript=no -device e1000,netdev=mynet0,mac=52:55:00:d1:55:01

第二种linux下tap网络配置方法:

1.建立一个虚拟网络接口

1
$ sudo mknod /dev/net/tun c 10 200

2.建立网桥
修改/etc/network/interface配置文件。此处建立一个名为br0的网桥,先桥接上eth0,在启动qemu时,再桥接上tap0。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
auto lo
iface lo inet loopback

auto br0
iface br0 inet static
address 192.168.1.2
network 192.168.1.0
netmask 255.255.255.0
broadcast 192.168.1.255
gateway 192.168.1.1
bridge_ports eth0
bridge_fd 9
bridge_hello 2
bridge_maxage 12
bridge_stp off

3.建立qemu-ifup脚本,启动qemu时调用

1
2
3
4
5
6
7
8
$ sudo apt install uml-utilities bridge-utils
$ brctl addbr br0
$ sudo vim /etc/qemu-ifup
#!/bin/sh
sudo /sbin/ifconfig $1 0.0.0.0 promisc up
sudo /sbin/brctl addif br0 $1
sleep 2
$ sudo chmod +x /etc/qemu-ifup

4.qemu启动命令

1
$ -net nic -net tap,ifname=tap0,script=/etc/qemu-ifup 

reference
http://smilejay.com/2016/09/kvm-user-mode-networking/
http://smilejay.com/2012/08/kvm-bridge-networking/