× К оглавлению На главную Об авторе

   Дата и время публикации:
Дата и время модификации:

Проблемы и решение

1. Суть проблемы

Под капотом у GNOME Boxes находится эмулятор QEMU, которая по умолчанию "эмулирует" доступ гостевых ОС (guest) простым пробором ("passes through ", он же – в virt-manager "Пользовательский режим сети") за счет использования тех же самых возможностей доступа к Internet, что и хозяйская ОС (host) . При этом эмулятор для guest по умолчанию назначает шлюзe IP: 10.0.2.2 , но не доступен со стороны host, т.к реализуемая эмулятором QEMU локальная вычислительная сеть для guest изолирована от него по умолчанию. Поэтому , кроме доступа к IP: 127.0.0.1 своего локального узла пользователи guest не имеют, ну и разве что к ограниченному числу сети Internet. Полная схема распределения адресного пространства в эмуляторе QEMU [3.2], показана на рисунке 1.1

Рисунок 1.1, взят с wiki.qemu.org

На рисунке 1.1, кроме шлюза (Gateway) доступа к хозяйской сети (Host network) показан встроенный сервер DNS с IP:10.0.2.3 и сама Guest с IP: 10.0.2.15 , а также опционально подключаемый узел SMB c IP: 10.0.2.4, что и иллюстрирует следующий рисунок 1.2

Рисунок 1.2

На рисунке 1.1, кроме шлюза (gateway) доступа к хозяйской сети (Host network) показан встроенный сервер DNS с IP:10.0.2.3 и сама guest с IP: 10.0.2.15 , а также опционально подключаемый узел SMB с IP: 10.0.2.4. Что и иллюстрирует следующий рисунок 1.2

Как показано на рисунке 1.2, результат вывода сообщений netlink в guest команды ip -ts monitor, которая, в данном случае, выводит нам интересующую информацию к каким IP-адресам эмулятора производится обращение guest. В данном случае, к DNS серверу c IP:10.0.2.3 и шлюзу с IP:10.0.2.2. При этом, все попытки получить какую-либо активность на интерфейсах host c использованием той же ip -ts monitor потерпели неудачу.

Поэтому, чтобы обеспечить доступ к host из guest, можно воспользоваться самым простым решением использовать virbr0, настраиваемый с помощью программных средств virt-manager, но как мне кажется более полнофункциональным и интересным решением будет использовать программный сетевой интерфейс TAP, который обеспечивает на уровне ядра Linux сопряжения c канальным уровнем модели OSI [3.4], оперируя с кадрами Ethernet[3.3]

2. Решение

2.1 Создание сетевого интерфейса TAP

На стороне host в консоле набиваем небольшой скрипт gboxes-tapdev-up.sh, содержимое которого показано в листинге 2.1.1

Дамп 1.1

#!/bin/sh  
TAP="tap2" 
VIRTBR="virbr1"
UID=`id -u`
sudo $TUNCTL -u $UID -t $TAP 2>&1
        if [ $? -eq 0 ] ; then 
            sudo ip addr add 192.168.2.1/32 broadcast 192.168.2.255 dev $TAP
            if [ $? -eq 0 ] ; then
               sudo ip link set dev $TAP up
               if [ $? -eq 0 ] ; then
                  sudo ip route add to 192.168.3.1 dev $TAP
                  if [ $? -eq 0 ] ; then
                     sudo brctl addif $VIRTBR $TAP
                    echo "Success."
                    exit 0  
                  fi 
                  echo "Failure." 
                  exit 1
               fi
            fi
        fi

Который создает с использованием команды tunctl сетевой интерфейс tap2, присваивает IP: 192.168.2.1, поднимает созданный TUN/TAP интерфейс, подключает к внутри сетевому коммутатору, выполняющий gataway, и устанавливает маршрут к шлюзу гостевого узла

