简体   繁体   中英

Easiest way to check ip address against a range of values using c#

We are writing a feature that allows an administrator to block/allow ranges of ip addresses.

Is this easy enough to do with c#?

I was thinking of looking at each number [here].[here].[here].[here] and then mathing it with the ranges and just seeing if each number was between the two?

Will that work for standard ip v4 addresses?

I'd convert them to integers and then compare the integer. But what's correct depends on how you define ranges.

UInt32 Ip4ToInt(string ip)
{
  UInt32[] parts=ip.Split('.').Select(s=>UInt32.Parse(s)).ToArray();
  if (parts.Length != 4)
    throw new ArgumentException("InvalidIP");
  return (parts[0]<<24) | (parts[1]<<16) | (parts[2]<<8) | parts[3];
}

For example should 1.1.1.99 be part of the range 1.1.1.1 - 1.1.2.2 ? When comparing each group it isn't, when comparing the integers it is.

public static bool CheckIfIpValid(string allowedStartIp, string allowedEndIp, string ip)
        {
            // if both start and end ip's are null, every user with these credential can log in, no ip restriction needed.

        if (string.IsNullOrEmpty(allowedStartIp) && string.IsNullOrEmpty(allowedEndIp))
            return true;
        bool isStartNull = string.IsNullOrEmpty(allowedStartIp),
            isEndNull = string.IsNullOrEmpty(allowedEndIp);
        string[] startIpBlocks, endIpBlocks, userIp = ip.Split('.');
        if (!string.IsNullOrEmpty(allowedStartIp))
            startIpBlocks = allowedStartIp.Split('.');
        else
            startIpBlocks = "0.0.0.0".Split('.');
        if (!string.IsNullOrEmpty(allowedEndIp))
            endIpBlocks = allowedEndIp.Split('.');
        else
            endIpBlocks = "999.999.999.999".Split('.');

        for (int i = 0; i < userIp.Length; i++)
        {
            // if current block is smaller than allowed minimum, ip is not valid.
            if (Convert.ToInt32(userIp[i]) < Convert.ToInt32(startIpBlocks[i]))
                return false;
            // if current block is greater than allowed maximum, ip is not valid.
            else if (Convert.ToInt32(userIp[i]) > Convert.ToInt32(endIpBlocks[i]))
                return false;
            // if current block is greater than allowed minimum, ip is valid.
            else if ((Convert.ToInt32(userIp[i]) > Convert.ToInt32(startIpBlocks[i])) && !isStartNull)
                return true;

        }
        return true;
    }

I know that System.Net.IPAddress.Address is deprecated But I think that this is the easiest way:

bool result = false;

System.Net.IPAddress iStart = System.Net.IPAddress.Parse(ipStart);
System.Net.IPAddress iEnd = System.Net.IPAddress.Parse(ipEnd);
System.Net.IPAddress iIp = System.Net.IPAddress.Parse(ip);

if (iStart.Address <= iIp.Address && iEnd.Address >= iIp.Address)
{
    result = true;
}

ps. the ipStart, ipEnd, ip are strings. example: 127.0.0.1

Recently, I need to do something similar in ASP.NET Core. I went with the approach of using System.Net.IPAddress to express the IP addresses as a byte array. I then compared elements in the arrays to see if the subject IP address is within the range. This is a similar approach to answer given by CodesInChaos and Pabuc.

System.Net.IPAddress.TryParse(ipAddressRule.StartIpAddress, out var startIpAddress);
System.Net.IPAddress.TryParse(ipAddressRule.EndIpAddress, out var endIpAddress);

if (IsWithinAllowedIpAddresses(clientIpAddress.GetAddressBytes(), startIpAddress.GetAddressBytes(), endIpAddress.GetAddressBytes()))
{
     ...
}



public bool IsWithinAllowedIpAddresses(byte[] ipAddress, byte[] startAllowIpAddress, byte[] endAllowIpAddress)
{
    if (ipAddress.Length != startAllowIpAddress.Length)
    {
        throw new ArgumentException();
    }
    if (ipAddress.Length != endAllowIpAddress.Length)
    {
        throw new ArgumentException();
    }

    for (int i = 0; i < ipAddress.Length; i++)
    {
        if (ipAddress[i] < startAllowIpAddress[I])
        {
            return false;
        }
        if (ipAddress[i] > endAllowIpAddress[I])
        {
            return false;
        }
    }

    return true;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM