通過(guò)QEMU-GuestAgent實(shí)現(xiàn)從外部注入寫文件到KVM虛擬機(jī)內(nèi)部

通過(guò)QEMU-GuestAgent實(shí)現(xiàn)從外部注入寫文件到KVM虛擬機(jī)內(nèi)部

武穴網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)公司!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、APP開(kāi)發(fā)、成都響應(yīng)式網(wǎng)站建設(shè)公司等網(wǎng)站項(xiàng)目制作,到程序開(kāi)發(fā),運(yùn)營(yíng)維護(hù)。創(chuàng)新互聯(lián)公司從2013年創(chuàng)立到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)公司。

本文將以宿主上直接寫文件到VM內(nèi)部為例講解為何要注入以及如何實(shí)現(xiàn)

tag: qemu-ga, qemu guest agent, kvm, guest-file-write, inject

小慢哥的原創(chuàng)文章,歡迎轉(zhuǎn)載


目錄

? 為什么要“注入”到VM內(nèi)部
? 如何實(shí)現(xiàn)“注入”
? Step1. 為VM配置channel
? Step2. 部署qemu-ga
? Step3. 注入操作說(shuō)明
? Step4. Base64計(jì)算
? Step5. 開(kāi)始注入
? 附1. qemu-ga支持的所有指令
? 附2. 配置多個(gè)channel
? 參考文檔


為什么要“注入”到VM內(nèi)部

原因很簡(jiǎn)單:在VM外部無(wú)法實(shí)現(xiàn),只能進(jìn)入到VM內(nèi)來(lái)實(shí)現(xiàn)

KVM不像Docker(container)只是對(duì)進(jìn)程進(jìn)行cgroup隔離,KVM是全封閉的環(huán)境。

對(duì)于基于KVM的虛擬機(jī)來(lái)說(shuō),通常存在如下需求:

? 在線修改密碼
? 在線增加公鑰
? 在線采集性能(如cpu使用率、負(fù)載、內(nèi)存使用量等性能指標(biāo))
? 其他各種在線功能

上述這些場(chǎng)景的共性:僅在VM外部是無(wú)法實(shí)現(xiàn)的。因此就有了多種解決方案,但無(wú)論哪種解決方案都要同時(shí)滿足以下2點(diǎn)才能實(shí)現(xiàn):

? 通道:在VM內(nèi)部與外部(宿主)之間打開(kāi)一個(gè)通道,可以進(jìn)行數(shù)據(jù)交互
? agent:在VM內(nèi)部種下一個(gè)agent,用于接收外部的指令并反饋結(jié)果

在VM內(nèi)部種下agent的做法可以形象地稱之為"inject 注入"


如何實(shí)現(xiàn)“注入”

第一步,打開(kāi)通道

有2類方法:

? 走網(wǎng)絡(luò):會(huì)復(fù)雜一些,需要提前預(yù)插入一張管理網(wǎng)卡,或者利用已有網(wǎng)卡+特殊的路由來(lái)確保數(shù)據(jù)能走出去,這帶來(lái)了較為復(fù)雜的網(wǎng)絡(luò)拓?fù)?br/>? 走設(shè)備:簡(jiǎn)單很多,只需在VM內(nèi)部和宿主之間建立一個(gè)設(shè)備通道即可。比如為KVM虛擬機(jī)增加一個(gè)字符設(shè)備,并在宿主上映射為一個(gè)socket文件。字符設(shè)備與socket之間形成了一個(gè)channel,通過(guò)該channel就可以進(jìn)行內(nèi)外數(shù)據(jù)互通

“走網(wǎng)絡(luò)”不是本文想要介紹的,接下來(lái)所有內(nèi)容均為“走設(shè)備”

第二步,啟動(dòng)agent

在虛擬機(jī)里啟動(dòng)一個(gè)agent,實(shí)時(shí)讀取字符設(shè)備,實(shí)現(xiàn)與宿主的數(shù)據(jù)交互。

在channel中發(fā)送與接收什么樣的數(shù)據(jù),是可以自己定義的,也可以使用KVM官方實(shí)現(xiàn)的解決方案,稱為Qemu Guest Agent,簡(jiǎn)稱qemu-ga。它包含2方面:

