日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

kvm虚拟机_通过QEMU-GuestAgent实现从外部注入写文件到KVM虚拟机内部

發布時間:2025/3/21 编程问答 63 豆豆
生活随笔 收集整理的這篇文章主要介紹了 kvm虚拟机_通过QEMU-GuestAgent实现从外部注入写文件到KVM虚拟机内部 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文將以宿主上直接寫文件到VM內部為例講解為何要注入以及如何實現

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

小慢哥的原創文章,歡迎轉載


目錄

? 為什么要“注入”到VM內部

? 如何實現“注入”

? Step1. 為VM配置channel

? Step2. 部署qemu-ga

? Step3. 注入操作說明

? Step4. Base64計算

? Step5. 開始注入

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

? 附2. 配置多個channel

? 參考文檔


為什么要“注入”到VM內部

原因很簡單:在VM外部無法實現,只能進入到VM內來實現

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

對于基于KVM的虛擬機來說,通常存在如下需求:

? 在線修改密碼

? 在線增加公鑰

? 在線采集性能(如cpu使用率、負載、內存使用量等性能指標)

? 其他各種在線功能

上述這些場景的共性:僅在VM外部是無法實現的。因此就有了多種解決方案,但無論哪種解決方案都要同時滿足以下2點才能實現:

? 通道:在VM內部與外部(宿主)之間打開一個通道,可以進行數據交互

? agent:在VM內部種下一個agent,用于接收外部的指令并反饋結果

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


如何實現“注入”

第一步,打開通道

有2類方法:

? 走網絡:會復雜一些,需要提前預插入一張管理網卡,或者利用已有網卡+特殊的路由來確保數據能走出去,這帶來了較為復雜的網絡拓撲

? 走設備:簡單很多,只需在VM內部和宿主之間建立一個設備通道即可。比如為KVM虛擬機增加一個字符設備,并在宿主上映射為一個socket文件。字符設備與socket之間形成了一個channel,通過該channel就可以進行內外數據互通

“走網絡”不是本文想要介紹的,接下來所有內容均為“走設備”

第二步,啟動agent

在虛擬機里啟動一個agent,實時讀取字符設備,實現與宿主的數據交互。

在channel中發送與接收什么樣的數據,是可以自己定義的,也可以使用KVM官方實現的解決方案,稱為Qemu Guest Agent,簡稱qemu-ga。它包含2方面:

? channel中傳送數據的協議定義:基于JSON的格式

? VM內的agent:啟動一個名叫qemu-ga的守護進程,該進程將從字符設備里獲取傳進來的json指令,然后根據指令執行相關命令,并將結果通過字符設備返回給宿主

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

關于qemu-ga的配置與使用,筆者之前已寫過一篇文章《基于QMP實現對qemu虛擬機進行交互》,詳細介紹其工作原理及基本使用方法,這里附上地址

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

由于本文主題是“注入寫文件”,因此接下來將重點闡述如何寫文件,不過也會將qemu-ga的部署與啟用方法再次貼出。


Step1. 為VM配置channel

通過libvirt啟動的虛擬機,可以在XML里增加一段配置

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

注意:上面這段配置要放在<devices>段落中


Step2. 部署qemu-ga

1?? 安裝qemu-ga

在VM內部安裝并啟動qemu-ga,linux和windows均支持qemu-ga,許多linux發行商都會提供自己的qemu-ga,比如rhel/centos、fedora、ubuntu、opensuse都有提供編譯好的qemu-ga,可以直接下載使用。而windows系統需要下載virtio-win,其中有包含一些virtio的win驅動以及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安裝包如圖所示

2?? 啟動qemu-ga

以centos7為例

# 啟動qemu-ga守護進程 systemctl start qemu-guest-agent# 加入開機啟動 systemctl enable qemu-guest-agent

啟動后通過systemctl status qemu-guest-agent應當能看到進程已啟動,如圖所示

注意:有的qemu-ga會拒絕部分指令,這是因為qemu-ga的配置文件里將某些指令給禁用了,比如在centos7里,配置文件為/etc/sysconfig/qemu-ga

# 修改/etc/sysconfig/qemu-ga,將以下內容注釋掉,或直接刪掉 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?? 測試qemu-ga

在VM的宿主機上,執行以下命令:

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

如果返回以下內容則表示qemu-ga可用

{"return":{}}

接下來查看下qemu-ga支持哪些指令

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

應該會看到支持很多命令,由于接下來做的實驗需要用到如下命令,因此請先確認是否均支持

? guest-exec:執行命令(異步操作)

? guest-exec-status:查看執行命令的結果

? guest-file-open:打開文件,獲得句柄

? guest-file-write:寫文件(傳遞base64)

? guest-file-close:關閉文件


Step3. 注入操作說明

實驗目標:將RSA的公鑰內容寫入到/root/.ssh/authorized_keys

這涉及到如下3個步驟:

1. 創建/root/.ssh目錄且權限為700

2. 創建/root/.ssh/authorized_keys文件且權限為600

3. 將RSA公鑰文本進行Base64編碼(guest-file-write不支持明文,僅支持base64),并將編碼后的內容寫入/root/.ssh/authorized_keys


Step4. Base64計算

這里先假設RSA公鑰內容為

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

進行Base64編碼

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

這樣就獲得了base64編碼內容

