If you need to whitelist/blacklist an IP address for a client sometimes they’ll give you a subnet range rather than a list of IP addresses. If the site is being hosted in Azure then this is simple to do but if you need to check the IP address against the subnet range within the site then it’s a bit more work.

The below C# code is based on that from the answer here.

// 'https://stackoverflow.com/questions/1499269/how-to-check-if-an-ip-address-is-within-a-particular-subnet
public static bool IsInSubnet(string ipAddress, string subnetMask)
{
    IPAddress address = System.Net.IPAddress.Parse(ipAddress);

    var slashIdx = subnetMask.IndexOf("/");

    // 'We only handle netmasks in format "IP/PrefixLength".
    if (slashIdx == -1)
        throw new NotSupportedException("Only SubNetMasks with a given prefix length are supported.");

    // 'First parse the address of the netmask before the prefix length.
    var maskAddress = System.Net.IPAddress.Parse(subnetMask.Substring(0, slashIdx));

    if (maskAddress.AddressFamily != address.AddressFamily)
        // 'We got something like an IPV4-Address for an IPv6-Mask. This is not valid.
        return false;

    // 'Now find out how long the prefix is.
    int maskLength = int.Parse(subnetMask.Substring(slashIdx + 1));

    if (maskAddress.AddressFamily == AddressFamily.InterNetwork)
    {
        // 'Convert the mask address to an unsigned integer.
        var maskAddressArray = maskAddress.GetAddressBytes();
        Array.Reverse(maskAddressArray);
        var maskAddressBits = BitConverter.ToUInt32(maskAddressArray, 0);

        // 'And convert the IpAddress to an unsigned integer.
        var ipAddressArray = address.GetAddressBytes();
        Array.Reverse(ipAddressArray);
        var ipAddressBits = BitConverter.ToUInt32(ipAddressArray, 0);

        // 'Get the mask/network address as unsigned integer.
        uint mask = uint.MaxValue << (32 - maskLength);

        // 'https//stackoverflow.com/a/1499284/3085985
        // 'Bitwise And mask And MaskAddress, this should be the same as mask And IpAddress
        // 'as the end of the mask Is 0000 which leads to both addresses to end with 0000
        // 'And to start with the prefix.
        return (maskAddressBits & mask) == (ipAddressBits & mask);
    }

    if (maskAddress.AddressFamily == AddressFamily.InterNetworkV6)
    {
        // ' Convert the mask address to a BitArray.
        var maskAddressBits = new BitArray(maskAddress.GetAddressBytes());

        // 'And convert the IpAddress to a BitArray.
        var ipAddressBits = new BitArray(address.GetAddressBytes());

        if (maskAddressBits.Length != ipAddressBits.Length)
            throw new ArgumentException("Length of IP Address and Subnet Mask do not match.");

        // 'Compare the prefix bits.
        for (int maskIndex = 0; maskIndex <= maskLength - 1; maskIndex++)
        {
            if (ipAddressBits(maskIndex) != maskAddressBits(maskIndex))
                return false;
        }

        return true;
    }

    throw new NotSupportedException("Only InterNetworkV6 or InterNetwork address families are supported.");
}

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *