Не похоже, что у фреймворка есть способ сделать это.Наиболее точным способом было бы выполнить поиск маршрута, но я не вижу хорошего способа сделать это в C #.(В Linux я бы набрал /sbin/ip -6 route get <ipv6-addr>
и посмотрел, какой маршрут возвращается.) Вам нужно было бы найти собственный вызов, чтобы сделать это в Windows;Я не вижу приложения командной строки.
Наилучшим способом может быть синтаксический анализ вывода netsh interface ipv6 show route verbose
.Вы можете искать любые префиксы, отличные от / 128, и сопоставлять их с самым длинным префиксом.(хорошо, если вы нажмете / 128, это адрес, назначенный для поля)
Вы также можете проверить таблицу соседей.(netsh interface ipv6 show neighbors
), но он может не содержать искомую запись, если вы недавно не общались с этим хостом.
Другие потенциальные проблемы, которые вам необходимо рассмотреть:
- Локальные адреса ссылок (fe80 :: / 10) (и многоадресная, кольцевая и неопределенная - все в таблице)
- Тот факт, что в IPv6 назначен адресне подразумевает префикс по ссылке.Таблица префиксов является отдельной.Не ясно, как проверить это под Windows, но
netsh interface ipv6 show siteprefixes
может помочь.Похоже, что Windows на самом деле может относиться к этому больше как к IPv4, чем ожидает стандарт.
Редактировать : похоже, что проверка таблицы соседей будет для вас способом наименьшего сопротивлениясделай это;если вы принимаете соединение из интрасети, а затем оборачиваетесь и проверяете таблицу соседей, вы можете быть достаточно уверены, что если сосед является локальным, он будет существовать в таблице.Если вы проверяете таблицу соседей, BE ОСТОРОЖНО , чтобы смотреть на таблицу соседей только для интерфейсов LAN.(Интерфейс ISATAP, установленный по умолчанию во многих системах Windows, представляет весь IPv4-интернет как локальную ссылку "подсети".)
Опять же, адреса IPv6 не имеют понятия "маска сети ", так как таблица префиксов на связи отделена от назначения адреса. Однако , если у вас где-то сидит сервер, вы можете быть на 99% уверены, что он находится на / 64 .(хотя вам следует быть осторожным; если бы он сам был конечной точкой туннеля, иногда я видел более длинные префиксы, назначенные для туннелей 6in4). Таким образом, быстрый и грязный алгоритм будет выглядеть так:
- Игнорировать всеадреса, где первые 64 бита равны 0 (локальный шлейф)
- Игнорировать все адреса, соответствующие ff00 :: / 8 (многоадресная передача)
- Если адрес соответствует fe80 :: / 10, это локальный интерфейс .Будьте осторожны с этим, потому что если у вас включен интерфейс ISATAP, «link-local» означает «автоматический туннель ко всему интернету IPv4»!(не очень хорошо.) Поэтому, возможно, лучше не доверять локальным ссылочным адресам, если вы не уверены, что они поступают из интерфейса локальной сети.(они не могут быть направлены)
- (Теперь сложная часть) Определите, является ли адрес соседним.(поиск соседей) Решением hack-and-slash является проверка всех IPv6-адресов, настроенных в системе (автоматически настраиваемых через автоконфигурирование адресов без сохранения состояния, DHCPv6 или статических, если вы можете это определить) и проверка первых 64 битов. На сервере (при условии, что в туннелях не настроены шутки с префиксами, отличными от / 64), в редких случаях это будет ошибкой, поскольку, опять же, вы не можете быть уверены, что адрес действительно подключенесли вы не проверите таблицу префиксов по ссылке.(о которой Windows не имеет понятия; кажется, что она хранится в таблице маршрутизации.) Большинство сетевых устройств, которые можно настроить для отправки объявлений маршрутизатора через интерфейс Ethernet, всегда будут объявлять префикс / 64.Если вы можете проверить, что пакет поступил через интерфейс локальной сети, будет еще менее вероятно, что это будет ошибкой.
Редактировать 2
Я написал некоторый код для разбора таблицы маршрутов IPv6 и разместил его здесь .Это еще не решает трудные проблемы, поставленные в этом вопросе, но это шаг в правильном направлении.