c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCQVFEVktvZzA0cGJiTGFhcmpicHZLN0NSYUl1VXdXeGVoSklIOHRxdFgvb1Y0R1lONVdHWVBGYTF0enNkNFZ5b2JsbTRMZVBYNzlXZUk0a0ZIZ1NiSDVQNkg5aThsM0tDVEZISGVKVC9nMFA1NS9jNjB5RGIzbzZscXBXdTlJS0UzSTRsc1RwMDVZL1cwS3M3VzI3Sm5kcjE2Mm5pMFlidGhnZDlDUXlvaWJ1cm9oMzVFQ2lQR3dXVU9CVko0SUVwU3BPWmREVUpMUy92VnVTUWd2RUgwZnEvRzFEUDNTT3lSK0ROYXNKMDBtd29uZmFVS0haWG1XQWxIOG1hck53UG1XYXB5VFNRd0NGS0toMUh3bEpFV0VUVjRmWXVGd20zaWVubmI4Y1gxeTRhWDlBSlduQTJjYzM1cnB1bGl2TWlqZVhzL3NzVDVpRmxqWFhHWXpta1g2blIgcm9vdEBsb2NhbGhvc3QubG9jYWxkb21haW4K

Step5. 開始注入

1?? 創建/root/.ssh目錄且權限為700

# mkdir /root/.ssh virsh qemu-agent-command ${DOMAIN} '{"execute":"guest-exec","arguments":{"path":"mkdir","arg":["-p","/root/.ssh"],"capture-output":true}}'# 假設上一步返回{"return":{"pid":911}},接下來查看結果(通常可忽略) virsh qemu-agent-command ${DOMAIN} '{"execute":"guest-exec-status","arguments":{"pid":911}}' # chmod 700 /root/.ssh,此行其實可不執行,因為上面創建目錄后就是700,但為了防止權限不正確導致無法使用,這里還是再刷一次700比較穩妥 virsh qemu-agent-command ${DOMAIN} '{"execute":"guest-exec","arguments":{"path":"chmod","arg":["700","/root/.ssh"],"capture-output":true}}' # 假設上一步返回{"return":{"pid":912}},接下來查看結果(通常可忽略) virsh qemu-agent-command ${DOMAIN} '{"execute":"guest-exec-status","arguments":{"pid":912}}'

2?? 創建/root/.ssh/authorized_keys文件且權限為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}}'# 假設上一步返回{"return":{"pid":913}},接下來查看結果(通常可忽略) virsh qemu-agent-command ${DOMAIN} '{"execute":"guest-exec-status","arguments":{"pid":913}}'# chmod 600 /root/.ssh/authorized_keys,此行其實可不執行,因為上面創建文件后就是600,但為了防止權限不正確導致無法使用,這里還是再刷一次600比較穩妥 virsh qemu-agent-command ${DOMAIN} '{"execute":"guest-exec","arguments":{"path":"chmod","arg":["600","/root/.ssh/authorized_keys"],"capture-output":true}}'# 假設上一步返回{"return":{"pid":914}},接下來查看結果(通常可忽略) virsh qemu-agent-command ${DOMAIN} '{"execute":"guest-exec-status","arguments":{"pid":914}}'

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

# 打開文件(以讀寫方式打開),獲得句柄 virsh qemu-agent-command ${DOMAIN} '{"execute":"guest-file-open", "arguments":{"path":"/root/.ssh/authorized_keys","mode":"w+"}}'# 寫文件,假設上一步返回{"return":1000},1000就是句柄 virsh qemu-agent-command ${DOMAIN} '{"execute":"guest-file-write", "arguments":{"handle":1000,"buf-b64":"c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCQVFEVktvZzA0cGJiTGFhcmpicHZLN0NSYUl1VXdXeGVoSklIOHRxdFgvb1Y0R1lONVdHWVBGYTF0enNkNFZ5b2JsbTRMZVBYNzlXZUk0a0ZIZ1NiSDVQNkg5aThsM0tDVEZISGVKVC9nMFA1NS9jNjB5RGIzbzZscXBXdTlJS0UzSTRsc1RwMDVZL1cwS3M3VzI3Sm5kcjE2Mm5pMFlidGhnZDlDUXlvaWJ1cm9oMzVFQ2lQR3dXVU9CVko0SUVwU3BPWmREVUpMUy92VnVTUWd2RUgwZnEvRzFEUDNTT3lSK0ROYXNKMDBtd29uZmFVS0haWG1XQWxIOG1hck53UG1XYXB5VFNRd0NGS0toMUh3bEpFV0VUVjRmWXVGd20zaWVubmI4Y1gxeTRhWDlBSlduQTJjYzM1cnB1bGl2TWlqZVhzL3NzVDVpRmxqWFhHWXpta1g2blIgcm9vdEBsb2NhbGhvc3QubG9jYWxkb21haW4K"}}'# 關閉文件 virsh qemu-agent-command ${DOMAIN} '{"execute":"guest-file-close", "arguments":{"handle":1000}}'

查看效果:此時到VM里查看/root/.ssh/authorized_keys,應該能看到新增加的一行


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

不同的qemu-ga版本、不同的操作系統,支持的指令都會有所差異,下面是從官網上看到的當前所有參數

? 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

具體使用方法,請參考官網文檔

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

附2. 配置多個channel

1?? 可以在XML里配置多個channel,這樣就可以創建多個設備通道

<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里要啟動2個qemu-ga守護進程,可以將原有的service文件拷貝一份出來進行修改

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

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

3?? 啟動服務

systemctl start qemu-guest-agent-1

參考文檔

# qemu-ga介紹與使用:QEMU Guest Agent # qemu-ga完整參數:https://qemu.weilnetz.de/doc/qemu-ga-ref.html # 筆者另一篇相關文章《基于QMP實現對qemu虛擬機進行交互》:https://www.toutiao.com/i6646012291059810823/

總結

以上是生活随笔為你收集整理的kvm虚拟机_通过QEMU-GuestAgent实现从外部注入写文件到KVM虚拟机内部的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。