2014年3月27日 星期四

Qemu 執行時之問題排除

Qemu 是建置虛擬電腦教室環境中不可或缺的工具,我們所使用的 Qemu 是自行編譯下載,在執行時可能會出現底下錯誤需要處理:

設定qemu-bridge-helper 權限

qemu-bridge-helper 需要有 root 的權限才能執行,如果沒有 root 權限的話在啟動 qemu 時會出現底下錯誤訊息

failed to create tun device: Operation not permitted
failed to launch bridge helper
qemu-system-x86_64: -net bridge,br=br10: Device 'bridge' could not be initialized

由於我們希望給一般使用者執行 qemu-bridge-helper 的權限,而其安裝目錄在 /usr/local/libexec,我們可以執行底下指令以觀看此檔權限:

ls -l /usr/local/libexec/qemu-bridge-helper


其輸出如下所示:

-rwxr-xr-x 1 root staff 39624 Mar  8 00:08 qemu-bridge-helper

為了讓一般使用者可以執行,此檔案必須具有 SETUID,如此一來才有可以執行之權限,請執行底下指令來設定:

chmod u+s /usr/local/libexec/qemu-bridge-helper

此時再觀察其屬性,其輸出如下所示:

-rwsr-xr-x 1 root staff 39624 Mar  8 00:08 qemu-bridge-helper


我們可以發現其屬性由 rwxr-xr-x 改成 rw{\bf s}r-xr-x,這表示此檔已具有 SEDUID 屬性,可以提供一般使用者使用了。

設定可執行之橋接網路權限

在 Qemu 執行時,會檢查 /usr/local/etc/qemu/bridge.conf 中之權限,如果沒(有)設定的話,在執行 Qemu 時會出現底下的錯誤訊息:

access denied by acl file
failed to launch bridge helper
qemu-system-x86_64: -net bridge,br=br10: Device 'bridge' could not be initialized

以本書來說,所要支援之橋接網路介面為 br10,因此我們必須在 /usr/local/etc/qemu/bridge.conf 檔中增加一行 allow br10 之設定,如底下所示。

allow br0
allow br1
allow br2
allow br10

上述設定是說橋接網路介面 br0、br1、br2 以及 br10 都可以使用,此時我們再執行 Qemu 的話就不會(有)先前的錯誤訊息了。





找不到 bios.bin

如果在執行 qemu 時出現底下錯誤,那表示 seabios 沒有安裝或是作正確的連結。

qemu: could not load PC BIOS 'bios.bin'

要解決此問題,請先安裝 seabios 套件,然後以 root 權限在 /usr/local/share/qemu 目錄下執行:

/usr/local/share/qemu# ln -sf /usr/share/seabios/*.bin .

找不到 kvmvapic.bin

如果在執行 qemu 時出現底下錯誤,那表示 seabios 沒有安裝或是作正確的連結。

Could not open option rom 'kvmvapic.bin': No such file or directory

要解決此問題,請先安裝 seabios 套件,然後以 root 權限在 /usr/local/share/qemu 目錄下執行:

/usr/local/share/qemu# ln -sf /usr/share/seabios/optionrom/*.bin .

安裝、設定 PXE Server

#2019/09/23 修訂

PXE 開機伺服器建置

從現在開始我們要進行虛擬電腦教室的安裝,有關所有檔案的定義請參考下圖:



安裝 qemu 套件

請以 root 權限安裝 qemu-utils qemu-system-x86 套件,指令如下:

# apt-get install qemu-utils qemu-system-x86

裝完之後請以一般使用者權限執行
$ qemu-img --help



開機之問題排除

當我們執行 qemu 時,會出現底下錯誤:
qemu: could not load PC BIOS 'bios.bin'

這是因為 qemu 在執行時會使用到一些 BIOS 的檔案,這些檔案在 qemu 中並未提供,而是要安裝 seabios 套件,因此請執行

apt-get install seabios

將 seabios 套件安裝,並且在 /usr/local/share/qemu 作連結,指令如下:

# ln -sf /usr/share/bios/*.bin

作好連結後再啟動  runpxe.sh,此時即可順利進入 qemu 畫面,並讓 pxe server 順利開機。
一旦 Qemu 可以正常執行之後,我們即可立即動手建立虛擬電腦教室中的第一台電腦,這台電腦將會是整間虛擬電腦教室的 pxe、dhcp 以及安裝伺服器,我們將此電腦命名為 pxeserver。

PXE Server 影像檔建置

PXE Server 並不需要太大的硬碟空間,因此我們設定一個 2GB 大小的影像檔即可,這個檔案我們命名為 pxeserver.img,請執行底下指令來建立此影像檔。

~/virtualclassroom $ qemu-img create pxeserver.img 2G -f qcow2

建立完畢後,我們可以執行 ls -l pxeserver.img 來觀看此檔案,其輸出如下所示:

-rw-r--r-- 1 hunter hunter 2147483648  3月 27 20:23 pxeserver.img


乍看之下 pxeserver.img 的大小為 2 GB (2147483648 bytes),但是如果我們以 du 這個指令來觀看其大小如底下所示:

du -sh pxeserver.img

會發現其輸出為 0 如底下所示,這是因為 qemu-img 所建立的檔案是一個會長大的檔案,一開始新建的檔案大小為 0,而當我們使用此檔來進行作業系統安裝時,它會隨著容量的增加而(自)己長大,一直到 2 GB 為止。

0 pxeserver.img



安裝 Debian X86_64 作業系統

接下來要開始使用 Qemu 安裝 Debian X86_64 作業系統(至) pxeserver.img,安裝「標準系統工具」即可,其它套件例如桌面環境 (Debian desktop environment) 等不必安裝,以節省空間。

請把 Debian 的 ISO 檔放在 /opt/iso/debian-8.3.0-amd64-CD-1.iso

然後執行:

~/virtualclassroom $  qemu-system-x86_64 -enable-kvm -m 2048 -cpu host -smp 2 -drive file=pxeserver.img,format=qcow2 -cdrom /opt/iso/debian-10.1.0-amd64-netinst.iso -boot d

我們可以另外編輯一個 buildpxe.sh 的檔案,其內容如下:

qemu-system-x86_64 -enable-kvm -m 2048 -cpu host -smp 2 \
        -drive file=pxeserver.img,format=qcow2 \
        -cdrom /opt/iso/debian-10.1.0-amd64-netinst.iso \
        -boot d
然後在 ~/virtualclassroom 目錄中執行 sh buildpxe.sh 即可。請安裝 base install,硬碟讓系統自動幫你分割。



啟動 PXE Server

建立好 PXE Server 之後,我們可以另外使用 runpxe.sh 來啟動 PXE Server,其內容如下所示。


# IP=192.168.10.254
# PXE Server

CPU=host
SMP=2
MEMORY=1024
HDA=pxeserver.img
MAC="DE:AD:BE:CF:EC:B7"
BRIDGE=br10
CDROM=/opt/iso/debian-10.1.0-amd64-netinst.iso

qemu-system-x86_64 -enable-kvm -cpu $CPU -smp $SMP -m $MEMORY \
-drive file=$HDA,format=qcow2 \
-net nic,macaddr=$MAC -net bridge,br=$BRIDGE \
-boot c

如果不曉得要怎麼生虛擬 MAC Address 的可以至 https://miniwebtool.com/mac-address-generator/ 網址自己產生一個。

儲存完畢後執行:

~/virtualclassroom $ sh runpxe.sh 
failed to create tun device: Operation not permitted
qemu-system-x86_64: -net bridge,br=br10: bridge helper failed

此訊息是因為 qemu bridge helper 這個檔案的權限不足所致,因此我們要自行設定此檔案有 u+s 的權限,請以 root 權限切換至 /usr/lib/qemu 底下有一個 qemu-bridge-helper 的檔案,其屬性如下:

/usr/lib/qemu# ls -l
總計 16
-rwxr-xr-x 1 root root 14328  8月  9 18:41 qemu-bridge-helper

請以 root 權限執行:

/usr/lib/qemu# chmod u+s qemu-bridge-helper 

作完之後其屬性為:

ls -l
總計 16
-rwsr-xr-x 1 root root 14328  8月  9 18:41 qemu-bridge-helper

接著恢復一般使用者權限執行:

