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.

Foi útil?

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/

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top