Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if IP is in LAN (behind firewalls and routers)

I've been crawling in the web for about 5 hours now and couldn't find a solution for my problem:

My company is developing an educational game and I'm writing an autoupdater for it using Monotorrent. The game will be used in schools, but because most schools only have very weak internet connections there should only be one computer in the network that downloads from a httpseeder, and the others should leech from the one computer that is downloading from the httpseed.

So I get loads of IP-addresses from the tracker and need to filter out only the ones that are in the LAN.

Of course schools are sometimes quite strict with firewalls and there will be loads of routers and switches between some computers in a school.

I've already tried most solutions, things like

 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
                );
        }
    }

Or similar techniques only deliver the information of the router/switch/whatever.

So in a nutshell, what I want to do is check if a given IP is accessible via LAN.

I'd really appreciate any help because this feature is the last one remaining :)

like image 329
Squirrel Avatar asked Aug 29 '11 15:08

Squirrel


1 Answers

You could take advantage of TTL. With a TTL of 1 the packet won't be able to make it to the internet:

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;
}

However, remember that it is called an IPv4 mask for a reason - you can use it as one (so here is your algorithmic solution):

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;
}
like image 73
Jonathan Dickinson Avatar answered Oct 01 '22 03:10

Jonathan Dickinson