Работа с сетью в qemu

Работа с сетью в qemu достаточна проста, но зачастую вызывает множество вопросов у начинающих. Несмотря на то, что в сети существует ряд полезных руководств, в процессе решения прикладных задач возникают мелкие, но неприятные проблемы. В данной статье, я постараюсь постепенно собирать ряд рецептов и рекомендаций по настройке сети в qemu. Со стороны читателей приветствуются замечания и дополнения.

Все примеры в статье проверены на Fedora 14, qemu 0.13.0, kvm включен.

Основы.

С самого начала надо пояснить, как создать сетевой адаптер в гостевой системе. Для этого служит опция -net с параметром nic (Network Interface Card)

-net nic[,model=<adapter_model>][,macaddr=<mac>][...]

При указании данной опции в гостевой системе появится сетевой интерефейс заданной модели, с указанным mac адресом. При отсутствии параметра model будет эмулироваться адаптер realtek. Узнать какие адаптеры поддерживаются qemu для вашей архитектуры можно при помощи следующей команды

$ qemu-kvm -net nic,model=?

После указания адаптера самое время подумать, как он будет взаимодействовать с внешним миром. Qemu предоставляет несколько различных способов сетевого поключения для гостевой системы, но прежде чем перейти к описанию некоторых из них, необходимо познакомиться с понятием vlan. Сразу хочу отметить,что к Virtual Local Area Network этот термин не имеет отношения. В терминологии qemu vlan - это виртуальный коммутатор который создается процессом qemu, на один процесс их может быть несколько штук, и различаются они по номеру. Подключить сетевой адаптер к нужному vlan можно указав номер в качестве параметра, например

-net nic,model=e1000,macaddr=00:11:22:33:44:55,vlan=0

Все что поступает на vlan передаётся другим подключенным туда интерфейсам, а весь секрет взаимодействия с хост системой и внешней сетью заключается в том, что помимо адаптера гостевой системы к vlan можно подлючить много чего ещё.

Так как же всё таки настроить работающую сеть?

Самый простой способ подключения сети в гостевой системе - использование встроенной в qemu системы сетевого обмена с хостом (user mod). Она не требует дополнительной конфигурации - если на хост-системе настроена сеть, то qemu сам позаботиться о том, чтобы запросы автоматически перенаправлялись на нужный сетевой интерфейс.

$ qemu-kvm -drive file=test/winXP -net nic,vlan=0 -net user,vlan=0

В данном случае к vlan 0 подключается с одной стороны сетевой адаптер гостевой системы, с другой стороны к этому же vlan подключается встроеннsq в qemu маршрутизатор. Гостевая система при этом получает IP адрес по DHCP (по умолчанию в диапазоне 10.0.2.0/8).


