Назад | Перейти на главную страницу

Подключение IPv6 потеряно на гостевом KVM через 20 минут

У меня есть сервер виртуализации KVM в Hetzner. Hetzner предоставляет мне главный IP-адрес (95.xxx.xxx.235), подсеть / 29 IPv4 (95.xxx.xxx.184 / 29) и сеть / 64 IPv6 (2a01: xxxx: xxxx: xxxx :: / 64).

KVM Guest (Debian Stretch) теряет возможность подключения по IPv6 ровно через 20 минут после перезагрузки при перезапуске сетевых служб. Даже если соединение потеряно, я могу пропинговать шлюз по умолчанию (fe80 :: 1). Подключение по IPv4 работает постоянно и без проблем.

В настоящее время интерфейс настроен как macvlan в режиме моста, и я также безуспешно пробовал VEPA и частные режимы. Также тип NIC установлен на e1000, но я тоже пробовал virtio, но безуспешно.

После потери соединения я взял дамп TCP с физического сетевого адаптера на хосте, и он показывает, что есть эхо-запросы и приходят эхо-ответы на интерфейс, но tcpdump, взятый с гостевой сетевой карты, я мог видеть только запросы, выходящие из NIC.

/ etc / network / interfaces на хосте:

auto lo
iface lo inet loopback
iface lo inet6 loopback

auto enp2s0
iface enp2s0 inet static
  address 95.xxx.xxx.235
  netmask 255.255.255.192
  gateway 95.xxx.xxx.193
  up route add -net 95.xxx.xxx.192 netmask 255.255.255.192 gw 95.xxx.xxx.193 dev enp2s0

iface enp2s0 inet6 static
  address 2a01:xxx:xxx:xxx::2
  netmask 64
  gateway fe80::1

/ etc / network / interfaces в гостевой системе:

auto lo
iface lo inet loopback
iface lo inet6 loopback

auto ens3
iface ens3 inet static
    address 95.xxx.xxx.187
    netmask 255.255.255.248
    gateway 95.xxx.xxx.185

iface ens3 inet6 static
    address 2a01:xxx:xxx:xxx::20
    netmask 64
    gateway fe80::1

# route -6 -n на хосте:

Kernel IPv6 routing table
Destination                    Next Hop                   Flag Met Ref Use If
2a01:xxxx:xxxx:xxxx::/64          ::                         U    256 8  1162 enp2s0
fe80::/64                      ::                         U    256 0     0 macvtap0
fe80::/64                      ::                         U    256 0     0 enp2s0
::/0                           fe80::1                    UG   1024 8  4534 enp2s0
::/0                           ::                         !n   -1  1 11069 lo
::1/128                        ::                         Un   0   9    81 lo
2a01:xxxx:xxxx:xxxx::/128         ::                         Un   0   1     0 lo
2a01:xxxx:xxxx:xxxx::2/128        ::                         Un   0   9    82 lo
fe80::/128                     ::                         Un   0   1     0 lo
fe80::/128                     ::                         Un   0   1     0 lo
fe80::/128                     ::                         Un   0   1     0 lo
fe80::xxxx:xxxx:xxxx:1069/128   ::                         Un   0   1     0 lo
fe80::xxxx:xxxx:xxxx:22e1/128   ::                         Un   0   1     0 lo
fe80::xxxx:xxxx:xxxx:201/128   ::                         Un   0   2    79 lo
ff00::/8                       ::                         U    256 0     0 macvtap0
ff00::/8                       ::                         U    256 0     0 enp2s0
::/0                           ::                         !n   -1  1 11069 lo

# route -6 -n для гостя:

Kernel IPv6 routing table
Destination                    Next Hop                   Flag Met Ref Use If
2a01:xxxx:xxxx:1414::/64          ::                         U    256 0     0 ens3
fe80::/64                      ::                         U    256 0     0 ens3
::/0                           fe80::1                    UG   1024 2    77 ens3
::/0                           ::                         !n   -1  1  6846 lo
::1/128                        ::                         Un   0   5   525 lo
2a01:xxxx:xxxx:xxx::20/128       ::                         Un   0   3    70 lo
fe80::xxxx:xxxx:xxx:22e1/128   ::                         Un   0   2     6 lo
ff00::/8                       ::                         U    256 0     0 ens3
::/0                           ::                         !n   -1  1  6846 lo

# ip -6 neigh на хосте:

2a01:xxxx:xxxx:xxxx::20 dev enp2s0  FAILED
fe80::1 dev enp2s0 lladdr xx:xx:xx:8d:22:06 router STALE

# ip -6 neigh on Guest:

fe80::1 dev enp2s0 lladdr xx:xx:xx:8d:22:06 router REACHABLE

Вероятно, актуальные вещи из /etc/sysctl.conf на хосте:

net.ipv4.ip_forward=1
net.ipv4.conf.enp2s0.send_redirects=0
net.ipv6.conf.all.forwarding=1

Возможно, уместные вещи из /etc/sysctl.conf в гостевой системе:

net.ipv6.conf.default.accept_ra=2
net.ipv6.conf.default.autoconf=1
net.ipv6.conf.all.accept_ra=2
net.ipv6.conf.all.autoconf=1
net.ipv6.conf.ens3.accept_ra=2
net.ipv6.conf.ens3.autoconf=1

Вероятно, соответствующий раздел гостевой libvirt-config:

<interface type='direct' trustGuestRxFilters='yes'>
  <mac address='xx:xx:xx:xx:xx:xx'/>
  <source dev='enp2s0' mode='bridge'/>
  <model type='e1000'/>
  <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>

Поскольку я боролся с этим около двух недель и читал почти все соответствующие сообщения с аналогичными проблемами, я видел, что Hetzner, по-видимому, делает какие-то подозрительные реализации IPv6. Я уже связывался с ними, но они поинтересовались, что у меня самого возникнет проблема с маршрутизацией. Это может быть правдой, поскольку через 20 минут я все еще получаю эхо-ответы на физическом NIC, даже если они не пересылаются гостю.

Итак, есть идеи от коллег по IPv6?

Обновить:

Итак, Хетцнер подтвердил мне, что сеть 2a01: xxxx: xxxx: xxxx :: / 64 маршрутизируется на локальный адрес физического интерфейса. При перезапуске сети запись NDP остается в течение 20 минут, но впоследствии удаляется, поскольку виртуальная машина не отвечает с правильным локальным адресом канала, так как у нее другой MAC-адрес.

Начинает казаться, что я не могу использовать здесь интерфейсы macvtap, но я должен создать для этого мост. Однако мне интересно, почему хост не может видеть гостя (и наоборот) с IPv6, когда IPv4 все еще работает. Думаю, это позволит мне направлять трафик прямо с основного локального адреса ссылки.

У меня была такая же проблема с сервером Hetzner, но с использованием VirtualBox вместо KVM.

Проблема:

Hetzner направляет все пакеты IPv6, имеющие любой целевой IP-адрес в вашей подсети / 64, на MAC-адрес вашего физического хоста. Это означает, что если вы отправляете эхо-запрос откуда-то из Интернета на свою виртуальную машину, у которой есть IPv6-адрес с тем же префиксом, что и у хоста, шлюз Hetzer не запрашивает соседа для поиска MAC-адреса вашей виртуальной машины, а просто пересылает ICMP пакеты к MAC вашего хоста. Это причина, по которой вы можете видеть эхо-ответы на вашем физическом хосте, но не на вашей виртуальной машине: они нацелены на MAC вашего хоста, а не на MAC виртуальной машины.

Однако, похоже, есть ошибка в реализации IPv6 Hetzner (или это может быть сделано специально, я не знаю): если виртуальная машина отправляет запрос соседу для поиска MAC-адреса шлюза (fe80 :: 1) и он использует свой глобальный IPv6 IP в качестве исходного адреса запроса, каким-то образом шлюз Hetzner, кажется, обновляет свою внутреннюю таблицу IPv6-to-MAC-адресов. В течение следующих 20 минут шлюз Hetzner будет отправлять любой пакет, предназначенный для IPv6-адреса виртуальных машин, на MAC-адрес виртуальных машин. Если в течение 20 минут никакие дальнейшие запросы от MAC-адреса виртуальной машины и глобального IP-адреса виртуальной машины не отправляются на шлюз, он возвращается к отправке пакетов IPv6 на MAC-адрес хоста.

Теперь ваша виртуальная машина - сразу после запуска сети, возможно из-за того, что локальный адрес канала не назначен на этом этапе - ONCE отправляет запрос, используя свой глобальный адрес IPv6 в качестве источника, и поэтому «случайно» обновляет таблицу MAC-адресов Hetzner на этот раз. Во время выполнения виртуальная машина по-прежнему непрерывно отправляет запросы на поиск MAC-адреса шлюза, чтобы поддерживать его таблицу MAC-адресов в актуальном состоянии, но для этого использует свой локальный IPv6-адрес (что вполне нормально с точки зрения IPv6), но которые не будут обновлять таблицу MAC-адресов Hetzner Gatway. По этой причине после запуска виртуальной машины IPv6 кажется полностью работоспособным, но только в течение 20 минут.

Решения:

Есть грязный раствор и чистый раствор:

  • Грязное решение: ваша виртуальная машина должна время от времени отправлять запрос на получение MAC-адреса шлюза, используя его глобальный IPv6-адрес (скажем, каждые 5 минут). Это сложно: ваша виртуальная машина будет отправлять запросы, но с использованием локального IPv6. Итак, я использовал дешевый трюк: я удаляю локальный IP-адрес из интерфейса, отправляю запрос (который затем принудительно использует глобальный IP-адрес) и повторно присоединяю локальный IP-адрес:

    ip -6 addr del fe80::a00:27ff:fecf:e270/64 dev enp0s3
    ndisc6 fe80::1 enp0s3
    ip -6 addr add fe80::a00:27ff:fecf:e270/64 dev enp0s3
    
  • Чистое решение: не используйте перемычку. Теперь я использую Host-only-Networking. Это означает, что виртуальная машина подключена к отдельному сетевому адаптеру (vboxnet0). Я добавил маршрут IPv6, который перенаправляет весь трафик с хоста на IPv6-адрес виртуальной машины:

    ip -6 route add <my IPv6 pefix>::20 dev vboxnet0
    

На виртуальной машине я использую локальный IPv6-адрес хоста в качестве GW по умолчанию. Чтобы позволить хосту подключать виртуальную машину к глобальному IPv6 IP, я назначил другой IP из той же подсети / 64 для vboxnet0. Для меня это отлично работает.