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

DHCP и macvlan: только первый виртуальный интерфейс работает с одноадресным DHCPREQUEST

Что я пытаюсь сделать?

Я пытаюсь получить 3 общедоступных IP-адреса через DHCP на одном физическом восходящем кабеле ISP.

Что не так?

Продления идут не так, как надо. Из интерфейсов virtual0 работает нормально, когда он пытается обновить через одноадресное соединение с DHCP-сервером. Интерфейсы virtual1 и virtual2 не работают при одноадресной передаче. Они переходят в резервный режим, чтобы использовать широковещательные рассылки и успешно с ними, но спамят журналы, полные вещей, которые не могут быть хорошими. Я использую Debian 8 и isc-dhcp-client v. 4.3.1.

Я настроил интерфейсы при загрузке следующим образом:

IF_VIRTUAL_BASE=eth0
IF_PUB0=virtual0
IF_PUB1=virtual1
IF_PUB2=virtual2
IF_LAN=eth2

ifconfig "$IF_VIRTUAL_BASE" up
ip link add link "$IF_VIRTUAL_BASE" address 00:90:0b:ff:10:5b "$IF_PUB0" type macvlan
ip link set "$IF_PUB0" up
ip link add link "$IF_VIRTUAL_BASE" address 00:90:0b:ff:11:5b "$IF_PUB1" type macvlan
ip link set "$IF_PUB1" up
ip link add link "$IF_VIRTUAL_BASE" address 00:90:0b:ff:12:5b "$IF_PUB2" type macvlan
ip link set "$IF_PUB2" up

# Enable forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward

Я тоже делаю unset new_routers при выполнении dhcprequest для virtual1 и virtual2.

И знаете что, это чудовище работает:

Jul 11 20:45:43 gw dhclient: DHCPREQUEST on virtual0 to 255.255.255.255 port 67
Jul 11 20:45:43 gw dhclient: DHCPREQUEST on virtual1 to 255.255.255.255 port 67
Jul 11 20:45:43 gw ifup[582]: DHCPREQUEST on virtual0 to 255.255.255.255 port 67
Jul 11 20:45:43 gw ifup[592]: DHCPREQUEST on virtual1 to 255.255.255.255 port 67
Jul 11 20:45:43 gw dhclient: DHCPREQUEST on virtual2 to 255.255.255.255 port 67
Jul 11 20:45:43 gw ifup[634]: DHCPREQUEST on virtual2 to 255.255.255.255 port 67
Jul 11 20:45:46 gw dhclient: DHCPREQUEST on virtual1 to 255.255.255.255 port 67
Jul 11 20:45:46 gw ifup[592]: DHCPREQUEST on virtual1 to 255.255.255.255 port 67
Jul 11 20:45:46 gw dhclient: DHCPACK from 88.113.75.2
Jul 11 20:45:46 gw ifup[592]: DHCPACK from 88.113.75.2
Jul 11 20:45:46 gw logger: virtual1 (REBOOT): IP:  -> 88.113.75.59; GW:  -> 88.113.75.1

Jul 11 20:45:47 gw dhclient: DHCPREQUEST on virtual0 to 255.255.255.255 port 67
Jul 11 20:45:47 gw ifup[582]: DHCPREQUEST on virtual0 to 255.255.255.255 port 67
Jul 11 20:45:47 gw dhclient: DHCPACK from 88.113.75.2
Jul 11 20:45:47 gw ifup[582]: DHCPACK from 88.113.75.2
Jul 11 20:45:47 gw logger: virtual0 (REBOOT): IP:  -> 88.113.75.65; GW:  -> 88.113.75.1

Jul 11 20:45:50 gw dhclient: DHCPREQUEST on virtual2 to 255.255.255.255 port 67
Jul 11 20:45:50 gw ifup[634]: DHCPREQUEST on virtual2 to 255.255.255.255 port 67
Jul 11 20:45:50 gw dhclient: DHCPACK from 88.113.75.2
Jul 11 20:45:50 gw ifup[634]: DHCPACK from 88.113.75.2
Jul 11 20:45:50 gw logger: virtual2 (REBOOT): IP:  -> 88.113.75.61; GW:  -> 88.113.75.1

Значит, они работали? И это широковещательные запросы. Хорошо, перемотаем вперед на час или около того, мы получим много такого:

Jul 11 21:45:09 gw dhclient: DHCPREQUEST on virtual2 to 195.74.6.55 port 67
Jul 11 21:45:11 gw dhclient: DHCPREQUEST on virtual1 to 195.74.6.55 port 67
Jul 11 21:45:22 gw dhclient: DHCPREQUEST on virtual2 to 195.74.6.55 port 67
Jul 11 21:45:25 gw dhclient: DHCPREQUEST on virtual1 to 195.74.6.55 port 67
Jul 11 21:45:32 gw dhclient: DHCPREQUEST on virtual1 to 195.74.6.55 port 67
Jul 11 21:45:43 gw dhclient: DHCPREQUEST on virtual2 to 195.74.6.55 port 67
Jul 11 21:45:46 gw dhclient: DHCPREQUEST on virtual1 to 195.74.6.55 port 67
Jul 11 21:45:56 gw dhclient: DHCPREQUEST on virtual2 to 195.74.6.55 port 67
Jul 11 21:46:05 gw dhclient: DHCPREQUEST on virtual1 to 195.74.6.55 port 67
Jul 11 21:46:11 gw dhclient: DHCPREQUEST on virtual2 to 195.74.6.55 port 67
Jul 11 21:46:21 gw dhclient: DHCPREQUEST on virtual1 to 195.74.6.55 port 67
Jul 11 21:46:30 gw dhclient: DHCPREQUEST on virtual2 to 195.74.6.55 port 67
Jul 11 21:46:33 gw dhclient: DHCPREQUEST on virtual1 to 195.74.6.55 port 67
Jul 11 21:46:42 gw dhclient: DHCPREQUEST on virtual2 to 195.74.6.55 port 67
Jul 11 21:46:47 gw dhclient: DHCPREQUEST on virtual1 to 195.74.6.55 port 67
Jul 11 21:47:00 gw dhclient: DHCPREQUEST on virtual2 to 195.74.6.55 port 67
Jul 11 21:47:01 gw dhclient: DHCPREQUEST on virtual1 to 195.74.6.55 port 67
Jul 11 21:47:09 gw dhclient: DHCPREQUEST on virtual1 to 195.74.6.55 port 67

Интерфейсы virtual1 и virtual2 отчаянно пытаются обновить свои IP-адреса через одноадресное соединение с предыдущим DHCP-сервером 195.74.6.55. Они не работают с одноадресной передачей. Но потом происходит что-то забавное, в конце концов они переключаются на трансляцию как запасной вариант и преуспевают!

Jul 11 22:30:41 gw dhclient: DHCPREQUEST on virtual1 to 195.74.6.55 port 67
Jul 11 22:30:47 gw dhclient: DHCPREQUEST on virtual2 to 195.74.6.55 port 67
Jul 11 22:30:52 gw dhclient: DHCPREQUEST on virtual1 to 255.255.255.255 port 67
Jul 11 22:30:52 gw dhclient: DHCPACK from 88.113.75.2
Jul 11 22:30:52 gw logger: virtual1 (RENEW): IP: 88.113.75.59 -> 88.113.75.59; GW: 88.113.75.1 -> 88.113.75.1

Jul 11 22:30:58 gw dhclient: DHCPREQUEST on virtual2 to 255.255.255.255 port 67
Jul 11 22:30:58 gw dhclient: DHCPACK from 88.113.75.2
Jul 11 22:30:59 gw logger: virtual2 (RENEW): IP: 88.113.75.61 -> 88.113.75.61; GW: 88.113.75.1 -> 88.113.75.1

Обратите внимание на интерфейс virtual0:

Jul 11 22:38:17 gw dhclient: DHCPREQUEST on virtual0 to 195.74.6.55 port 67
Jul 11 22:38:18 gw dhclient: DHCPACK from 195.74.6.55
Jul 11 22:38:18 gw logger: virtual0 (RENEW): IP: 88.113.75.65 -> 88.113.75.65; GW: 88.113.75.1 -> 88.113.75.1

Вывод состоит в том, что для интерфейса virtual0 работают одноадресные (dhclient) DHCP-запросы, а для virtual1 и virtual2 работают только широковещательные обновления DHCP. Значит, это проблема маршрутизации? Вот что показывает IP-маршрут после обычной загрузки:

root@gw:~# ip route
default via 88.113.75.1 dev virtual0
88.113.75.0/24 dev virtual0  proto kernel  scope link  src 88.113.75.65
88.113.75.0/24 dev virtual1  proto kernel  scope link  src 88.113.75.59
88.113.75.0/24 dev virtual2  proto kernel  scope link  src 88.113.75.61
172.16.8.0/28 via 172.16.8.2 dev tun0 # For openvpn
172.16.8.0/24 dev eth2  proto kernel  scope link  src 172.16.8.254 # For LAN
172.16.8.2 dev tun0  proto kernel  scope link  src 172.16.8.1 #For openvpn

Как заставить dhclients на интерфейсах на основе macvlan virtual1 и virtual2 правильно маршрутизировать свои одноадресные запросы на обновление и получать ответы соответствующим образом?

Я выполнил множество поисков в Google, попытался перевернуть многие настройки, включая политики брандмауэра, маршрутизацию на основе политик, режим eth0 promisc и переменные sysctl, урезав общие настройки сети и т. Д. В настоящее время я выполняю strace для dhclient. Одна комбинация этих настроек должна работать. Если потребуется дополнительная информация, я буду более чем счастлив предоставить ее.

РЕДАКТИРОВАТЬ1: dhclient strace стал готов.

Это происходит в самом начале:

bind(5, {sa_family=AF_PACKET, proto=0x7669, if1635087474, pkttype=PACKET_HOST, addr(0)={12652, }, 16) = 0
bind(6, {sa_family=AF_INET, sin_port=htons(68), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
sendto(5, "......", 342, 0, {sa_family=AF_PACKET, proto=0x7669, if1635087474, pkttype=PACKET_HOST, addr(0)={12652, }, 18) = 342

«Sendto (5», насколько я понимаю, был первой успешной отправкой dhclient на основе широковещательной рассылки.

Затем, позже первая неудачная одноадресная отправка:

sendto(6, "......", 300, 0, {sa_family=AF_INET, sin_port=htons(67), sin_addr=inet_addr("195.74.6.55")}, 16) = 300

И следующий успешный широковещательный отправляем:

sendto(5, "......", 342, 0, {sa_family=AF_PACKET, proto=0x7669, if1635087474, pkttype=PACKET_HOST, addr(0)={12652, }, 18) = 342

Я смог это исправить! Немного неортодоксальным образом, но все же.

Так что я сделал? Я просто удалил isc-dhcp-client 4.3.1 и установил dhcpcd 6.0.5 (от Роя Марплеса, имя пакета debian dhcpcd5). Вот и все.

Я перезагрузил компьютер примерно в 23:00 и проверил, все ли интерфейсы в порядке, затем запустил tcpdump. Примерно в 00:02 истекает срок действия одного из таймеров DHCP, и все 3 интерфейса аккуратно получают свои IP-адреса без каких-либо вопросов:

https://i.stack.imgur.com/xGQpq.png

В основном мне не нужно было ничего менять в /etc/dhcpcd.conf. Похоже, что dhcpcd построен умнее, чем dhclient. По крайней мере, по моему сценарию.

(Примечание: я должен сказать, что было довольно легко перейти с isc-dhcp-client на dhcpcd. Debian 8 имел встроенную поддержку; кажется, если вы установите dhcpcd5, удалите isc-dhcp-client и перезагрузитесь, система подберет новый клиент автоматически. Что касается сценариев, кажется, что нет каталога сценариев для dhcpcd, но один файл для всех обработчиков ввода и один файл для всех обработчиков выхода. Файлы были названы: /etc/dhcpcd.enter-hook и / etc / dhcpcd. exit-hook. Если вы поместите в эти файлы скрипты хуков dhclient, они будут работать без изменений. Я впечатлен!)