? channel中傳送數(shù)據(jù)的協(xié)議定義:基于JSON的格式
? VM內(nèi)的agent:?jiǎn)?dòng)一個(gè)名叫qemu-ga的守護(hù)進(jìn)程,該進(jìn)程將從字符設(shè)備里獲取傳進(jìn)來(lái)的json指令,然后根據(jù)指令執(zhí)行相關(guān)命令,并將結(jié)果通過(guò)字符設(shè)備返回給宿主

qemu-ga的好用之處在于其封裝的指令兼容了一些不同的操作系統(tǒng),比如寫文件指令guest-file-write,既可以用于linux也可以用于windows。

關(guān)于qemu-ga的配置與使用,筆者之前已寫過(guò)一篇文章《基于QMP實(shí)現(xiàn)對(duì)qemu虛擬機(jī)進(jìn)行交互》,詳細(xì)介紹其工作原理及基本使用方法,這里附上地址

https://www.toutiao.com/i6646012291059810823/

由于本文主題是“注入寫文件”,因此接下來(lái)將重點(diǎn)闡述如何寫文件,不過(guò)也會(huì)將qemu-ga的部署與啟用方法再次貼出。


Step1. 為VM配置channel

通過(guò)libvirt啟動(dòng)的虛擬機(jī),可以在XML里增加一段配置

<channel type='unix'>
  <source mode='bind' path='/tmp/channel.sock'/>
  <target type='virtio' name='org.qemu.guest_agent.0'/>
</channel>

注意:上面這段配置要放在&lt;devices&gt;段落中


Step2. 部署qemu-ga

1?? 安裝qemu-ga

在VM內(nèi)部安裝并啟動(dòng)qemu-ga,linux和windows均支持qemu-ga,許多l(xiāng)inux發(fā)行商都會(huì)提供自己的qemu-ga,比如rhel/centos、fedora、ubuntu、opensuse都有提供編譯好的qemu-ga,可以直接下載使用。而windows系統(tǒng)需要下載virtio-win,其中有包含一些virtio的win驅(qū)動(dòng)以及qemu-ga安裝包,也可以僅下載qemu-ga安裝包

# rhel/centos
yum install qemu-guest-agent

# windows,最新virtio-win iso
https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/latest-virtio/
# windows,最新qemu-ga安裝包
https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/latest-qemu-ga/

windows的qemu-ga安裝包如圖所示

通過(guò)QEMU-GuestAgent實(shí)現(xiàn)從外部注入寫文件到KVM虛擬機(jī)內(nèi)部

2?? 啟動(dòng)qemu-ga

以centos7為例

# 啟動(dòng)qemu-ga守護(hù)進(jìn)程
systemctl start qemu-guest-agent

# 加入開(kāi)機(jī)啟動(dòng)
systemctl enable qemu-guest-agent

啟動(dòng)后通過(guò)systemctl status qemu-guest-agent應(yīng)當(dāng)能看到進(jìn)程已啟動(dòng),如圖所示

通過(guò)QEMU-GuestAgent實(shí)現(xiàn)從外部注入寫文件到KVM虛擬機(jī)內(nèi)部

注意:有的qemu-ga會(huì)拒絕部分指令,這是因?yàn)閝emu-ga的配置文件里將某些指令給禁用了,比如在centos7里,配置文件為/etc/sysconfig/qemu-ga

# 修改/etc/sysconfig/qemu-ga,將以下內(nèi)容注釋掉,或直接刪掉
BLACKLIST_RPC=guest-file-open,guest-file-close,guest-file-read,guest-file-write,guest-file-seek,guest-file-flush,guest-exec,guest-exec-status

# 重啟qemu-ga才能生效
systemctl restart qemu-guest-agent

3?? 測(cè)試qemu-ga

在VM的宿主機(jī)上,執(zhí)行以下命令:

# ${DOMAIN}表示虛擬機(jī)名字或UUID
virsh qemu-agent-command ${DOMAIN} '{"execute":"guest-ping"}'

