Проверете дали IP е в LAN (зад защитни стени и рутери)

Ровя се в мрежата от около 5 часа и не можах да намеря решение на проблема си:

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

Така че получавам купища IP адреси от тракера и трябва да филтрирам само тези, които са в LAN.

Разбира се, училищата понякога са доста строги със защитните стени и ще има много рутери и суичове между някои компютри в училище.

Вече опитах повечето решения, неща като

 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 е достъпен през LAN.

Наистина ще се радвам на всяка помощ, защото тази функция е последната останала :)


person Squirrel    schedule 29.08.2011    source източник
comment
всички компютри, съдържащи играта, свързват ли се към вашия интернет сървър?   -  person Yahia    schedule 29.08.2011
comment
Има ограничен брой IP-адреси, които са разрешени за вътрешна употреба, частните подмрежи. Няма ли да е достатъчно идентификация? Много рядко се използват публични IP адреси и след това защитна стена, защото не искате да губите IPv4 адреси. IPv6 е съвсем различен въпрос.   -  person jishi    schedule 29.08.2011
comment
@jishi предполагаш, че мрежите в училищата са създадени според препоръките. Въпреки че частните диапазони са препоръчителни, нищо не ви пречи да използвате публични.   -  person Jonathan Dickinson    schedule 29.08.2011
comment
@ Yahia всички се свързват с един и същ тракер да, но само един от тях се свързва с html-seeder, така че всички останали да изтеглят от този компютър (по този начин спестявам честотна лента, защото играта се изтегля само от един компютър и се споделя в мрежата )   -  person Squirrel    schedule 30.08.2011
comment
@Jonathan Dickinson Е, ако са използвали публични IP адреси и за NAT, тогава вероятно имат по-големи проблеми от няколко клиента, които генерират малко повече честотна лента...   -  person jishi    schedule 30.08.2011
comment
@jishi определено, но приложението ви все пак трябва да направи всичко възможно, за да се държи предвидимо.   -  person Jonathan Dickinson    schedule 30.08.2011
comment
@Jonathan Dickinson Разбира се е хубаво, ако едно приложение може да вземе под внимание неправилни конфигурации, но не бих го нарекъл необходимост. Въпреки това има други жизнеспособни и по-стабилни решения, просто исках да дам просто решение, ако може да бъде предразположено към провал.   -  person jishi    schedule 30.08.2011
comment
@jishi - разбира се, това ще работи в 99% персентил и е наистина просто (просто проверете дали първият байт е 10 или 192).   -  person Jonathan Dickinson    schedule 30.08.2011
comment
добре, засега в офиса работи перфектно, за съжаление предполагам, че ще мога да го тествам най-рано през уикенда, но веднага ще публикувам резултатите си, благодаря отново на всички вас (особено на Джонатан Дикинсън)   -  person Squirrel    schedule 30.08.2011


Отговори (3)


Можете да се възползвате от 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;
}
person Jonathan Dickinson    schedule 29.08.2011
comment
второто решение изглежда работи, благодаря много, въпреки че не съм сигурен за TTL-решението, поправете ме, ако греша (наистина не съм сигурен), но не е ли ttl също намален при преминаване през локален превключвател или рутер? Защото ако е така, няма да влезе зад локалните превключватели? - person Squirrel; 30.08.2011
comment
@Squirrel, доколкото знам, се намалява само при преминаване на рутер (а не на комутатор или хъб); и LAN трябва да има само един рутер. Въпреки това, разтворът с маска е най-малко вероятно да даде грешни резултати. - person Jonathan Dickinson; 30.08.2011
comment
Просто проверката дали IP адресът е в същата локална мрежа всъщност не показва дали сте в локална мрежа или случайно имате интернет доставчик, който ви обслужва IP адреси. Може да сте част от /24 или дори /22 мрежа с публичен IP, тогава не сте в LAN, а просто от същия интернет доставчик. - person jishi; 30.08.2011
comment
@jishi вашият рутер ще има IP от вашия интернет доставчик; и не съм сигурен дали шлюзът може да бъде конфигуриран да "преминава" директно към интернет - дори така че вашият ISP/NS/държава така или иначе няма да може да разпредели този IP диапазон с IANA. Така че можете да го провалите от единия край, но не и от другия. - person Jonathan Dickinson; 30.08.2011
comment
Проверих го в училище, решението с IPv4 маската се получи добре. много благодаря отново - person Squirrel; 05.09.2011
comment
Може ли някой да предложи решение, което би било валидно, ако клиентът използва или ip4, или ip6? - person Watson; 16.08.2012
comment
@user190084 технически това трябва да работи с IPv6, но не съм го тествал. Получавате ли грешки? Редактиране: Поне ако премахнете заобиколното решение, специфичната за IPv4 проверка. - person Jonathan Dickinson; 17.08.2012

Обикновено всички IP адреси като 10.x.x.x (клас A) или 192.x.x.x (клас C) могат безопасно да се приемат, че са в частна локална мрежа. IP класификации

person Arun    schedule 29.08.2011
comment
Предположението е наистина лош път. Потребителите са идиоти, те правят всякакви луди неща. - person Jonathan Dickinson; 29.08.2011
comment
@Jonathan Като потребител съм обиден. Като разработчик съм съгласен. - person Rotem; 13.01.2014

Едно нещо, което бихте могли да използвате, е да опитате да комуникирате между клиенти, използвайки мултикаст. Повечето защитни стени и рутери биха блокирали мултикаст трафик (и ISP определено), което означава, че не бихте могли да се присъедините към мултикаст група, ако няма друг клиент в мрежата. Един тъп превключвател ще прехвърли трафика, превключвател от слой 3 може да го блокира или да го разреши в зависимост от конфигурацията. Така или иначе, ако превключвателят на ниво 3 го блокира, вероятно така или иначе сте в различни подмрежи, така че всички други опции също ще се провалят.

Една технология, която идва на ум, е SSDP ( http://en.wikipedia.org/wiki/Simple_Service_Discovery_Protocol ), което вярвам, че ще послужи доста добре на вашата цел. По този начин не е нужно наистина да разберете дали сте в LAN или не, просто потърсете друг възел, който активно изтегля, ако не можете да намерите такъв, започнете да изтегляте сами.

Тъй като SSDP е стандарт, използван в uPnP, вероятно ще можете да намерите прилични реализации, с които можете да работите.

person jishi    schedule 30.08.2011