Проверьте, находится ли IP-адрес в локальной сети (за брандмауэрами и маршрутизаторами)

Я просканировал в сети около 5 часов и не нашел решения для своей проблемы:

Моя компания разрабатывает обучающую игру, и я пишу автоудатчик для нее, используя Monotorrent. Игра будет использоваться в школах, но из-за того, что большинство школ имеют очень слабые интернет-соединения, в сети должен быть только один компьютер, загружаемый с сервера httpseeder, а остальные должны пиявки с одного компьютера, загружаемого с httpseed.

Итак, я получаю множество IP-адресов от трекера и должен отфильтровывать только те, которые находятся в локальной сети.

Конечно, школы иногда довольно строгие с брандмауэрами, и в некоторых школах будет много маршрутизаторов и коммутаторов.

Я уже пробовал большинство решений, например,

 NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();

    foreach (NetworkInterface iface in interfaces)
    {
        IPInterfaceProperties properties = iface.GetIPProperties();

        foreach (UnicastIPAddressInformation address in properties.UnicastAddresses)
        {
            Console.WriteLine(
                "{0} (Mask: {1})",
                address.Address,
                address.IPv4Mask
                );
        }
    }

Или аналогичные методы предоставляют только информацию о маршрутизаторе/коммутаторе/независимо.

Итак, вкратце, что я хочу сделать, это проверить, доступен ли данный IP-адрес через локальную сеть.

Я очень благодарен за любую помощь, потому что эта функция остается последней:)

Ответ 1

Вы можете воспользоваться TTL. С TTL 1 пакет не сможет сделать это в Интернете:

private static bool IsLanIP(IPAddress address)
{
    var ping = new Ping();
    var rep = ping.Send(address, 100, new byte[] { 1 }, new PingOptions()
    {
        DontFragment = true,
        Ttl = 1
    });
    return rep.Status != IPStatus.TtlExpired && rep.Status != IPStatus.TimedOut && rep.Status != IPStatus.TimeExceeded;
}

Однако помните, что он называется маской IPv4 по какой-либо причине - вы можете использовать его как один (так вот ваше алгоритмическое решение):

private static bool IsLanIP(IPAddress address)
{
    var interfaces = NetworkInterface.GetAllNetworkInterfaces();
    foreach (var iface in interfaces)
    {
        var properties = iface.GetIPProperties();
        foreach (var ifAddr in properties.UnicastAddresses)
        {
            if (ifAddr.IPv4Mask != null && 
                ifAddr.Address.AddressFamily == AddressFamily.InterNetwork &&
                CheckMask(ifAddr.Address, ifAddr.IPv4Mask, address))
                return true;
        }
    }
    return false;
}

private static bool CheckMask(IPAddress address, IPAddress mask, IPAddress target)
{
    if (mask == null)
        return false;

    var ba = address.GetAddressBytes();
    var bm = mask.GetAddressBytes();
    var bb = target.GetAddressBytes();

    if (ba.Length != bm.Length || bm.Length != bb.Length)
        return false;

    for (var i = 0; i < ba.Length; i++)
    {
        int m = bm[i];

        int a = ba[i] & m;
        int b = bb[i] & m;

        if (a != b)
            return false;
    }

    return true;
}

Ответ 2

Как правило, любые IP-адреса, такие как 10.x.x.x(класс A) или 192.x.x.x(класс C), можно смело считать внутри частной локальной сети. IP-классификации

Ответ 3

Одна вещь, которую вы могли бы использовать, - это попытаться установить связь между клиентами с помощью многоадресной рассылки. Большинство брандмауэров и маршрутизаторов будут блокировать многоадресный трафик (и ISPs наиболее определенно), что означает, что вы не сможете присоединиться к группе многоадресной рассылки, если другой клиент не находится на LAN. Тупой коммутатор будет передавать трафик, слой 3-переключатель может блокировать его или может разрешить его в зависимости от конфигурации. В любом случае, если коммутатор уровня 3 блокирует его, вы, вероятно, все равно в разных подсетях, так что все остальные параметры также потерпят неудачу.

Одной технологией, которая приходит на ум, является SSDP (http://en.wikipedia.org/wiki/Simple_Service_Discovery_Protocol), который будет служить вашей цели довольно хорошо, я верю. Таким образом, вам действительно не нужно выяснять, находитесь ли вы в локальной сети или нет, просто выполните поиск другого node, который активно загружается, если вы не можете его найти, начните загрузку самостоятельно.

Поскольку SSDP является стандартом, используемым в uPnP, вы, вероятно, сможете найти достойные реализации, с которыми вы могли бы работать.