如果返回以下內(nèi)容則表示qemu-ga可用

{"return":{}}

接下來(lái)查看下qemu-ga支持哪些指令

virsh qemu-agent-command ${DOMAIN} --pretty '{"execute":"guest-info"}'

應(yīng)該會(huì)看到支持很多命令,由于接下來(lái)做的實(shí)驗(yàn)需要用到如下命令,因此請(qǐng)先確認(rèn)是否均支持

? guest-exec:執(zhí)行命令(異步操作)
? guest-exec-status:查看執(zhí)行命令的結(jié)果
? guest-file-open:打開(kāi)文件,獲得句柄
? guest-file-write:寫文件(傳遞base64)
? guest-file-close:關(guān)閉文件


Step3. 注入操作說(shuō)明

實(shí)驗(yàn)?zāi)繕?biāo):將RSA的公鑰內(nèi)容寫入到/root/.ssh/authorized_keys

這涉及到如下3個(gè)步驟:

1. 創(chuàng)建/root/.ssh目錄且權(quán)限為700
2. 創(chuàng)建/root/.ssh/authorized_keys文件且權(quán)限為600
3. 將RSA公鑰文本進(jìn)行Base64編碼(guest-file-write不支持明文,僅支持base64),并將編碼后的內(nèi)容寫入/root/.ssh/authorized_keys


Step4. Base64計(jì)算

這里先假設(shè)RSA公鑰內(nèi)容為

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDVKog04pbbLaarjbpvK7CRaIuUwWxehJIH8tqtX/oV4GYN5WGYPFa1tzsd4Vyoblm4LePX79WeI4kFHgSbH5P6H9i8l3KCTFHHeJT/g0P55/c60yDb3o6lqpWu9IKE3I4lsTp05Y/W0Ks7W27Jndr162ni0Ybthgd9CQyoiburoh45ECiPGwWUOBVJ4IEpSpOZdDUJLS/vVuSQgvEH0fq/G1DP3SOyR+DNasJ00mwonfaUKHZXmWAlH8marNwPmWapyTSQwCFKKh2HwlJEWETV4fYuFwm3iennb8cX1y4aX9AJWnA2cc35rpulivMijeXs/ssT5iFljXXGYzmkX6nR root@localhost.localdomain

進(jìn)行Base64編碼

echo 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDVKog04pbbLaarjbpvK7CRaIuUwWxehJIH8tqtX/oV4GYN5WGYPFa1tzsd4Vyoblm4LePX79WeI4kFHgSbH5P6H9i8l3KCTFHHeJT/g0P55/c60yDb3o6lqpWu9IKE3I4lsTp05Y/W0Ks7W27Jndr162ni0Ybthgd9CQyoiburoh45ECiPGwWUOBVJ4IEpSpOZdDUJLS/vVuSQgvEH0fq/G1DP3SOyR+DNasJ00mwonfaUKHZXmWAlH8marNwPmWapyTSQwCFKKh2HwlJEWETV4fYuFwm3iennb8cX1y4aX9AJWnA2cc35rpulivMijeXs/ssT5iFljXXGYzmkX6nR root@localhost.localdomain' | base64 -w 0

這樣就獲得了base64編碼內(nèi)容

c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCQVFEVktvZzA0cGJiTGFhcmpicHZLN0NSYUl1VXdXeGVoSklIOHRxdFgvb1Y0R1lONVdHWVBGYTF0enNkNFZ5b2JsbTRMZVBYNzlXZUk0a0ZIZ1NiSDVQNkg5aThsM0tDVEZISGVKVC9nMFA1NS9jNjB5RGIzbzZscXBXdTlJS0UzSTRsc1RwMDVZL1cwS3M3VzI3Sm5kcjE2Mm5pMFlidGhnZDlDUXlvaWJ1cm9oMzVFQ2lQR3dXVU9CVko0SUVwU3BPWmREVUpMUy92VnVTUWd2RUgwZnEvRzFEUDNTT3lSK0ROYXNKMDBtd29uZmFVS0haWG1XQWxIOG1hck53UG1XYXB5VFNRd0NGS0toMUh4bEpFV0VUVjRmWXVGd20zaWVubmI4Y1gxeTRhWDlBSlduQTJjYzM1cnB1bGl2TWlqZVhzL3NzVDVpRmxqWFhHWXpta1g2blIgcm9vdEBsb2NhbGhvc3QubG9jYWxkb21haW4K

