EDIT: WIP: Основная причина сбоев, описанных ниже, заключается в том, что я не поднял интерфейсы TAP хоста в нужное время. Если я позволю QEMU обрабатывать создание устройств TAP, все будет работать так, как и ожидалось. Я изучу сбой более подробно и предоставлю более четкое объяснение проблемы, когда она у меня появится. Спасибо @anx за советы!
Цель: запустить dnsmasq
внутри хоста виртуальную машину QEMU, которая обслуживает сетевую загрузку с другой виртуальной машины QEMU, работающей на хосте.
Я хотел бы, чтобы виртуальная машина dnsmasq действовала как шлюз, с одной сетевой картой в качестве интерфейса WAN верхнего уровня, с сервером DHCP верхнего уровня, а другой интерфейс был бы частным интерфейсом LAN, к которому были бы «подключены» другие виртуальные машины, и выполняла бы сетевую загрузку с dnsmasq, прослушивающего этот частный интерфейс LAN.
Во-первых, чтобы позволить виртуальным машинам общаться друг с другом, я создаю собственный мост на хосте,
ip link add name vivianbr0 type bridge
ip link set vivianbr0 up
Чтобы виртуальные машины могли взаимодействовать друг с другом через хост-мост, мне понадобятся два ответвителя: один для интерфейса частной локальной сети на шлюзовой виртуальной машине, а другой — для единого сетевого интерфейса частной виртуальной машины.
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
Для шлюзовой виртуальной машины я использую Arch Linux ISO для целей тестирования, виртуальная машина загружается с двух сетевых карт, таким образом,
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...
Внутри этой виртуальной машины есть два интерфейса. ens4
с MAC DE:AD:BE:EF:00:11 и ens5
с MAC DE:AD:BE:EF:00:12. Внутри этой виртуальной машины я начинаю 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
Начинается без ошибок.
Теперь я пытаюсь загрузить по сети другую виртуальную машину, запущенную на хосте таким образом,
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, но нет ответов, ничего не доходит до 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
Странно, но я вижу запросы BOOTP отde:ad:be:ef:00:13
(MAC-адрес виртуальной машины сетевой загрузки)и из de:ad:be:ef:00:12
(частная сетевая карта шлюзовой виртуальной машины), что указывает на наличие серьезной ошибки в настройках.
Как мне это реализовать?
решение1
Ваши действия для двух гостей вполне приемлемы, я только что повторил вашу установку.вплоть до момента аренды адресов. Я мог бы раздавать IP-адреса с одной виртуальной машины, на которой запущен dnsmasq, на другую виртуальную машину, на которой запущен клиент dhcp.
Проверьте это:
- невозможно вызвать неприсоединенные устройства для подключения
- видно из
DOWN
состояния вip a l
выводе хоста (следует указатьUNKNOWN
илиUP
)- если вы позволите qemu создать устройство tap, оно
qemu-bridge-helper
будет запущено - если вы используете скрипт=, вызовите устройство там
- в противном случае вам придется
ip link set tapN up
некоторое время после запуска виртуальной машины
- если вы позволите qemu создать устройство tap, оно
- видно из
- MAC-адреса должны быть уникальными.
- виден в
ether
адресе вip a l
гостях - список изученных (не хостовых) mac, например
brctl showmacs br0
должен иметьдвазаписи с ненулевым таймером старения
- виден в
- сброс пакетов через iptables
- проверьте
/proc/sys/net/bridge/bridge-nf-call*
иbr_netfilter
загружен ли модуль - добавьте правило ведения журнала, для IPv4 что-то вроде
iptables -A FORWARD -j LOG --log-prefix "forward dropped"
before dropping или перед политикой DROP в таблице FORWARD - игнорировать
/sys/class/net/br*/bridge/nf_call_*
(я не знаю, почему этиможетбыть выключенным при включенной фильтрации)
- проверьте
Другие примечательные моменты, которые я обнаружил во время тестирования:
- Qemu добавил эту
vnet_hdr
опцию на моих устройствах tap. Это кажется разумным и могло быть отключено в командной строке qemu, если бы это было необходимо. - Иногда мой (ссылка на область) маршрут для моста пропадал. Мне еще предстоит выяснить, как это вообще могло произойти.
О вашей попытке упростить тестирование путем привязки к устройству tap..
dnsmasq будет работать внутри виртуальной машины QEMU
Насколько мне известно, устройства постоянного подключения не могут использоваться до фактического подключения. Поэтому вы можете осмысленно протестировать только одну из следующих полных установок:
- Хотите запустить dnsmasq на хосте?
- затем прикрепите его к мостовому устройству
- или вы хотите запустить dnsmasq внутри виртуальной машины?
- затем подключите его к соответствующему сетевому интерфейсувнутричто ВМ
--interface=tap0
Совет: используйте, --bind-interfaces
чтобы указать dnsmasq переключиться с простого отбрасывания трафика с других интерфейсов на фактическую попытку привязки, тем самым завершая работу со строгим сообщением при запуске с непригодными для использования настройками.