編集: WIP: 以下に説明する失敗の主な原因は、ホスト TAP インターフェイスを適切なタイミングで起動しなかったためです。QEMU にタップ デバイスの作成を処理させると、すべてが期待どおりに動作します。この失敗についてさらに詳しく調査し、問題がわかったらより明確な説明を提供します。ヒントを提供してくれた @anx に感謝します。
目標:dnsmasq
ホスト上で実行されている別の QEMU VM からのネットブートを処理するホスト QEMU VM 内でを実行します。
dnsmasq VM をゲートウェイのように動作させ、1 つの NIC をアップストリーム WAN インターフェイスとして、アップストリーム DHCP サーバーと、もう 1 つのインターフェイスをプライベート LAN インターフェイスにして、他の VM を「接続」し、このプライベート LAN インターフェイスでリッスンしている dnsmasq からネットブートするようにしたいと思います。
まず、VM同士が通信できるようにするために、ホスト上に独自のブリッジを作成します。
ip link add name vivianbr0 type bridge
ip link set vivianbr0 up
VMがホストブリッジを介して互いに通信するには、ゲートウェイVMのプライベートLANインターフェース用とプライベートVMの単一ネットワークインターフェース用の2つのタップデバイスが必要です。
ip tuntap add mode tap tap0 user cturner
ip tuntap add mode tap tap1 user cturner
ip link set tap0 up
ip link set tap1 up
ip link set tap0 master vivianbr0
ip link set tap1 master vivianbr0
ゲートウェイVMでは、テスト目的でArch Linux ISOを使用しています。VMは2つのNICで起動されるため、
qemu-system-x86_64 \
-drive file=arch-disk.qcow2,if=none,id=nvm \
-device nvme,serial=deadbeef,drive=nvm \
-cdrom archlinux-2021.09.01-x86_64.iso \
-boot d \
-device virtio-net-pci,romfile=,netdev=net0,mac="DE:AD:BE:EF:00:11" \
-device virtio-net-pci,romfile=,netdev=net1,mac="DE:AD:BE:EF:00:12" \
`# Simulate the plugged in "upstream" cable with user-mode networking` \
-netdev user,id=net0,hostfwd=tcp::60022-:22,hostfwd=tcp::8080-:80,hostfwd=tcp::8081-:8000,hostfwd=tcp::2375-:2375 \
`# And now the unplugged one with, with TAP networks` \
-netdev tap,id=net1,ifname=tap0,script=no,downscript=no \
-net bridge,br=vivianbr0 \
-m 4G \
-enable-kvm
このマシンが起動すると、ブリッジ構成に次の内容が表示されます。
brctl show vivianbr0
bridge name bridge id STP enabled interfaces
vivianbr0 8000.46954a1ad851 no tap0
tap1
tap2
tap2
QEMU によって作成されたものだと思います...
このVM内には2つのifaceがあります。MAC ens4
DE:AD:BE:EF:00:11とens5
MAC DE:AD:BE:EF:00:12です。このVM内でdnsmasq
、
ip addr add 10.42.0.1/24 dev ens5
dnsmasq -d --dhcp-range=10.42.0.10,10.42.0.100 --dhcp-script=/bin/echo --enable-tftp=ens5 --interface=ens5
これはエラーなしで開始されます。
次に、ホスト上で次のように起動した別のVMをネットブートしてみます。
qemu-system-x86_64 \
-machine pc-q35-6.0,accel=kvm \
-m 1024 -smp 2,sockets=2,cores=1,threads=1 \
-netdev tap,id=net0,ifname=tap1,script=no,downscript=no \
-device virtio-net-pci,netdev=net0,bootindex=1,mac=DE:AD:BE:EF:00:13 \
-net bridge,br=vivianbr0 \
-enable-kvm \
-vga virtio
しかし、起動に失敗します。vivianbr0
使用状況を監視しtcpdump
、DHCP要求を確認できますが、応答はなく、最初のVM内で実行されているdnsmasqには何も届きません。
tcpdump -i vivianbr0 -nN
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on vivianbr0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
12:21:39.585229 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from de:ad:be:ef:00:13, length 397
12:21:40.587741 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from de:ad:be:ef:00:13, length 397
12:21:40.700038 IP6 fe80::6ce2:2aff:fe94:ba48.5353 > ff02::fb.5353: 0 [7q] PTR (QM)? _nfs._tcp.local. PTR (QM)? _ftp._tcp.local. PTR (QM)? _webdav._tcp.local. PTR (QM)? _webdavs._tcp.local. PTR (QM)? _sftp-ssh._tcp.local. PTR (QM)? _smb._tcp.local. PTR (QM)? _afpovertcp._tcp.local. (118)
12:21:42.619968 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from de:ad:be:ef:00:13, length 397
12:21:46.684448 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from de:ad:be:ef:00:13, length 397
12:22:30.609555 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from de:ad:be:ef:00:12, length 289
12:23:33.796148 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from de:ad:be:ef:00:12, length 289
12:24:38.673364 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from de:ad:be:ef:00:12, length 289
de:ad:be:ef:00:13
奇妙なことに、 (ネットブートVMのMACアドレス)からのBOOTPリクエストが見られます。そしてから de:ad:be:ef:00:12
(ゲートウェイ VM のプライベート NIC)、何かが誤って構成されていることを示しています。
どうすればこれを機能させることができますか?
答え1
2人のゲストのための手順は問題ありません。私はあなたの設定を再現しましたアドレスをリースするまでは、dnsmasq を実行している 1 つの VM から、dhcp クライアントを実行している 1 つの VM に IP を割り当てることができました。
以下を確認してください:
- 未接続のタップデバイスを起動できません
- ホストの出力
DOWN
の状態から見える(またはと言うべき)ip a l
UNKNOWN
UP
- qemuにタップデバイスを作成させると、
qemu-bridge-helper
それが起動します - script=を使用する場合は、そこでデバイスを起動します
- それ以外の場合は、
ip link set tapN up
VMの起動後にしばらく待つ必要があります
- qemuにタップデバイスを作成させると、
- ホストの出力
- MACアドレスは一意である必要があります
- ゲストの
ether
アドレスに表示されるip a l
- 学習した(非ホスト)MACをリスト
brctl showmacs br0
します。二ゼロ以外のエージングタイマーを持つエントリ
- ゲストの
- iptables経由でパケットをドロップする
- モジュールがロードされている
/proc/sys/net/bridge/bridge-nf-call*
かどうかを確認しますbr_netfilter
iptables -A FORWARD -j LOG --log-prefix "forward dropped"
IPv4の場合は、 FORWARDテーブルのドロップ前やDROPポリシーの前などのログルールを追加します。- 無視する
/sys/class/net/br*/bridge/nf_call_*
(なぜこれらのできるフィルタリングがオンのときはオフになります)
- モジュールがロードされている
テスト中に見つけたその他の注目すべき点:
- Qemu は
vnet_hdr
私のタップ デバイスにオプションを追加しました。これは妥当なようですし、必要に応じて qemu コマンドラインで無効にすることもできます。 - 時々、ブリッジの (スコープ リンク) ルートが失われることがありました。それがどのようにして起こるのかはまだわかりません。
タップ デバイスにバインドすることでテストを簡素化する試みについて。
dnsmasqはQEMU VM内で実行されます
私の知る限り、永続的なタップ デバイスは実際に接続されるまで使用できません。したがって、意味のあるテストを行えるのは、次のいずれかの完全なセットアップのみです。
- ホスト上で dnsmasq を実行しますか?
- それをブリッジデバイスに接続します
- または、VM 内で dnsmasq を実行しますか?
- それぞれのネットワークインターフェースに接続します内部そのVM
--インターフェース=tap0
ヒント: --bind-interfaces
dnsmasq に、他のインターフェースからのトラフィックを単に破棄するのではなく、実際にバインドを試行するように切り替えて、使用できない設定で起動したときに冗長なメッセージを表示して終了するように指示するために使用します。