~/virtualclassroom $ sh runpxe.sh
access denied by acl file
qemu-system-x86_64: -net bridge,br=br10: bridge helper failed

此時會有另一個錯誤訊息叫 access denied by acl file,要解決這個問題,必須以 root 權限在 /etc/qemu 目錄底下新增一個 bridge.conf,裡面的內容是:

allow br10

然後再以一般使用者權限執行:

~/virtualclassroom $ sh runpxe.sh 


此時應該可以看到 pxe 這台虛擬機正確啟動,沒有問題。PXE 伺服器啟動後,我們來驗收一下系統,請執行:

$ cat /proc/cpuinfo
$ free -h
$ df -h

來看 CPU、記憶體以及硬碟空間。




2014年3月13日 星期四

如何在 Qemu 環境下使用 tun/tap 設定以與外界連繫 ?

前言,要使用 VM (虛擬機器) 的一個相當重要的前提是外界可以連到我們的 VM,因此需要使用到 tun tap 來進行設定,以下我們將介紹如何在 Debian 底下以 Qemu 架設 VM,再來與外界連繫。


什麼是 tun tap ?
http://www.ibm.com/developerworks/cn/linux/l-tuntap/index.html

首先請先確認你的機器中有載入 tun 模組,指令如下:

lsmod |grep tun

如果有載入 tun 模組的話,那麼會有底下的輸出:

tun                    16887  13

萬一沒有的話,可以使用 root 權限執行

modprobe tun

來載入此模組。我們可以觀察底下檔案

/dev/net/tun

來看看是否有 tun 裝置。其輸出如下:

crw-rw-rwT 1 root root 10, 200 12月 30 15:03 /dev/net/tun

理論上,你的 tun 裝置現在的 owner 及 group 都是 root,這對我們執行虛擬機器有
很大安全漏洞,因為使用者要使用 tun 裝置必須將其加入 root 群組才行,但是把一般
使用者加入 root 群組讓這個使用者擁有不必要的 root 權限。為了系統安全著想,我
們特別新增一個 kvm 的群組,並且讓所有人(包括裝置)都以 kvm 群組為內定權限來開
啟虛擬機器。並將 /dev/net/tun 之群組改為 kvm,如底下所示:


crw-rw-rwT 1 root kvm 10, 200 11月 11 08:42 /dev/net/tun


新增群組 groupadd kvm
設定群組 chgrp kvm /dev/net/tun
觀看使用群組 id username
該 user 必須要有一個次群組為 kvm 才行,如下所示:

id herman
uid=1000(herman) gid=1000(herman) groups=1000(herman),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),1001(kvm),120(uml-net),500(nfsuser),501(ftp),502(qemu)




Q: 萬一你的 Linux 核心沒有 tun 模組怎麼辦 ?
A: 自己編 Linux 核心,並將 tun 編譯成模組。

接下來請以 qemu 執行虛擬機器,指令如下:

 qemu-system-x86_64 -enable-kvm -m 1024 -hda linux1.img -net nic -net bridge,br=br1


成功的話,我們可以在實體機器上 ping 虛擬機器,也可以在虛擬機器上 ping 實體機器,而此時虛擬機器要以 192.168.1.xx 為 IP。


如何在 Linux 底下建立橋接介面給虛擬機器使用

#2019/09/23 修訂

0. 原始網路介面:enp2s0

1. 安裝需要軟體 aptitude install bridge-utils uml-utilities

   安裝完畢後我們即可使用 brctl 這個指令來觀察/新增/移除橋接網路介面。


2. 請以 root 權限執行

   brctl

   其輸出如下所示:

Usage: brctl [commands]
commands:
        addbr           <bridge>                add bridge
        delbr           <bridge>                delete bridge
        addif           <bridge> <device>       add interface to bridge
        delif           <bridge> <device>       delete interface from bridge
        hairpin         <bridge> <port> {on|off}        turn hairpin on/off
        setageing       <bridge> <time>         set ageing time
        setbridgeprio   <bridge> <prio>         set bridge priority
        setfd           <bridge> <time>         set bridge forward delay
        sethello        <bridge> <time>         set hello time
        setmaxage       <bridge> <time>         set max message age
        setpathcost     <bridge> <port> <cost>  set path cost
        setportprio     <bridge> <port> <prio>  set port priority
        show            [ <bridge> ]            show a list of bridges
        showmacs        <bridge>                show a list of mac addrs
        showstp         <bridge>                show bridge stp info
        stp             <bridge> {on|off}       turn stp on/off

