Restricción de una IP si está entre un rango de IP
-
06-07-2019 - |
Pregunta
Ok, es viernes por la tarde, y he tenido una semana larga, ¡agradecería algo de ayuda! Actualmente, tengo una lista de rangos de IP, de la siguiente manera:
List<IPRange> ipRanges = new List<IPRange>();
ipRanges.Add(new IPRange { From = "145.36.0.0", To = "145.36.255.255" });
ipRanges.Add(new IPRange { From = "194.183.227.184", To = "194.183.227.191" });
ipRanges.Add(new IPRange { From = "193.131.192.0", To = "193.131.223.255" });
Después de obtener la IP del cliente, si cae en algún lugar entre estos conjuntos de rangos, deben redirigirse a otro lugar.
Por ejemplo,
Si alguien visitara el sitio con la IP 192.168.0.1
, se les permitiría el acceso.
Si visitaron con 145.36.1.0
, no se les permitiría el acceso porque se encuentra entre el primer rango en esa lista.
Podría dividir cada IP por el período y determinar dónde comienza a cambiar el rango, luego hacer una comparación, pero eso sería pesado en el servidor.
Sé que las IP son básicamente números decimales, pero no estoy realmente seguro de cómo funciona.
¿Alguien ha encontrado esto antes?
Saludos, Sean.
Solución
Convierta cada dirección IP para numerar , y luego verifique si la dirección IP del usuario está entre esos números.
public double Dot2LongIP(string DottedIP)
{
int i;
string [] arrDec;
double num = 0;
if (DottedIP == "")
{
return 0;
}
else
{
arrDec = DottedIP.Split('.');
for(i = arrDec.Length - 1; i >= 0 ; i --)
{
num += ((int.Parse(arrDec[i])%256) * Math.Pow(256 ,(3 - i )));
}
return num;
}
}
Otros consejos
Convertiría las direcciones IP a números de 32 bits y luego haría un simple > = From y < = Para verificar si está dentro del rango.
Por ejemplo, 192.168.1.1 - > 192 * 256 ^ 3 + 168 * 256 ^ 2 + 1 * 256 + 1.
Trabajando con sus valores, 145.36.0.0 - > 2435055616 y 145.36.0.0 - & Gt; 2435121151. Entonces 145.36.200.30 - & Gt; 2435106846, y cae en ese rango, por lo que es válido. Pero 145.35.255.255 - & Gt; 2435055615 no está en el rango (apenas), por lo que falla.
Escribiría mi clase de IPRange para que los captadores / establecedores conviertan internamente la cadena de IP en un número:
new IPRange { From = "145.36.0.0", To = "145.36.255.255" }
Establecería internamente:
int from = 145036000000;
int to = 145036255255;
Luego agregue un método .IsInRange (string ip) que convierta la IP entrante al nombre int form y haga una comparación simple.
public bool IsInRange(string ipStr)
{
int ip = ConvertIPStringToInt(ipStr);
return (from <= ip && ip <= to);
}
De esa manera, no tiene que dividir las IP en el rango por períodos cada vez que se verifica.
Solo por diversión (y cierta apariencia de integridad): la otra forma obvia de hacerlo es asegurarse de que siempre use 3 dígitos para cada segmento de la dirección IP cuando se almacena como una cadena, es decir, 145.36.0.0 debería ser 145.036. 000.000 - de esa manera las cadenas serían directamente comparables.
Y lo menos obvio sería tener una clase de dirección IP explícita y un rollo de su propio conjunto de lógica de comparación (supongo precipitadamente que ya no hay algo como esto enterrado en las profundidades del marco .NET. ..)
Leí sobre esto hace unos días.
Puede convertir sus rangos de IP y compararlos.
IF exists (SELECT * from dbo.sysobjects
WHERE id = object_id(N'[dbo].[IsPrivateIP]')
AND OBJECTPROPERTY(id, N'IsScalarFunction') = 1)
DROP FUNCTION [dbo].[IsPrivateIP]
GO
CREATE FUNCTION dbo.IsPrivateIP( @vcIPAddress varchar(15))
/**************************************************************************
DESCRIPTION: Returns Numeric IP if not private, otherwise returns null
PARAMETERS:
@vcIPAddress - The string containing a valid IP
RETURNS: IP converted to bigint or null if a private IP
USAGE: SELECT dbo.IsPrivateIP( '207.158.26.10')
DEPENDANCIES: dbo.IPStringToNumber() function
AUTHOR: Karen Gayda
DATE: 06/11/2003
MODIFICATION HISTORY:
WHO DATE DESCRIPTION
--- ---------- ---------------------------------------------------
***************************************************************************/
RETURNS bigint
AS
BEGIN
DECLARE @biClassALo bigint ,
@biClassAHi bigint ,
@biClassBLo bigint ,
@biClassBHi bigint ,
@biClassCLo bigint ,
@biClassCHi bigint ,
@biIP bigint,
@bTemp int
SET @biClassALo = 167772160
SET @biClassAHi = 169549375
SET @biClassBLo = 2885681152
SET @biClassBHi = 2887778303
SET @biClassCLo = 3232235520
SET @biClassCHi = 3232301055
SET @biIP = dbo.IPStringToNumber(@vcIPAddress)
IF @biIP BETWEEN @biClassALo AND @biClassAHi OR @biIP BETWEEN @biClassBLo AND @biClassBHi
OR @biIP BETWEEN @biClassCLo AND @biClassCHi
SET @biIP = NULL
RETURN @biIP
END
GO
Aquí está la función IPStringToNumber que necesita:
IF exists (SELECT * from dbo.sysobjects
WHERE id = object_id(N'[dbo].[IPStringToNumber]')
AND OBJECTPROPERTY(id, N'IsScalarFunction') = 1)
DROP FUNCTION [dbo].[IPStringToNumber]
GO
CREATE FUNCTION dbo.IPStringToNumber( @vcIPAddress varchar(15))
/**************************************************************************
DESCRIPTION: Returns Numeric IP, otherwise returns null
PARAMETERS:
@vcIPAddress - The string containing a valid IP
RETURNS: IP converted to bigint or null if not a valid IP
USAGE: SELECT dbo.IPStringToNumber( '10.255.255.255')
AUTHOR: Karen Gayda
DATE: 06/11/2003
MODIFICATION HISTORY:
WHO DATE DESCRIPTION
--- ---------- ---------------------------------------------------
***************************************************************************/
RETURNS bigint
AS
BEGIN
DECLARE
@biOctetA bigint,
@biOctetB bigint,
@biOctetC bigint,
@biOctetD bigint,
@biIP bigint
DECLARE @tblArray TABLE
(
OctetID smallint, --Array index
Octet bigint --Array element contents
)
--split the IP string and insert each octet into a table row
INSERT INTO @tblArray
SELECT ElementID, Convert(bigint,Element) FROM dbo.Split(@vcIPAddress, '.')
--check that there are four octets and that they are within valid ranges
IF (SELECT COUNT(*) FROM @tblArray WHERE Octet BETWEEN 0 AND 255) = 4
BEGIN
SET @biOctetA = (SELECT (Octet * 256 * 256 * 256) FROM @tblArray WHERE OctetID = 1)
SET @biOctetB = (SELECT (Octet * 256 * 256 ) FROM @tblArray WHERE OctetID = 2)
SET @biOctetC = (SELECT (Octet * 256 ) FROM @tblArray WHERE OctetID = 3)
SET @biOctetD = (SELECT (Octet) FROM @tblArray WHERE OctetID = 4)
SET @biIP = @biOctetA + @biOctetB + @biOctetC + @biOctetD
END
RETURN(@biIP)
END
Referencias:
http://www.sqlservercentral.com/scripts/Miscellaneous/31036/
http://www.sqlservercentral.com/Authors/Scripts/kgayda/ 17134 /