LINUX.ORG.RU
решено ФорумAdmin

QEMU/KVM macvtap и mac-адрес

 , ,


0

1

Поднял дома на подкроватном сервере-одноплатнике kvm. Не хочется менять настройки сети, доступ с самого одноплатника на виртуальные машины не нужен, поэтому настроил сеть на госте через macvtap. А далее что-то странное. Другие компы в сети, видят mac-адрес самой сетевой карты одноплатника, а не виртуального интерфейса. Соответственно, если попытаться стукнуться на виртуалку по ssh, оно идёт на хост, а не на виртуальную машину. Если потом с помощью ip neigh replace на десктопе или ноуте поставить айпишнику виртуальной машины правильный mac-адрес, всё работает как задумано.

Кто-нибудь встречал подобное поведение? Много лет использую kvm с macvtap и такое поведение вижу впервые.

Если это важно, на хосте-одноплатнике gentoo. На других машинах в локалке или gentoo, или debian.

В качестве роутера всей сети noname-китайский роутер от провайдера. Я сначала решил, что он виноват, так как проблему заметил, подключаясь с ноутбука по wi-fi. Но потом попробовал с десктопа, подключённого как и одноплатник по проводу, и проблема повторилась. Такое впечатление, что хост-система на одноплатнике на arp who-has отдаёт неверный ответ.

★★★★★

Последнее исправление: shell-script (всего исправлений: 2)

Я не разбираюсь в эти фокусах с виртуальными мак адресами и не знаю что такое maсvtap, но, как я понял, другие компы получают по arp неправильный мак-адрес для какого-то айпи. А значит стоит запустить везде (и на клиенте, и на виртуалочном хосте, и в самой виртуалке) tcpdump -e и проследить кто что куда шлёт, для начала.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от firkax

Как я написал выше, компы в локалке шлют arp who-has по броадкасту, хост-одноплатник отвечаем им с неправильным mac-адресом.

не знаю что такое maсvtap

Это ключевой кейс в данном вопросе.

shell-script ★★★★★
() автор топика
Ответ на: комментарий от firkax

В самой виртуалке всё работает штатно. В неё ничего пробрасывать не надо. Проблема в том, что хост отдаёт в локалку неверный(свой хостовый mac-адрес) вместо того, что висит на macvtap-интерфейсе.

Я же говорю, что на клиентах после изменения mac-адреса виртуалки в arp-таблице всё работает.

С любой машины в локалке.

└─> ip neigh list 192.168.0.100
192.168.0.100 dev enp6s0 lladdr 7c:83:34:b5:e8:c3 REACHABLE
└─> ping -c 1 192.168.0.100
PING 192.168.0.100 (192.168.0.100) 56(84) bytes of data.
64 bytes from 192.168.0.100: icmp_seq=1 ttl=64 time=0.738 ms

--- 192.168.0.100 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.738/0.738/0.738/0.000 ms
Это ответил хост.

Теперь меняем.

└─> sudo ip neigh replace 192.168.0.100 lladdr 52:54:00:77:97:ba dev enp6s0
└─> ping -c 1 192.168.0.100
PING 192.168.0.100 (192.168.0.100) 56(84) bytes of data.
64 bytes from 192.168.0.100: icmp_seq=1 ttl=64 time=0.716 ms

--- 192.168.0.100 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.716/0.716/0.716/0.000 ms
Теперь уже ответила виртуалка.

При нормальном поведении, сразу должна была отвечать виртуалка, а хост вовсе не должен знать про ip 192.168.0.100.

На хосте оно выглядит так:

└─> ip a l dev enp1s0
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 7c:83:34:b5:e8:c3 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.14/24 brd 192.168.0.255 scope global dynamic noprefixroute enp1s0
       valid_lft 44737sec preferred_lft 33937sec
    inet6 fe80::7e83:34ff:feb5:e8c3/64 scope link proto kernel_ll 
       valid_lft forever preferred_lft forever
└─> ip a l dev macvtap1
528: macvtap1@enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 500
    link/ether 52:54:00:77:97:ba brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.100/24 brd 192.168.0.255 scope global dynamic noprefixroute macvtap1
       valid_lft 51684sec preferred_lft 40884sec
    inet6 fe80::5054:ff:fe77:97ba/64 scope link proto kernel_ll 
       valid_lft forever preferred_lft forever

Что-то у меня с поднятием macvtap неправильно. Но что именно, и почему так получилось, я как раз пытаюсь понять.

shell-script ★★★★★
() автор топика
Ответ на: комментарий от shell-script

Так ты tcpdump -e смотрел (на хосте хотя бы, хотя лучше и на виртуалке) во время первого пинга и во время второго?

Кстати интересно для него эти два интерфейса как два отдельных видны или на enp1s0 видно всё?

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 3)
Ответ на: комментарий от firkax

