快轉到主要內容

將Linux的QEMU/KVM網路設定為橋接模式,讓外網可以連線到虛擬機

分類   資訊科技 虛擬機與容器技術
標籤   QEMU-KVM Libvirt
🗓️ 民國113年 甲辰年
✍ 切換正體/簡體字
目錄

Set up bridged networking with libvirt and QEMU/KVM.

1. 問題點
#

  • 宿主機:Ubuntu 24.04 (核心版本6.5.0)
  • 虛擬機:Windows 11
  • 網路架構:Ubuntu電腦透過乙太網路線直接連到數據機(Modem),數據機還有開Wifi。

使用Virt Manager預設NAT網路下,Windows虛擬機的SMB服務無法被同Wifi網路下的其他裝置存取。所以我要建立一個新的虛擬網路橋接器,讓Windows虛擬機裡面系統跑的SMB服務可以從外部網路存取。

為何要建立新的橋接器?

在你安裝Virt Manager之後,Libvirt會在Linux新增一個叫做「virbr0」的虛擬橋接器(virtual bridge),負責處理虛擬機的網路連線。virbr0本身是作為NAT,在虛擬機開機後,Libvirrt會再新增一個vnet的界面連到virbr0,此時所有虛擬機位於該虛擬NAT之後,虛擬機可連線到外部網路,宿主機能連線到虛擬機,各個虛擬機之間也可以互相連線,但是無法從外部網路連線到虛擬機。

要讓外部網路連線到躲在虛擬NAT背後的虛擬機,是可以透過調整iptables forward規則的方式達成啦,但是規則設定上很麻煩,不如另外弄個完整的橋接器吧,讓它使用真正的橋接網路模式(bridged networking)。

Linux的橋接網路可以在多個裝置之間轉送封包。我們會建立一個新的虛擬橋接器「br0」,並把宿主機的實體乙太網路界面連上該橋接器,如此一來就能從外部網路存取虛擬機服務了。

且在新增br0虛擬橋接器之後,你還是可以讓虛擬機使用原本的virbr0連線。

建議不要使用Wifi無線網路裝置橋接,否則會多一道建立hostapd的手續。請在有乙太網路的狀態下建立橋接器。

2. 設定Libvirt
#

  1. 請先 安裝QEMU/KVM與Virt Manager

  2. 用指令列出所有虛擬網路界面

sudo virsh net-list --all
  1. 列表應該會看到有名為default的網路界面,裝置為virbr0,此為Libvirt自動建立,這就是上面說的NAT模式的虛擬橋接器。
# 範例輸出
 Name              State    Autostart   Persistent
----------------------------------------------------
 default           active   yes         yes

3. 用NetworkManager建立虛擬橋接器
#

很多工具都能建立橋接器,比如NetworkManager、Netplan、iproute2、Network Bridge Utilities,還有KDE和GNOME的圖形界面。

鑑於很多Linux發行版都用NetworkManager管網路,我們就用附屬的nmcli工具來建立橋接器吧。

  1. 透過sudo nmcli device status指令得知,乙太網路連線的裝置(Device)名稱為enp0s2,網路連線名稱(Name)為乙太網路連線1
# 範例輸出

NAME                      UUID                                  TYPE      DEVICE
乙太網路連線1             b32df45e-3d34-11ef-8781-ebb418880514  ethernet  enp2s0
  1. 透過ip addr得知我的區域IP網段為192.168。
# 範例輸出
2: enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether b0:6e:bf:ca:68:94 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.102/24 brd 192.168.1.255 scope global dynamic noprefixroute enp2s0
  1. 新建一個叫做br0的橋接器,關閉STP
sudo nmcli connection add type bridge ifname br0 stp no
  1. enp2s0設定為br0的bridge-slave
sudo nmcli connection add type bridge-slave ifname enp2s0 master br0
  1. 關閉目前的乙太網路連線。
sudo nmcli connection down "乙太網路連線1"
  1. 確保它不會自動重新連線