В роли шлюза с гостевым узлом выступает внутри сетевой, программный коммутатор, имеющий адрес IP:192.168.2.1. Наличие же TUN/TAP интерфейса позволит другим сетям использовать его в установке маршрута.

В роли шлюза с гостевым узлом выступает внутри сетевой коммутатор, имеющий адрес 192.168.2.1, а сопряженное с ним виртуальное сетевой интерфейс TUN/TAP позволит другим сетям обеспечивать доступ через виртуальную сеть к guest. Так, например, как показано в том же листинге 2.1.1 устанавливается IP:192.168.3.1/32 на host и играющий роль шлюза уже с сетью IP:192.168.3.0/24

2.2 Настройка межсетевой ретрансляции адреса

Производить не требуется, т.к. будет создана автоматически при создании сети командой net-create в virsh, результат установки межсетевой ретрансляции адреса показан в дампе 2.2.1

Дамп 2.1.1

$ sudo iptables --list
[sudo] пароль для user: 
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
LIBVIRT_INP  all  --  anywhere             anywhere            

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
LIBVIRT_FWX  all  --  anywhere             anywhere            
LIBVIRT_FWI  all  --  anywhere             anywhere            
LIBVIRT_FWO  all  --  anywhere             anywhere            

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
LIBVIRT_OUT  all  --  anywhere             anywhere            

Chain LIBVIRT_FWI (1 references)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             192.168.2.0/24      
REJECT     all  --  anywhere             anywhere             reject-with icmp-port-unreachable

Chain LIBVIRT_FWO (1 references)
target     prot opt source               destination         
ACCEPT     all  --  192.168.2.0/24       anywhere            
REJECT     all  --  anywhere             anywhere             reject-with icmp-port-unreachable

Chain LIBVIRT_FWX (1 references)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            

Chain LIBVIRT_INP (1 references)
target     prot opt source               destination         
ACCEPT     udp  --  anywhere             anywhere             udp dpt:domain
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:domain
ACCEPT     udp  --  anywhere             anywhere             udp dpt:bootps
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:67

Chain LIBVIRT_OUT (1 references)
target     prot opt source               destination         
ACCEPT     udp  --  anywhere             anywhere             udp dpt:domain
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:domain
ACCEPT     udp  --  anywhere             anywhere             udp dpt:bootpc
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:68

2.3 Настройка Gnome-boxes

Для настройки доступа host к guest в gnome-boxes необходимо остановить гостевую ОС, если она запущена, и открыть её свойства: кликнуть правой кнопки на значке гостевой машины в gnome-boxes. Затем, в открывшемся диалоге свойств guest выбрать раздел система и открыть редактор XML, который показан на рисунке 2.3.1

Рисунок 2.3.1

Так как основная конфигурация в формате XML хранится в двух директориях: основная – в $HOME/.config/libvirt/qemu , а выполняемая – в $HOME/.config/gnome-boxes, то как показала практика, лучше редактировать её в основной директории.

Но, это не безопасно, потому что Gnome Boxes является графическим интерфейсом, сходной с virt-manager, который может и должен быть использован (на момент написания статьи сохранение результатов редактирования конфигурации XML получался через раз) для создания, отображения доступа и управления виртуальными машинами, запускаемыми в эмуляторе QEMU и гипервизоре KVM

Поэтому несмотря на всякие смелые утверждения в сети, связка QEMU/KVM представляет собой технологию визуализации ОС GNU/Linux, управление которой легко реализуется через virt-manager, являющиеся в свою очередь частью программной надстройки Libvirt, оперирующей конфигурацией виртуальной машины в формате XML, хранимой в данном случае в директории $HOME/.config/libvirt/qemu[3.7], которую ранее назвали основной.

Особенно, virt-manager будет привычен для пользователей привыкших к диспетчеру устройств 7-x,8-x версий Windows. Пример визуализации конфигурации виртуальной машины в формате XML показан на рисунке 2.3.2

Рисунок 2.3.2