Да, именно tcpdump'ом я определяю, куда идут пакеты(после того, как заметил несовпадение хешей sshd).

Кстати интересно для него эти два интерфейса как два отдельных видны или на enp1s0 видно всё?

На enp1s0 хост видит полностью всё. На macvtpap1 только то, что предназначено ему.

shell-script ★★★★★
() автор топика
Ответ на: комментарий от firkax

Я не понимаю, что ты там хочешь увидеть.

Держи:

└─> tcpdump -ntpei enp1s0 host 192.168.0.10 and host 192.168.0.10 and icmp and not net 192.168.222.0/24
dropped privs to pcap
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on enp1s0, link-type EN10MB (Ethernet), snapshot length 262144 bytes


70:8b:cd:a2:c2:ea > 7c:83:34:b5:e8:c3, ethertype IPv4 (0x0800), length 98: 192.168.0.10 > 192.168.0.100: ICMP echo request, id 6408, seq 1, length 64
7c:83:34:b5:e8:c3 > 70:8b:cd:a2:c2:ea, ethertype IPv4 (0x0800), length 98: 192.168.0.100 > 192.168.0.10: ICMP echo reply, id 6408, seq 1, length 64
70:8b:cd:a2:c2:ea > 7c:83:34:b5:e8:c3, ethertype IPv4 (0x0800), length 98: 192.168.0.10 > 192.168.0.100: ICMP echo request, id 6408, seq 2, length 64
7c:83:34:b5:e8:c3 > 70:8b:cd:a2:c2:ea, ethertype IPv4 (0x0800), length 98: 192.168.0.100 > 192.168.0.10: ICMP echo reply, id 6408, seq 2, length 64
70:8b:cd:a2:c2:ea > 7c:83:34:b5:e8:c3, ethertype IPv4 (0x0800), length 98: 192.168.0.10 > 192.168.0.100: ICMP echo request, id 6408, seq 3, length 64
7c:83:34:b5:e8:c3 > 70:8b:cd:a2:c2:ea, ethertype IPv4 (0x0800), length 98: 192.168.0.100 > 192.168.0.10: ICMP echo reply, id 6408, seq 3, length 64
70:8b:cd:a2:c2:ea > 7c:83:34:b5:e8:c3, ethertype IPv4 (0x0800), length 98: 192.168.0.10 > 192.168.0.100: ICMP echo request, id 6408, seq 4, length 64
7c:83:34:b5:e8:c3 > 70:8b:cd:a2:c2:ea, ethertype IPv4 (0x0800), length 98: 192.168.0.100 > 192.168.0.10: ICMP echo reply, id 6408, seq 4, length 64
70:8b:cd:a2:c2:ea > 7c:83:34:b5:e8:c3, ethertype IPv4 (0x0800), length 98: 192.168.0.10 > 192.168.0.100: ICMP echo request, id 6408, seq 5, length 64
7c:83:34:b5:e8:c3 > 70:8b:cd:a2:c2:ea, ethertype IPv4 (0x0800), length 98: 192.168.0.100 > 192.168.0.10: ICMP echo reply, id 6408, seq 5, length 64


70:8b:cd:a2:c2:ea > 52:54:00:77:97:ba, ethertype IPv4 (0x0800), length 98: 192.168.0.10 > 192.168.0.100: ICMP echo request, id 6547, seq 1, length 64
52:54:00:77:97:ba > 70:8b:cd:a2:c2:ea, ethertype IPv4 (0x0800), length 98: 192.168.0.100 > 192.168.0.10: ICMP echo reply, id 6547, seq 1, length 64
70:8b:cd:a2:c2:ea > 52:54:00:77:97:ba, ethertype IPv4 (0x0800), length 98: 192.168.0.10 > 192.168.0.100: ICMP echo request, id 6547, seq 2, length 64
52:54:00:77:97:ba > 70:8b:cd:a2:c2:ea, ethertype IPv4 (0x0800), length 98: 192.168.0.100 > 192.168.0.10: ICMP echo reply, id 6547, seq 2, length 64
70:8b:cd:a2:c2:ea > 52:54:00:77:97:ba, ethertype IPv4 (0x0800), length 98: 192.168.0.10 > 192.168.0.100: ICMP echo request, id 6547, seq 3, length 64
52:54:00:77:97:ba > 70:8b:cd:a2:c2:ea, ethertype IPv4 (0x0800), length 98: 192.168.0.100 > 192.168.0.10: ICMP echo reply, id 6547, seq 3, length 64
70:8b:cd:a2:c2:ea > 52:54:00:77:97:ba, ethertype IPv4 (0x0800), length 98: 192.168.0.10 > 192.168.0.100: ICMP echo request, id 6547, seq 4, length 64
52:54:00:77:97:ba > 70:8b:cd:a2:c2:ea, ethertype IPv4 (0x0800), length 98: 192.168.0.100 > 192.168.0.10: ICMP echo reply, id 6547, seq 4, length 64
70:8b:cd:a2:c2:ea > 52:54:00:77:97:ba, ethertype IPv4 (0x0800), length 98: 192.168.0.10 > 192.168.0.100: ICMP echo request, id 6547, seq 5, length 64
52:54:00:77:97:ba > 70:8b:cd:a2:c2:ea, ethertype IPv4 (0x0800), length 98: 192.168.0.100 > 192.168.0.10: ICMP echo reply, id 6547, seq 5, length 64
192.168.222.0/24 отфильтровал, чтобы не мешалась в выводе.

