Под капотом · Виртуализация · Сеть

Сеть по умолчанию (NAT)

Пользователь включает сеть libvirt по умолчанию и подключает к ней ВМ. Для этого он вводит несколько команд:

Команда
virsh net-list --all
virsh net-start default
virsh net-autostart default
virsh attach-interface vm1 --type network --source default \
    --model virtio --config
libvirt API virNetworkCreate(), virDomainAttachDeviceFlags()

После выполнения команд у ВМ есть адрес и выход в сеть, но снаружи к ней не постучаться.

  • Команда net-start поднимает мост virbr0 и dhcp-сервер на нём;
  • Команда net-autostart включает сеть при каждой загрузке хоста;
  • Команда attach-interface добавляет ВМ интерфейс типа network;
  • Гость получает адрес по DHCP и выходит наружу через NAT.
  • пользователь 1. Пользователь включает сеть default
    virsh net-list --all
    default  active  yes

    Сеть - отдельный объект libvirt со своим XML: она существует независимо от ВМ и её можно включить без гостей.

  • libvirt 2. Демон создаёт мост и dhcp
    <bridge name='virbr0'/>
    <forward mode='nat'/>
    <ip address='192.168.122.1' netmask='255.255.255.0'>
      <dhcp><range start='192.168.122.2' end='192.168.122.254'/></dhcp>
    </ip>

    Мост здесь свой, внутренний: физический интерфейс в него не входит, поэтому гость не попадает в ЛВС напрямую.

  • сеть 3. Появляется отдельная подсеть
    ip -br addr show virbr0
    virbr0  UP  192.168.122.1/24
    dnsmasq слушает на virbr0

    ВМ видят друг друга и хост, а дальше трафик идёт через IP-стек хоста - это и есть NAT.

  • libvirt 4. Демон добавляет ВМ интерфейс
    <interface type='network'>
      <source network='default'/>
      <model type='virtio'/>
    </interface>

    type='network' означает «подключи к сети libvirt»: конкретный мост демон выберет сам из описания сети.

  • libvirt 5. Демон создаёт tap и сажает его на virbr0
    /dev/net/tun -> vnet0
    ip link set vnet0 master virbr0

    TAP - виртуальный Ethernet-порт: с одной стороны в него смотрит QEMU, с другой - мост.

  • QEMU 6. QEMU подключает сетевую карту гостя
    -netdev tap,id=hostnet0,ifname=vnet0,vhost=on
    -device virtio-net-pci,netdev=hostnet0,mac=52:54:00:…

    Гость видит virtio-карту, а vhost=on переносит часть обработки очередей в ядро хоста.

  • гость 7. Гость получает адрес
    DHCPDISCOVER -> DHCPOFFER 192.168.122.15
    default via 192.168.122.1

    Адрес выдаёт dnsmasq, запущенный libvirt; шлюз - сам мост virbr0.

  • сеть 8. Трафик уходит наружу через NAT
    источник 192.168.122.15 -> подменяется на IP хоста

    Обратно соединение находит адресата по таблице трансляций; входящие соединения без проброса портов не проходят.