Соответственно, virt-manager имеет три режима работы виртуальной NIC, установка которых показана на рисунке 2.3.3

Рисунок 2.3.3

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

2.4 Настройка "Устройства моста"

Создаем файл xml c названием libvirt-mysubnet.xml и сетевым адресом 192.168.2.0/24, содержимое которого показан в листинге 2.4.1а

Листинг 2.4.1а

<network>
  <name>mysubnet</name>
  <bridge name='virbr1'/>
  <forward mode="route" dev="tap2"/>
  <ip address='192.168.2.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.2.11' end='192.168.2.11'/>
    </dhcp>
  </ip>
</network>
</pre>

Как показано в листинге 2.4.1, файл libvirt-mysubnet.xml содержит корневой элемент <network> виртуальной сети mysubnet, имя которой задается через подчиненный элемент <name>. Два следующих элемента <bridge> и <forward> определяют тип и режим сопряжения с физической сетью (physical network) на стороне host

Несмотря на то, что элемент <forward> является опциональным, именно его отсутствие указывает на то, что данная виртуальная изолирована от физической сети [3.15]. Поэтому этот элемент имеет всего два атрибута — 'mode' и 'dev', которые соответственно устанавливают режим работы виртуального моста и устройство на стороне host, на которое замыкается весь пробрасываемый трафик.

Так, если для атрибута 'mode' указано значение 'route' [3.16] для пробрасывания трафика будут использоваться средствами маршрутизации взамен межсетевой ретрансляции (преобразования) адреса (Network Address Translation, NAT), котрая задается значением 'nat' с использованием встроенного в ядро GNU/Linux программного межсетевого экрана iptables, как показано в листинге 2.4.1б

Листинг 2.4.1б

<network>
  <name>mysubnet</name>
  <bridge name='virbr1'/>
  <forward mode="nat" dev="tap2"/>
  <ip address='192.168.2.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.2.11' end='192.168.2.11'/>
    </dhcp>
  </ip>
</network>
</pre>

Элемент <bridge> определяет имя виртуального сетевого устройства моста на стороне host, в данном случае созданным выше 'virbr1'

И наконец, набор элементов определяющие динамически выделяемых адресов IPv4 с опционально включаемой поддержкой DHCP. Так, элемент определяет адрес , который имеет виртуальное сетевое устройства через атрибут 'address' и маску подсети 'netmask', по которой определяет IP самой виртуально подсети.

Соответственно, внутри <ip> указывается элемент <dhcp>, а внутри него – <range>, который устанавливает начальный IP (атрибут 'start') и конечный IP (атрибут 'end'). В данном случае, будет выделятся будет один – 192.168.2.11

Далее, запускаем сеть в утилите virsh , как показано в дампе 2.4.2

Дамп 2.4.2

$ sudo virsh
virsh # net-create /home/user/libvirt-mysubnet.xml
Сеть centin создана из /home/user/libvirt-mysubnet.xml

Соответственно, до выхода из virsh , рекомендую выполнить команду net-list, которой должна отобразить плоды наших усилий и выдать на консоль что-то подобное, как показано в дампе 2.4.3

Дамп 2.4.3

virsh # net-list
Имя      Состояние   Автозапуск   Постоянный
-----------------------------------------------
 mysubnet   активен     no           no

Далее, выполняем gboxes-tapdev-up.sh и проверяем, что все срослось, как показано в дампе 2.4.4

Дамп 2.4.4

$ brctl show
bridge name	bridge id		STP enabled	interfaces
virbr1		8000.52540062969d	yes		tap2
$ ip a
...
31: virbr1:  mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:62:96:9d brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.1/24 brd 192.168.2.255 scope global virbr1
       valid_lft forever preferred_lft forever
32: tap2:  mtu 1500 qdisc pfifo_fast master virbr1 state DOWN group default qlen 1000
    link/ether b2:35:63:60:f0:33 brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.10/32 brd 192.168.2.255 scope global tap2
       valid_lft forever preferred_lft forever

