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

Можно ли проверить MAC-адрес хоста, подключенного к TCP (в той же локальной сети)?

У меня есть локальная сеть Ethernet (192.168.1.0/24) с несколькими хостами, которым маршрутизатор назначает адреса через DHCP. Из-за способа настройки DHCP IP-адреса конкретных устройств могут изменяться непредсказуемым образом; это то, что я не могу контролировать.

На клиентском хосте работает некоторый код, который регулярно опрашивает серверные процессы, запущенные на каждом из других хостов, через TCP, чтобы собрать некоторые метрики с каждого хоста. Клиент должен иметь возможность надежно идентифицировать, с каким из серверов он обращается, а из-за динамического назначения IP единственная надежная идентификация основана на их MAC-адресах.

Я предпринял обычные шаги для получения сопоставления MAC-> IP для каждого из хостов:

  1. Я периодически бегаю сканирование сети с использованием nmap, чтобы убедиться, что кеш ARP заполнен
  2. Перед установкой каждого подключения к серверу я ищу сопоставление MAC-> IP в клиентском ARP-кеше (с помощью такого метода, как этот). Если MAC-адрес отсутствует в кэше ARP, я принудительно выполняю повторное сканирование сети.

Это работает в большинстве случаев, но я все еще сталкиваюсь с периодическими проблемами из-за переключения IP-адресов хостами.

Например, какое-то время у хоста A будет IP-адрес 192.168.1.101, а у хоста B - 192.168.1.102. Основываясь на кэше ARP и знании их MAC-адресов, я могу сказать, какие из них есть, и провести соответствующий опрос. Но иногда будет происходить переназначение IP-адреса по мере обновления аренды DHCP, и хост A окажется на 192.168.1.102, а хост B теперь на 192.168.1.101. В тот момент, когда это произойдет, клиентский кеш ARP будет неправильным. И на основе вышеупомянутого подхода клиент по-прежнему будет подключаться к 192.168.1.101, думая, что он считывает метрики хоста A, в то время как на самом деле он теперь разговаривает с хостом B.

Мне нужно устранить такие случаи.

Мне пришли в голову следующие три возможных подхода:

Я понимаю, что это было длинное вступление, но в основном я хотел бы знать есть ли практический способ реализовать вариант C?

Если я проверю пакеты данных, которыми обмениваются узлы во время TCP-соединения, соответствующие MAC-адреса присутствуют в качестве источника и назначения кадра Ethernet. Итак, теоретически - по крайней мере, на некотором уровне - клиентское устройство действительно знает конкретный MAC-адрес сервера, с которым оно разговаривает. Но есть ли способ показать это коду, запускающему TCP-соединение?

В моем контексте у меня есть код Python, создающий соединения с использованием встроенного socket библиотека на хосте Linux. Я понимаю, что ответ может сильно зависеть от фактической среды, но мне было бы интересно услышать какие-либо общие указания о том, как MAC-адреса доступны (или нет) процессам, инициирующим TCP-соединения. И действительно, любое руководство по надежному способу подключения к хосту на основе его MAC-адреса.

API-интерфейсы сокетов на уровне 3 и 4 не видят MAC-адрес уровня 2. Это требует исследования кеша обнаружения соседей. (И что ваш сетевой стек вообще включает MAC-адреса. Хотя Linux-машины в локальной сети, вероятно, будут, Ethernet повсеместен.)

ARP также не подходит для сетей IPv6. Вы также должны посмотреть кеш обнаружения соседей. Другое дело, даже если интерфейсы для его запроса похожи.

И MAC-адреса являются плохими первичными ключами в таблице хостов, они не самые стабильные или уникальные идентификаторы. Хосты имеют несколько сетевых адаптеров. Аппаратные сетевые карты заменяются. При клонировании виртуальной машины следует изменить нумерацию гостевых сетевых адаптеров. Отсутствие дубликатов вероятно, но не обязательно.


Скорее используйте длинный идентификатор хоста. Например, UUID, который, скорее всего, будет уникальным. Например, в системах systemd есть /etc/machine-id.