a. 觀看橋接介面資訊:

我們可以執行

   brctl show

   來觀看目前橋接介面狀態,因為目前為止沒有任何橋接介面存在,因此其輸出如下:

bridge name     bridge id               STP enabled     interfaces


b. 建立空的網路橋接介面

brctl addbr br0

建立完畢後再執行 brctl show,其輸出如下:

bridge name     bridge id               STP enabled     interfaces
br0             8000.000000000000       no

請注意最右邊的 interfaces 欄位底下是空的。

或是執行 ip addr show 可以顯示其結果,其輸出如下:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
    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: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:24:1d:12:5c:c7 brd ff:ff:ff:ff:ff:ff
    inet 120.117.72.71/25 brd 120.117.72.127 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::224:1dff:fe12:5cc7/64 scope link
       valid_lft forever preferred_lft forever
3: br0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN
    link/ether 8a:f7:14:d0:e3:54 brd ff:ff:ff:ff:ff:ff

上述兩種輸出我們都可以看到有新增一個介面叫 br0,這就是所謂的橋接網路介面。



3. 將 br0 橋接給 eth0 使用

brctl addif br0 eth0

eth0 -> br0 -> internet

此時我們再執行

brctl show

會出現

bridge name     bridge id               STP enabled     interfaces
br0             8000.00241d125cc7       no              eth0

這告訴我們目前 eth0 已加入 br0 橋接網路介面中。


接下來我們可以執行一些網路指令來觀看目前網路設定狀況:

3.1 ifconfig

其輸出如下:

br0       Link encap:Ethernet  HWaddr 00:24:1d:12:5c:c7
          inet6 addr: fe80::224:1dff:fe12:5cc7/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:31862 errors:0 dropped:0 overruns:0 frame:0
          TX packets:13 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:8351683 (7.9 MiB)  TX bytes:762 (762.0 B)

eth0      Link encap:Ethernet  HWaddr 00:24:1d:12:5c:c7
          inet addr:120.117.72.71  Bcast:120.117.72.127  Mask:255.255.255.128
          inet6 addr: fe80::224:1dff:fe12:5cc7/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:92871708 errors:0 dropped:27 overruns:0 frame:0
          TX packets:116756678 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:59143957987 (55.0 GiB)  TX bytes:143394438170 (133.5 GiB)


lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:854820 errors:0 dropped:0 overruns:0 frame:0
          TX packets:854820 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:72657228 (69.2 MiB)  TX bytes:72657228 (69.2 MiB)

3.2 route (觀看目前主機路由) -> 什麼叫主機路由 ?

其輸出如下:

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         120.117.72.126  0.0.0.0         UG    0      0        0 eth0
120.117.72.0    *               255.255.255.128 U     0      0        0 eth0

但是現在網路會出現連線的問題,因此我們要再修改一下。

4. 修改網路設定,使其開機後能自動 bridge

編輯 /etc/network/interfaces,將 eth0 由 底下片段:

# The primary network interface
allow-hotplug eth0
iface eth0 inet static
        address 120.117.72.71
        netmask 255.255.255.128
        gateway 120.117.72.126
        # dns-* options are implemented by the resolvconf package, if installed
        dns-nameservers 120.117.2.1
        dns-search eecs.stust.edu.tw

改為:

# The primary network interface
#allow-hotplug eth0
#iface eth0 inet static
#        address 120.117.72.71
#        netmask 255.255.255.128
#        gateway 120.117.72.126
#        # dns-* options are implemented by the resolvconf package, if installed
#        dns-nameservers 120.117.2.1
#        dns-search eecs.stust.edu.tw


iface eth0 inet manual

auto br0
iface br0 inet static
address 120.117.72.71
netmask 255.255.255.128
gateway 120.117.72.126
bridge_ports eth0
bridge_fd 9
bridge_hello 2
bridge_maxage 12
bridge_stp off