С клиентской машины пускал дважды ping -c 192.168.0.100. Пустыми строками отбил тот момент, когда после первой серии пингов сделал ip neigh replace.

Параллельно был запущен аналогичный tcpdump на macvtap1. Первую серию пингов он не увидел, вторая серия совпадает с той, что на листинге выше. Что собственно, ожидаемо.

Если же удалить на клиентской машине 192.168.0.100 из arp-таблицы и отфильтровать момент знакомства, видим:

└─> tcpdump -ntpei enp1s0 arp and host 192.168.0.100 and not host 192.168.0.1 and not host 192.168.0.14
dropped privs to pcap
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on enp1s0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
70:8b:cd:a2:c2:ea > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 60: Request who-has 192.168.0.100 tell 192.168.0.10, length 46
7c:83:34:b5:e8:c3 > 70:8b:cd:a2:c2:ea, ethertype ARP (0x0806), length 42: Reply 192.168.0.100 is-at 7c:83:34:b5:e8:c3, length 28
52:54:00:77:97:ba > 70:8b:cd:a2:c2:ea, ethertype ARP (0x0806), length 42: Reply 192.168.0.100 is-at 52:54:00:77:97:ba, length 28
Т.е. хост ответил, что это он 192.168.0.100. И это я тоже знаю. Я не знаю, почему он вообще это отвечает. Он не должен этого делать и вся суть проблемы именно в этом.

Сори, если сразу неясно это выразил.

shell-script ★★★★★
() автор топика
Ответ на: комментарий от shell-script

Видно что правильный arp-ответ таки есть, но перед ним идёт неправильный. Из твоих объяснений например этого не было понятно.

Предполагаю костыль - просто зафильтровать его и всё станет как надо. Второй (правильный) ответ кто шлёт? Хост или виртуалка? tcpdump в виртуалке всё-таки желателен.

Если его шлёт виртуалка то может надо убрать айпи-адрес с хостового интерфейса вообще?

firkax ★★★★★
()
Ответ на: комментарий от firkax

Правильный ответ шлёт виртуалка. Она полностью нормально работает с сетью. Проблема только в ответе хоста.

Фильтровать что-то и/или руками убирать - это костыли и не хотелось бы пока их лепить. Когда я буду поднимать новые виртуалки, появятся macvtap2, ..., macvtapN. Для каждой из них придётся это делать.

shell-script ★★★★★
() автор топика

Не работал с macvtap, но поверхностные поиски привели меня к https://suhu0426.github.io/Web/Presentation/20150120/index.html и https://stackoverflow.com/questions/49476653/how-to-use-custom-tap-with-libvirt где в обоих случаях кроме создания самого интерфейса ещё трогают net.ipv4.conf.***.proxy_arp = 1

Может стоит тоже это покрутить на хосте и посмотреть на разницу

Flotsky ★★
()
Ответ на: комментарий от shell-script

Всмысле «руками убирать»? Просто создай macvtap без айпи-адреса сразу и назначь айпи-адрес только внутри виртуалки.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от firkax

Я не создаю macvtap'ов. Из создаёт qemu/libvirt при запуске виртуальной машины. Сколько будет машин, столько будет и macvtap'ов.

Внутри виртуалки я тоже ничего не назначаю. Я автоматически получаю адреса по dhcp с привязкой по mac-адресу виртуалки.

shell-script ★★★★★
() автор топика
Ответ на: комментарий от Flotsky

Но у меня же проблема не в том, что arp не попадает в виртуалку. У меня проблема в том, что хост лишний раз отвечает. Я, конечно, почитаю подробнее, что там по ссылкам, но не похоже, что это мой случай.

Я понимаю, зачем они по ссылкам это делают. Там оно в usermode. У меня же используется ядерный модуль macvtap.

shell-script ★★★★★
() автор топика
Ответ на: комментарий от firkax

Ага. А вот это оказалось годная идея.

Для управления адресами на хосте используется dhcpcd.

[I] net-misc/dhcpcd (10.0.8@25.06.2024): A fully featured, yet light weight RFC2131 compliant DHCP client
Не путать с dhcpd.

Добавил в его конфиг строку denyinterfaces macvtap* и случилось счастье.

Спасибо за наводку. Проблема была не в libvirt. Вопрос решён.

shell-script ★★★★★
() автор топика