sudo nmcli connection modify "乙太網路連線1" connection.autoconnect no
  1. 啟用剛剛新建的橋接器
sudo nmcli connection up bridge-br0

sudo nmcli connection up bridge-slave-enp2s0
  1. 用指令sudo nmcli connection show --active檢視橋接器狀態,確認連線名稱(Name)為bridge-br0
# 範例輸出
NAME                 UUID                                  TYPE      DEVICE
bridge-br0           50b8e41e-3d34-11ef-a6b9-13326122fb1e  bridge    br0
bridge-slave-enp2s0  52dd08d8-3d34-11ef-8017-8fce9b54d32b  ethernet  enp2s0
  1. 接著分配固定IP給bridge-br0
sudo nmcli connection modify "bridge-br0" ipv4.addresses "192.168.1.101/24"
  1. 然後設定bridge-br0使用Google的DNS
sudo nmcli connection modify "bridge-br0" ipv4.dns "8.8.8.8"
  1. 重新啟用連線
nmcli connection up bridge-br0
  1. 使用指令sudo ip addr show br0確認連線狀態
# 範例輸出
11: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 46:d0:69:ba:ce:f5 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.102/24 brd 192.168.1.255 scope global noprefixroute br0
       valid_lft forever preferred_lft forever

4. QEMU/KVM虛擬機端的設定
#

  1. (選擇性)使用sysctl關閉Linux核心的Netfilter功能,提昇虛擬機網路效能
sudo mkdir /etc/sysctl.d

sudo bash -c 'cat << EOF > /etc/sysctl.d/99-netfilter-bridge.conf
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0
EOF'
  1. 載入br_netfilter核心模組,並設定開機自動載入
sudo modprobe br_netfilter

echo "br_netfilter" | sudo tee -a /etc/modules-load.d/br_netfilter.conf
  1. 套用設定
sudo sysctl -p /etc/sysctl.d/99-netfilter-bridge.conf
  1. 新建一個虛擬網路定義檔bridged-network.xml
cat << EOF > ~/bridged-network.xml
<network>
   <name>bridged-network</name>
   <forward mode="bridge" />
   <bridge name="br0" />
</network>
EOF
  1. 用virsh指令,按照xml內容新增一個叫做bridge-newtork的網路
sudo virsh net-define ~/bridged-network.xml
  1. 設定開機自動啟動bridged-network
sudo virsh net-start bridged-network
sudo virsh net-autostart bridged-network
  1. 開啟Virt Manager,調整虛擬機網路,選取bridged-network

  2. 開機後Windows應該會自動連上網路,並取得一個區域IP。自此之後,Windows的SMB服務就能讓同一Wifi下的其他裝置存取了。

  3. 如果虛擬機本身需要固定IP,請在虛擬機內部設定。Windows開啟「網路和網際網路設定」調整,Linux則是使用nmcli指令修改。

參考資料
#

相關文章

Linux KVM啟用巢狀虛擬化,在虛擬機裡面跑虛擬機
分類   資訊科技 虛擬機與容器技術
標籤   Libvirt QEMU-KVM Linux
Spice Guest Tools用法,QEMU/KVM虛擬機自動縮放解析度、共享資料夾
分類   資訊科技 虛擬機與容器技術
標籤   Libvirt QEMU-KVM
Ubuntu安裝QEMU/KVM和Virt Manager虛擬機管理員
分類   資訊科技 虛擬機與容器技術
標籤   Libvirt Ubuntu QEMU-KVM

留言板

此處提供二種留言板。點選按鈕,選擇您覺得方便的留言板。要討論程式碼請用Giscus,匿名討論請用Disqus。

這是Giscus留言板,需要Github帳號才能留言。支援markdown語法,若要上傳圖片請貼Imgur或Postimages。您的留言會在Github Discussions向所有人公開。

這是Disqus留言板,您可能會看到Disqus強制投放的廣告。有時留言可能會被系統判定需審核,導致延遲顯示,請見諒。若要上傳圖片請貼Imgur或Postimages。