重新編輯 /etc/network/interfaces 檔案後,我們可以執行

/etc/init.d/networking restart

來重新啟動網路介面,其輸出如下:

[....] Running /etc/init.d/networking restart is deprecated because it may not r[warnble some interfaces ... (warning).
[....] Reconfiguring network interfaces...
Waiting for br0 to get ready (MAXWAIT is 20 seconds).
Starting rpcbind daemon...Already running..
Starting NFS common utilities: statd idmapd.
done.

接著我們執行 ifconfig 來觀看網路狀況,其輸出如下:

br0       Link encap:Ethernet  HWaddr 00:24:1d:12:5c:c7
          inet addr:120.117.72.71  Bcast:120.117.72.127  Mask:255.255.255.128
          inet6 addr: fe80::224:1dff:fe12:5cc7/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:33183 errors:0 dropped:0 overruns:0 frame:0
          TX packets:427 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:8487100 (8.0 MiB)  TX bytes:33164 (32.3 KiB)

eth0      Link encap:Ethernet  HWaddr 00:24:1d:12:5c:c7
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:92875730 errors:0 dropped:27 overruns:0 frame:0
          TX packets:116759427 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:59145121172 (55.0 GiB)  TX bytes:143394914474 (133.5 GiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:857668 errors:0 dropped:0 overruns:0 frame:0
          TX packets:857668 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:72951279 (69.5 MiB)  TX bytes:72951279 (69.5 MiB)

我們可以發現此時 br0 有網路 ip 等設定,而 eth0 沒有了。接下來我們可以重啟電腦,
來觀看是否重開機後網路設定仍然存在。

另外我們可以觀察 route 來看看主機路由為何,其輸出如下:

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         120-117-72-126. 0.0.0.0         UG    0      0        0 br0
120.117.72.0    *               255.255.255.128 U     0      0        0 br0


從上面資訊可以看到目前的對外路由為 br0 介面。


5. 新增 br1 網路介面

請在 /etc/network/interfaces 中新增底下片段:

auto br1
iface br1 inet static
address 192.168.1.1
netmask 255.255.255.0
gateway 120.117.72.71
bridge_ports tap0
bridge_fd 9
bridge_hello 2
bridge_maxage 12
bridge_stp off

請注意上述設定中之 gateway 要為本機 ip,而 bridge ports 要設為 tap0,設定完畢後
請執行:

/etc/init.d/networking restart

其輸出如下:

[....] Running /etc/init.d/networking restart is deprecated because it may not r[warnble some interfaces ... (warning).
[....] Reconfiguring network interfaces...
Waiting for br0 to get ready (MAXWAIT is 20 seconds).
if-up.d/mountnfs[br0]: waiting for interface br1 before doing NFS mounts ... (warning).
interface tap0 does not exist!

Waiting for br1 to get ready (MAXWAIT is 20 seconds).
RTNETLINK answers: Network is unreachable
Failed to bring up br1.
done.

此時我們再執行一次 ifconfig 來觀看網路介面,其輸出如下:


br0       Link encap:Ethernet  HWaddr 00:24:1d:12:5c:c7
          inet addr:120.117.72.71  Bcast:120.117.72.127  Mask:255.255.255.128
          inet6 addr: fe80::224:1dff:fe12:5cc7/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:4 errors:0 dropped:0 overruns:0 frame:0
          TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1144 (1.1 KiB)  TX bytes:364 (364.0 B)

br1       Link encap:Ethernet  HWaddr 36:88:01:09:0f:26
          inet addr:192.168.1.1  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::3488:1ff:fe09:f26/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:238 (238.0 B)

eth0      Link encap:Ethernet  HWaddr 00:24:1d:12:5c:c7
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:123634 errors:0 dropped:0 overruns:0 frame:0
          TX packets:108003 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:102252702 (97.5 MiB)  TX bytes:96428415 (91.9 MiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:6489 errors:0 dropped:0 overruns:0 frame:0
          TX packets:6489 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:364364 (355.8 KiB)  TX bytes:364364 (355.8 KiB)


我們可以看到多了一個 br1 網路介面,其網段是 192.168.1.1/24