Step5. 開(kāi)始注入

1?? 創(chuàng)建/root/.ssh目錄且權(quán)限為700

# mkdir /root/.ssh
virsh qemu-agent-command ${DOMAIN} '{"execute":"guest-exec","arguments":{"path":"mkdir","arg":["-p","/root/.ssh"],"capture-output":true}}'

# 假設(shè)上一步返回{"return":{"pid":911}},接下來(lái)查看結(jié)果(通??珊雎裕?virsh qemu-agent-command ${DOMAIN} '{"execute":"guest-exec-status","arguments":{"pid":911}}' 

# chmod 700 /root/.ssh,此行其實(shí)可不執(zhí)行,因?yàn)樯厦鎰?chuàng)建目錄后就是700,但為了防止權(quán)限不正確導(dǎo)致無(wú)法使用,這里還是再刷一次700比較穩(wěn)妥
virsh qemu-agent-command ${DOMAIN} '{"execute":"guest-exec","arguments":{"path":"chmod","arg":["700","/root/.ssh"],"capture-output":true}}' 

# 假設(shè)上一步返回{"return":{"pid":912}},接下來(lái)查看結(jié)果(通??珊雎裕?virsh qemu-agent-command ${DOMAIN} '{"execute":"guest-exec-status","arguments":{"pid":912}}'

2?? 創(chuàng)建/root/.ssh/authorized_keys文件且權(quán)限為600

# touch /root/.ssh/authorized_keys
virsh qemu-agent-command ${DOMAIN} '{"execute":"guest-exec","arguments":{"path":"touch","arg":["/root/.ssh/authorized_keys"],"capture-output":true}}'

# 假設(shè)上一步返回{"return":{"pid":913}},接下來(lái)查看結(jié)果(通常可忽略)
virsh qemu-agent-command ${DOMAIN} '{"execute":"guest-exec-status","arguments":{"pid":913}}'

# chmod 600 /root/.ssh/authorized_keys,此行其實(shí)可不執(zhí)行,因?yàn)樯厦鎰?chuàng)建文件后就是600,但為了防止權(quán)限不正確導(dǎo)致無(wú)法使用,這里還是再刷一次600比較穩(wěn)妥
virsh qemu-agent-command ${DOMAIN} '{"execute":"guest-exec","arguments":{"path":"chmod","arg":["600","/root/.ssh/authorized_keys"],"capture-output":true}}'

# 假設(shè)上一步返回{"return":{"pid":914}},接下來(lái)查看結(jié)果(通??珊雎裕?virsh qemu-agent-command ${DOMAIN} '{"execute":"guest-exec-status","arguments":{"pid":914}}'

3?? 將Base64編碼寫入/root/.ssh/authorized_keys

# 打開(kāi)文件(以讀寫方式打開(kāi)),獲得句柄
virsh qemu-agent-command ${DOMAIN} '{"execute":"guest-file-open", "arguments":{"path":"/root/.ssh/authorized_keys","mode":"w+"}}'

# 寫文件,假設(shè)上一步返回{"return":1000},1000就是句柄
virsh qemu-agent-command ${DOMAIN} '{"execute":"guest-file-write", "arguments":{"handle":1000,"buf-b64":"c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCQVFEVktvZzA0cGJiTGFhcmpicHZLN0NSYUl1VXdXeGVoSklIOHRxdFgvb1Y0R1lONVdHWVBGYTF0enNkNFZ5b2JsbTRMZVBYNzlXZUk0a0ZIZ1NiSDVQNkg5aThsM0tDVEZISGVKVC9nMFA1NS9jNjB5RGIzbzZscXBXdTlJS0UzSTRsc1RwMDVZL1cwS3M3VzI3Sm5kcjE2Mm5pMFlidGhnZDlDUXlvaWJ1cm9oMzVFQ2lQR3dXVU9CVko0SUVwU3BPWmREVUpMUy92VnVTUWd2RUgwZnEvRzFEUDNTT3lSK0ROYXNKMDBtd29uZmFVS0haWG1XQWxIOG1hck53UG1XYXB5VFNRd0NGS0toMUh4bEpFV0VUVjRmWXVGd20zaWVubmI4Y1gxeTRhWDlBSlduQTJjYzM1cnB1bGl2TWlqZVhzL3NzVDVpRmxqWFhHWXpta1g2blIgcm9vdEBsb2NhbGhvc3QubG9jYWxkb21haW4K"}}'

