Restringir um IP se estiver entre um intervalo de IP
-
06-07-2019 - |
Pergunta
Ok, é sexta -feira à tarde, e eu tive uma longa semana, então apreciaria alguma ajuda! Atualmente, tenho uma lista de intervalos de IP, como segue:
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" });
Depois de obter o IP do cliente, se ele cair entre esses conjuntos de intervalos, eles precisam ser redirecionados para outro lugar.
Por exemplo,
Se alguém visitou o site com o IP 192.168.0.1
, eles teriam acesso permitido. Se eles visitaram com 145.36.1.0
, eles não teriam acesso ao acesso porque se enquadra entre o primeiro intervalo nessa lista.
Eu poderia dividir cada IP no período e descobrir onde o intervalo começa a mudar e depois fazer uma comparação, mas isso seria pesado no servidor.
Eu sei que os IPs são basicamente apenas números decimais, mas não tenho muita certeza de como isso funciona.
Alguém já passou por isso antes?
Saúde, Sean.
Solução
Converta cada endereço IP enumerar, e, em seguida, verifique se o endereço IP do usuário está entre esses 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;
}
}
Outras dicas
Eu converteria os endereços IP em números de 32 bits e, em seguida, fazia um simples> = de e <= para verificar se está no intervalo.
Por exemplo, 192.168.1.1 -> 192 * 256^3 + 168 * 256^2 + 1 * 256 + 1.
Trabalhando com seus valores, 145.36.0.0 -> 2435055616 e 145.36.0.0 -> 2435121151. SO 145.36.200.30 -> 2435106846 e cai nesse intervalo, por isso é válido. Mas 145.35.255.255 -> 2435055615 não está no intervalo (apenas), por isso falha.
Eu escrevia minha classe iPrange para que os getter/setters convertem internamente a sequência IP em um número:
new IPRange { From = "145.36.0.0", To = "145.36.255.255" }
Definiria internamente:
int from = 145036000000;
int to = 145036255255;
Em seguida, adicione um método .IsinRange (String IP) que converte o IP recebido no formulário Nome int e faz uma comparação simples.
public bool IsInRange(string ipStr)
{
int ip = ConvertIPStringToInt(ipStr);
return (from <= ip && ip <= to);
}
Dessa forma, você não precisa dividir o IPS no intervalo por períodos cada vez que é verificado.
Apenas por diversão (e alguma aparência de completude) - de outra maneira óbvia para fazer isso é garantir que você sempre use 3 dígitos para cada segmento do endereço IP quando armazenado como uma string isto é 145.36.0.0 deve ser 145.036.000 como as cordas seriam diretamente comparáveis.
E o menos óbvio seria ter uma classe de endereço IP explícita e um rolo seu próprio conjunto de lógica de comparação (estou assumindo bastante que já não há algo assim enterrado nas profundezas da estrutura .NET ...)
Eu li sobre isso alguns dias atrás.
Você pode converter e comparar seus intervalos de IP.
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
Aqui está a função ipstringtonumber que ele precisa:
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
Referências:
http://www.sqlservercentral.com/scripts/miscellanear/31036/
http://www.sqlservercentral.com/authors/scripts/kgayda/17134/