Является ли IP-адрес той же подсети, что и локальный компьютер (с поддержкой IPv6) - PullRequest
5 голосов
/ 09 сентября 2010

Есть ли у кого-нибудь код, который определит, находится ли IP-адрес (IPv4 или IPv6) в той же подсети, что и компьютер, на котором выполняется приложение?Я видел множество примеров кода, который делает это с IPv4, но я не могу найти ни одного, который поддерживает IPv6.

РЕДАКТИРОВАТЬ:

Я не уверен, если яЯ понимаю все различия между v4 и v6, так что вот немного больше к моему вопросу.У меня есть приложение, которое обслуживает как интернет-клиентов, так и клиентов интрасети, то есть есть клиенты, которые находятся в той же физической сети, что и сервер.Так что иногда между клиентом есть маршрутизаторы, а иногда нет.С помощью IPv4 я могу определить это, сравнив IP-адрес клиента с IP-адресом сервера и подсети, поэтому, если IP-адрес и маска подсети моего сервера соответственно:

192.168.123.15 255.255.255.0

Исервер получает запрос клиента от 192.168.123.100. Я знаю, что между клиентом и сервером нет маршрутизатора.Однако, если сервер получает запрос клиента от 192.168.1.100 или, возможно, от 67.7.23.4, я знаю, что между этими клиентами и сервером стоит маршрутизатор.В .Net я могу собрать IP-адреса клиента и сервера (как v4, так и v6), но не могу найти маску подсети IPv6.

Есть ли способ собрать эту информацию в .Net или есть какая-то разница между IPv4 и IPv6, которую я неправильно понимаю?

РЕДАКТИРОВАНИЕ x2:

Я разместил это на сайте MS Connect, чтобы посмотреть, над чем они работают, или по какой-то причине они не добавили свойство IPv6Mask в класс UnicastIPAddressInformation.

https://connect.microsoft.com/VisualStudio/feedback/details/643031/unicastipaddressinformation-class-has-no-ipv6mask-property

Я также опубликовал тот же вопрос на форумах MSDN примерно в то же время.1800+ просмотров и ни одного ответа.Думаю, я не единственный, кому это интересно.

http://social.msdn.microsoft.com/Forums/en-US/netfxnetcom/thread/dd30e161-9be5-4d70-97c0-22e2756ce953

Ответы [ 4 ]

3 голосов
/ 11 февраля 2011

Не похоже, что у фреймворка есть способ сделать это.Наиболее точным способом было бы выполнить поиск маршрута, но я не вижу хорошего способа сделать это в 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 и разместил его здесь .Это еще не решает трудные проблемы, поставленные в этом вопросе, но это шаг в правильном направлении.

2 голосов
/ 14 февраля 2011

Я искал в документации wmi, пытаясь найти префикс ipv6, и я также пытаюсь найти его. У меня есть рабочий код для IPv4, однако.

Я думаю, вы могли бы смело предположить, что префикс / 64 для этого сегмента сети. Если вы сделаете это, вы можете просто сравнить первые 8 байтов каждого адреса. Чаще всего в отдельных локальных сетях, в которых работают приложения, будет / 64, даже точечным соединениям часто дается полный диапазон / 64, даже если используется только 2.

2 голосов
/ 12 февраля 2011

Моральный эквивалент сетевой маски IPv4 в IPv6 называется длина префикса .(На самом деле, нам нравится говорить о длине префикса, а не о сетевой маске в IPv4, но некоторые люди еще не получили памятку.)

Еще одна проблема в IPv6, которая не подходит для IPv4, этоМаршрутизаторы по умолчанию объявляют о своем присутствии в ссылке, отвечая на запросы маршрутизатора от хостов.Хосты хранят список всех маршрутизаторов по умолчанию, которые они находят таким образом, вместе с их действительным и предпочтительным временем жизни.Маршрутизаторы могут также объявлять ноль, один или несколько префиксов, для которых они служат в качестве маршрутизатора по умолчанию, и хосты хранят их список вместе со своими связанными маршрутизаторами и их индивидуальные действительные и предпочтительные времена жизни.

Каждый префикс имеет два вспомогательныхбиты в объявлении, A и L, которые объединяются хостами при добавлении в список префиксов.Бит A = 1 указывает, разрешено ли хостам автоматически настраивать адрес интерфейса с этим префиксом, в то время как A = 0 означает, что хосты должны получать адрес с этим префиксом через DHCPv6 или вручную.Бит L = 1 указывает, что префикс находится «на линии связи», и хост может использовать обнаружение соседей (эквивалент IPv6 ARP) для прямой отправки по сети, тогда как L = 0 указывает, что префикс «вне линии связи» и чтохосты должны отправлять весь трафик для этого префикса на маршрутизатор по умолчанию.

Короче говоря: если вы хотите знать, что IPv6-адрес находится «на связи», то вам нужно пройти список префиксов IPv6 и сравнитькаждый с адресом, а также посмотрите на L-бит, чтобы убедиться, что это префикс по ссылке.Увы, я знаю только способ просмотра BSD-системы в списке префиксов, то есть sysctl(ICMPV6CTL_ND6_PRLIST, ...).На самом деле не уверен, что если MSFT предоставит разработчикам C # что-то для этого.

Да, я понимаю, что это не полный ответ.Увы.

1 голос
/ 17 февраля 2011

В 99% случаев это просто. Все подсети в IPv6 являются префиксами / 64, поэтому, если самые левые 64 бита префикса идентичны, они находятся в одной подсети.

Теперь верно, что некоторые люди делают странные вещи и создают подсети с более длинными префиксами, но большая часть этого имеет дело с цепями точка-точка, где они используют / 126 для нумерации двух конечных точек, а затем ЗАБИРАЮТ 64, содержащий / 126. Приложение никогда не столкнется с такой ситуацией, поскольку не задействованы никакие серверы.

Нет веских причин для поддержки размеров подсетей, отличных от /64.

.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...