# 關(guān)閉文件
virsh qemu-agent-command ${DOMAIN} '{"execute":"guest-file-close", "arguments":{"handle":1000}}'

查看效果:此時(shí)到VM里查看/root/.ssh/authorized_keys,應(yīng)該能看到新增加的一行


附1. qemu-ga支持的所有指令

不同的qemu-ga版本、不同的操作系統(tǒng),支持的指令都會(huì)有所差異,下面是從官網(wǎng)上看到的當(dāng)前所有參數(shù)

? guest-exec
? guest-exec-status
? guest-file-close
? guest-file-flush
? guest-file-open
? guest-file-read
? guest-file-seek
? guest-file-write
? guest-fsfreeze-freeze
? guest-fsfreeze-freeze-list
? guest-fsfreeze-status
? guest-fsfreeze-thaw
? guest-fstrim
? guest-get-fsinfo
? guest-get-host-name
? guest-get-memory-block-info
? guest-get-memory-blocks
? guest-get-osinfo
? guest-get-time
? guest-get-timezone
? guest-get-users
? guest-get-vcpus
? guest-info
? guest-network-get-interfaces
? guest-ping
? guest-set-memory-blocks
? guest-set-time
? guest-set-user-password
? guest-set-vcpus
? guest-shutdown
? guest-suspend-disk
? guest-suspend-hybrid
? guest-suspend-ram
? guest-sync
? guest-sync-delimited

具體使用方法,請(qǐng)參考官網(wǎng)文檔

https://qemu.weilnetz.de/doc/qemu-ga-ref.html

附2. 配置多個(gè)channel

1?? 可以在XML里配置多個(gè)channel,這樣就可以創(chuàng)建多個(gè)設(shè)備通道

<channel type='unix'>
  <source mode='bind' path='/tmp/channel.sock'/>
  <target type='virtio' name='org.qemu.guest_agent.0'/>
</channel>
<channel type='unix'>
  <source mode='bind' path='/tmp/channel.sock-1'/>
  <target type='virtio' name='org.qemu.guest_agent.1'/>
</channel>

2?? 在VM里要啟動(dòng)2個(gè)qemu-ga守護(hù)進(jìn)程,可以將原有的service文件拷貝一份出來(lái)進(jìn)行修改

cd /usr/lib/systemd/system
cp qemu-guest-agent.service qemu-guest-agent-1.service

然后修改qemu-guest-agent-1.service

通過(guò)QEMU-GuestAgent實(shí)現(xiàn)從外部注入寫文件到KVM虛擬機(jī)內(nèi)部

3?? 啟動(dòng)服務(wù)

systemctl start qemu-guest-agent-1

參考文檔

# qemu-ga介紹與使用:QEMU Guest Agent
# qemu-ga完整參數(shù):https://qemu.weilnetz.de/doc/qemu-ga-ref.html
# 筆者另一篇相關(guān)文章《基于QMP實(shí)現(xiàn)對(duì)qemu虛擬機(jī)進(jìn)行交互》:https://www.toutiao.com/i6646012291059810823/

分享文章:通過(guò)QEMU-GuestAgent實(shí)現(xiàn)從外部注入寫文件到KVM虛擬機(jī)內(nèi)部
鏈接URL:http://bm7419.com/article32/iehspc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供Google、移動(dòng)網(wǎng)站建設(shè)、電子商務(wù)、商城網(wǎng)站靜態(tài)網(wǎng)站、網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

商城網(wǎng)站建設(shè)