Необходимо подчернуть, что user режим работы сети включается по умолчнию, даже если не прописывать параметры конфигурации в командной строке qemu. Кроме того user режим имеет несколько полезных настроек - как всегда их можно подсмотреть в man`e.

Несмотря на свою простоту данный способ настройки сети для гостевой системы обладает рядом недостатков:

  • Медленная скорость сетевого соединения
  • Нет связи с другими виртульными машиными запущенными на данном хосте
  • Гостевая система недоступна с хост системы и с дригих машин в сети хоста.

К счастью существуют способы, позволяющие устранить эти проблемы.

Сетевое соединение между виртуальными машинами

Нижеописанный способ соединения позволяет установить связь между двумя виртуальными машинами qemu, через сетевой сокет на хост-системе. Для этого будет использоваться параметр -net socket

Сначала запустим первую машину, которая будет слушать порт 2030 по адресу 127.0.0.1

$ qemu-kvm -m 1024 -drive file=temp/win.img -net nic,macaddr=00:11:22:33:44:01,vlan=0  -net socket,vlan=0,listen=127.0.0.1:2030

Вторая запущенная виртуальная машина поключается к этому сокету (подразумевается, что машины запущены на одной хост-системе)

$ qemu-kvm -m 1024 -drive file=temp/fedora.img  -net nic,macaddr=00:11:22:33:44:02,vlan=1  -net socket,vlan=1,connect=127.0.0.1:2030  -net nic,macaddr=00:11:22:33:03,vlan=2  -net user,vlan=2

Во второй системе создается два интерфейса, один из которых подключается к первой виртуальной машине через сокет, а второй работает в user режиме (NAT встроенный в qemu и описанный выше) - благодаря этому вторая машина получает и доступ во внешнюю сеть и кроме того может обмениваться информацией с первой виртуальной машиной

Необходимо отметить, что при использовании socket механизма, сетевые настройки конечно же не раздаются автоматически. На скриншотах сетевые интерфейсы машин соединенных при помощи сокета на хост системе имеют адреса 192.168.200.1 и 192.168.200.2 (назначены руками) для Linux и Windows соответсвенно. На Linux системе также заметен и второй интерфейс eth2, который предоставляет доступ к внешней сети при помощи NAT.

Схему данной сети можно представить в следующем виде

Кроме того для связи нескольких машин друг с другом может использоваться схема UDP мультикаст сокетов, при этом сами виртуальные машины могут быть запущены на разных хостах. На этой схеме я подробно останавливаться не буду, так как сам её не использовал, а переписывать краткий мануал было бы бессмысленно.

Использование tun/tap интерфейсов для связи машин

Одним из самых распространенных способов работы с сетью для qemu является использование tap интерефейса. При запуске qemu c опцией -net tap в хост системе появляется дополнительный сетевой интерфейс tap#, который подключен к указанному vlan для запущенной виртуальной машины. Существенным недостатком данного метода является то, что для создания tap адаптера требуются права суперпользователя.

$ qemu-kvm -m 1024 -drive file=temp/fedora.img -net nic,vlan=2 -net tap,script=no,downscript=no

Теперь для соединения между хостом и гостевой системой достаточно назначить адреса для tap интерефейса и сетевого адаптера на гостевой системе.

Однако самый удобный и популярный способ работы c tap интерфейсами заключается в использовании сетевых мостов. Внимательный читатели наверно обратили внимание на параметры script и downscript в предыдущем примере. С помощью этих опций можно задать скрипты, которые будут выполняться после создания и перед удалением tap интерфейса. По умолчанию qemu использует файлы /etc/qemu-ifup и /etc/qemu-ifdown. Как правило в этих скриптах прописаны команды добавления и удаления интерфейса из сетевого моста.

Например, на хост-системе создан мост virtnet0, тогда для добавления в этот мост tap интерфейса привязанного к виртуальной машине /etc/qemu-ifup может выглядеть так

#!/bin/bash

bridge=virtnet0

ifconfig $1 0.0.0.0 promisc up
brctl addif $bridge $1

Сооветственно /etc/qeu-ifdown

#!/bin/bash

bridge=virtnet0

brctl delif $bridge $1

Первый параметр передаваемый скрипту - это имя tap адаптера, он переводится в promisc mode и добавляется в сетевой мост.

Таким образом, если запустить несколько виртаульных машин, то для каждой из них будет назначен tap интерфейс и добавлен в мост virtnet0. При этом машины могут общаться друг с другом и с хост системой (в этом случае мосту в хост системе назнаяается IP адрес).

Кроме того, можно изначально добавить в сетевой мост один из сетевых интерфейсов хост системы - тогда виртуальные машины получаею доступ во внешнюю сеть наравне с хост системой.

В сети можно найти множество различных руководств по настройке подобной конфигурации, поэтому здесь хочется отметить только несколько моментов. Если вы хотите использовать PXE загрузку (например для автоматической установки систем), то крайне рекомендую установить forward delay для моста равным 0

brctl setfd 0

Кроме того, если вы используете NetworkManager для настройки сети, то могли заметить, что он пока что не работает сетевыми мостами (Я не нашел адекватного и быстрого способа). Для решения этой проблемы можно создавать мост непосредственно в скрипте /etc/qemu-ifup

#!/bin/bash

bridge=virtnet0
ip=<bridge_IP>
netmask=<bridge_netmask>

# Create the bridge if needed
br_exsist=`brctl show | grep -c $bridge`
if [ $br_exsist -eq 0 ] ; then
brctl addbr $bridge
brctl setfd $bridge 0
ifconfig $bridge inet $ip netmask $netmask up
fi

ifconfig $1 0.0.0.0 promisc up
brctl addif $bridge $1
779