Нужно выполнить еще ряд действий, чтобы избежать проблемы, связанные с доступом к внутри вычислительной сети mysubnet и прекращения запуска гостевой ОС с ошибкой, детализация которой показана в дапме 2.4.5а

Дамп 2.4.5а

...
qemu-bridge-helper --br=virbr1 --fd=36: failed to communicate with bridge helper: Transport endpoint is not connected
stderr=failed to create tun device: Operation not permitted
...

Исправление ошибки, показанной в дампе 2.4.5а, заключалась в дополнительной настройки запуска вспомогательного скрипта qemu-bridge-helper, который запускается во время инициализации гостевой ОС в виртуальной среде эмулятора Qemu гипервизора KVM

Первым, понадобилось установить атрибут SETUID самому вспомогательному скрипту qemu-bridge-helper, потому что в выбранной мной ОС Debain-11, на базе которого разворачивал виртуальную среду эмулятора Qemu и гипервизора KVM под управлением программы gnome-boxes этот атрибут отсутствовал, что и показано в дапме 2.4.5б

Дамп 2.4.5б

user@home2:~$ ls -al /usr/lib/qemu/qemu-bridge-helper
-rwxr-xr-x 1 root root 279392 июл 18 16:14 /usr/lib/qemu/qemu-bridge-helper

Для установки атрибута SETUID, нужно выполнить команду chmod, как показано в дампе 2.4.5в

Дамп 2.4.5в

user@home2:~$ sudo chmod u+s /usr/lib/qemu/qemu-bridge-helper

Затем, так как эмулятор Qemu запускается в gnome-boxes с правами непривилегированного пользователя, создал файл /etc/qemu/bridge.conf, который участвует в реализации упрощенного реализации списка доступа непривеллигированных пользователей, что и показано в дапме 2.4.5г

Дамп 2.4.5г

user@home2:~$ echo "allow all" | sudo tee /etc/qemu/${USER}.conf
user@home2:~$ echo "include /etc/qemu/${USER}.conf" | sudo tee --append /etc/qemu/bridge.conf
user@home2:~$ sudo chown root:${USER} /etc/qemu/${USER}.conf
user@home2:~$ sudo chmod 640 /etc/qemu/${USER}.conf 

После чего, выполняем финальную настройку NIC в режиме "Устройства моста»" с помощью утилиты virt-manager, как показано на рисунке 2.4.6

Рисунок 2.4.6

В заключении нам остается лишь повторить эксперимент, который проводили в самом начале по команде ip -ts monitor all, результаты которого показано на рисунке 2.4.7

Рисунок 2.4.7

На котором видно, что шлюз с IP: 192.168.2.2 (устройство virbr0) и NIC (устройство tap2) на host с IP: 192.168.2.1 являются доступными. В то время как IP: 192.168.2.2, планируемый для использования встроенным DNS, остается недоступным, но это уже другая история.

3. Библиография

3.1 Unix & Linux. Allow VM in gnome boxes to access webserver on host

3.2 Qemu.Documentation/Networking

3.3 WiKipedia.Ru. TUN/TAP

3.4 WiKipedia.En. OSI

3.5 How to enable proxy arp on Linux 2.4

3.6 Gnome Boxes – A Front-end Tool For QEMU And KVM

3.7 Gul Raeez Gulshan. Virtual Networking in Linux

3.8 Cole Robinson. Easy qemu commandline passthrough with virt-xml

3.9 Qemu. Networking/Tap

3.10 Libvirt. QEMUSwitchToLibvirt

3.11 How to access the internet from a virtual machine in gnome boxes

3.12 Configuring GNOME Boxes VMs using virt-manager

3.13 Gnome. Support Bridged Networking to enable guests accessible from LAN

3.14 How to auto-scale the display in GNOME Boxes

3.15 Libvirt. VirtualNetworking

3.16 Libvirt. Network XML format