2

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?

Knaģis
  • 20,827
  • 7
  • 66
  • 80
Exitos
  • 29,230
  • 38
  • 123
  • 178

4 Answers4

3

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.

Eric Sassaman
  • 1,401
  • 1
  • 18
  • 23
CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
1
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;
    }
Pabuc
  • 5,528
  • 7
  • 37
  • 52
1

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

JP Hellemons
  • 5,977
  • 11
  • 63
  • 128
0

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;
}
Adrian Toman
  • 11,316
  • 5
  • 48
  • 62