У меня есть машина, подключенная к немного сломанному научному прибору, и я пытаюсь решить проблемы. Связь точка-точка, 2x25G Ethernet, никакие другие устройства не задействованы. Устройство передает данные UDP с одним потоком на интерфейс, и я могу настроить IP-адрес и MAC-адрес назначения, но исходный IP-адрес устройства одинаков для обоих интерфейсов. Используя tcpdump, я вижу, что трафик поступает на правильные интерфейсы с правильным IP-адресом назначения и MAC-адресом для обоих.
Но я могу прослушивать только один из IP-адресов и получать данные, если я слушаю на другом IP-адресе, трафика нет. Ядро явно сбрасывает трафик, и я не знаю, почему и как это отладить.
На машине работает ubuntu 18.04, IP-адреса 10.50.5.1/16 и 10.50.5.129/16, у устройства IP 10.50.1.10. Маршруты:
10.50.0.0/16 dev data0 proto kernel scope link src 10.50.5.1
10.50.0.0/16 dev data1 proto kernel scope link src 10.50.5.129
Какие-либо предложения?
В netstat я вижу, что пакеты не отбрасываются, так куда они деваются?
Kernel Interface table
Iface MTU RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
data0 9600 202320 0 0 0 29 0 0 0 BMRU
data1 9600 203600 0 0 0 31 0 0 0 BMRU
У вас возникают проблемы с маршрутизацией из-за попытки достичь одного и того же пункта назначения с использованием двух разных интерфейсов и маршрутов. По умолчанию маршрутизация выполняется по месту назначения, а не по источнику. По умолчанию Linux, который использует модель слабого хоста (но Ubuntu также устанавливает фильтр обратного пути, см. ниже) выберет тот же интерфейс: тот из равных кандидатов, который появится первым в его списке. Итак, здесь оба исходных IP-адреса 10.50.5.1 и 10.50.5.129 будут использовать data0 чтобы достичь 10.50.1.10, потому что в настоящее время он является первым среди двух равных в записях маршрута.
В противном случае требуется маршрутизация на основе источника (также известная как политика маршрутизации) в Linux: укажите также, что источник используется для определения маршрута к месту назначения.
Также по аналогичным причинам в вашей текущей конфигурации: имея два IP-адреса в одной IP-сети (10.50.0.0/16), Linux будет отвечать на запросы ARP в локальной сети с любого из своих интерфейсов с любым из своих MAC-адресов. В конце концов, если это не так, как в вашей настройке с устройством, использующим постоянные записи ARP вместо выполнения запросов, обычно только один интерфейс получает весь входящий трафик (он может быть даже «неправильным»).
И последняя капля заключается в том, что даже если инструмент отправляет на правильный интерфейс с правильным IP-адресом назначения, Ubuntu по умолчанию должен иметь Строгий обратный путь включен, отбрасывая пакеты, полученные на "неправильном" интерфейсе. Вот почему вам не хватает данных: интерфейс (попробуйте современный ip -statistics link
команда) получила их, но стек маршрутизации сбросил их сразу после. Чтобы убедиться в этом, просто спросите стек маршрутизации ядра, что он думает об отправке и получении IP-пакетов:
отправка
# ip route get from 10.50.5.1 10.50.1.10
10.50.1.10 from 10.50.5.1 dev data0 uid 0
cache
# ip route get from 10.50.5.129 10.50.1.10
10.50.1.10 from 10.50.5.129 dev data0 uid 0
cache
Оба будут отправлены с использованием data0, игнорируя data1.
получение
# ip route get from 10.50.1.10 iif data0 10.50.5.1
local 10.50.5.1 from 10.50.1.10 dev lo table local
cache <local> iif data0
# ip route get from 10.50.1.10 iif data1 10.50.5.129
RTNETLINK answers: Invalid cross-device link
Получение на data1 запрещено строгим фильтром обратного пути.
Вы можете отключить обратный путь, но если вам когда-нибудь понадобится отправить через определенный интерфейс, это все равно не поможет.
Ниже я предлагаю более чистый метод.
Во-первых, чтобы избежать использования настроек ARP (и «ARP флюс» соображений), рассмотрите два интерфейса, как они используются: двухточечные IP-интерфейсы, даже если они используются на канальном уровне Ethernet. Таким образом, нет необходимости использовать целую локальную сеть / 16: достаточно маршрутов точка-точка.
# ip address flush dev data0
# ip address flush dev data1
# ip address add 10.50.5.1 peer 10.50.1.10/32 dev data0
# ip address add 10.50.5.129 peer 10.50.1.10/32 dev data1
Две приведенные выше команды в основном являются ярлыками для ip address add 10.50.5.N/32 dev dataX; ip route add 10.50.1.10/32 dev dataX
.
Вы могли бы сохранить свои сетевые настройки / 16 (например: если, наконец, они привыкнут к реальному использованию LAN с фермой оборудования позади), но для этого также потребовалось бы переключить arp_filter=1
на интерфейсах, чтобы оставаться в безопасности.
Чтобы решить проблему маршрутизации на основе источника: используйте правила, указывающие на дополнительные таблицы маршрутизации, которые будут иметь частичную копию некоторых маршрутов из основной таблицы маршрутизации. Я выбираю произвольные значения 1000 и 1001 для этих таблиц маршрутизации (и использую произвольные фиксированные приоритеты правил 10000 10001, даже если они не требуются). Все в таблице 1000 не нужно (потому что она используется по умолчанию), но в любом случае она просто чище.
ip route add table 1000 10.50.1.10/32 dev data0 src 10.50.5.1
ip route add table 1001 10.50.1.10/32 dev data1 src 10.50.5.129
ip rule add pref 10000 from 10.50.5.1 lookup 1000
ip rule add pref 10001 from 10.50.5.129 lookup 1001
Основная таблица по-прежнему будет определять, какой интерфейс используется по умолчанию (возможно, data0): любой инструмент, не привязанный к конкретному IP-адресу, будет использовать его (и, следовательно, 10.50.5.1) по умолчанию, то же самое, если привязка к 10.50.5.1. Но теперь любой инструмент, привязанный к 10.50.5.129, будет правильно использовать двунаправленный трафик. data1.
# ip route get 10.50.1.10
10.50.1.10 dev data0 src 10.50.5.1 uid 0
cache
# ip route get from 10.50.5.1 10.50.1.10
10.50.1.10 from 10.50.5.1 dev data0 table 1000 uid 0
cache
# ip route get from 10.50.5.129 10.50.1.10
10.50.1.10 from 10.50.5.129 dev data1 table 1001 uid 0
cache
а теперь поступают данные о data1 не отбрасывается фильтром обратного пути:
# ip route get from 10.50.1.10 iif data0 10.50.5.1
local 10.50.5.1 from 10.50.1.10 dev lo table local
cache <local> iif data0
# ip route get from 10.50.1.10 iif data1 10.50.5.129
local 10.50.5.129 from 10.50.1.10 dev lo table local
cache <local> iif data1
Примечание:
Дополнительные таблицы маршрутизации заполняются вручную, а не ядром. Если интерфейс отключен (или IP-адрес удален), а затем восстановлен (или IP-адрес добавлен обратно), соответствующая таблица 1000 или 1001 будет очищена и не будет повторно заполнена: ее нужно добавить обратно вручную ( или с помощью инструмента настройки сети, способного это сделать).