2012-07-10 15 views
5

Tengo un script donde los procesadores de pagos vienen con confirmaciones de pago. Para hacer que la página es segura, ya que se puede acceder a la información del pedido y la otra materia relacionada con el usuario, que tenía que limitar los acceso por IP (/ 24) como sigue:¿Conoces una secuencia de comandos php simple para arrojar 403, después de la verificación ip?

$ipAllowed = array(
'192.192.192', 
'172.172.172' 
); 
$ipAllowed = str_replace(".", "\.", implode("|", $ipAllowed)); 

if(!preg_match("/^($ipAllowed)\.[0-9]{1,3}$/", $_SERVER['REMOTE_ADDR'])){ 
    header('HTTP/1.0 403 Forbidden'); 
    die('You are not allowed to access this file.'); 
} 

* la década de IP son sólo como ejemplo

Antes solía:

if(!in_array(@$_SERVER['REMOTE_ADDR'], array('ips here'))); //only works with full ip 

el in_array era mucho más ordenado y luego el que yo uso ahora, pero necesito algo que funciona con/24 ips, o incluso con los dos!

¿Sabes algo que funciona mejor/más rápido, es confiable y mucho más limpio?

@ rap-2-H como usted dijo esta es la versión más limpio que funciona con plena ip,/24 o incluso/16

$ipAllowed = array('192.168.1.153' '172.172.172'); 
$allowed = false; 

foreach($ipAllowed as $ip): 
    if(strpos($_SERVER['REMOTE_ADDR'], $ip) === 0) $allowed = true; 
endforeach; 

if (!$allowed) { 
    header('HTTP/1.0 403 Forbidden'); 
    die('You are not allowed to access this file.'); 
} 
+0

Espero que tenga otras medidas de seguridad también. IP es bueno como defensa en profundidad, pero evitaría confiar en él como única medida. – CodesInChaos

+0

¡sí! después, todo el método comienza a calcular los parámetros POST y actúa en consecuencia (también se envía un hash de todos los parámetros con una clave de cifrado). Podría confiar solo en eso, pero quiero estar a salvo. – amstegraf

+0

"también se envía un hash de todos los parámetros con una clave de cifrado" ¿Cómo funciona el hash con clave? ¿Es algo bueno, como HMAC, o algo roto como H (k || m)? – CodesInChaos

Respuesta

11

Usted puede intentar algo como esto:

$ipAllowed = array('192.192.192', '172.172.172'); 

$allowed = false; 
foreach($ipAllowed as $ip) { 
    if (strpos($_SERVER['REMOTE_ADDR'], $ip) !== false) { 
     $allowed = true; 
    } 
} 
if (!$allowed) { 
    header('HTTP/1.0 403 Forbidden'); 
    die('You are not allowed to access this file.');  
} 

Así que solo puede tener fragmento de IP en su matriz $ipAllowed. No es muy elegante, pero debería funcionar ...

+0

Usar strpos es en realidad una mejor solución que piratear a ciegas el último octeto, como lo hice yo. –

+0

esto parece adecuado, pero también da acceso a toda la clase ip, ya que 172.0.0.0 también devuelve verdadero o 0. ¿No? – amstegraf

+0

'172.172.172.1' y' 1.172.172.172' serán permitidos con este código. Si solo desea '172.172.172.X' puede reemplazar una condición como esta' if (strpos ($ _ SERVER ['REMOTE_ADDR'], $ ip) === 0) ' –

1

Utilice esta función para comprobar si está especificado en IP es la red:

por ejemplo: 192.168.1.25 es en la red 192.168.1.0/24

<?php 

/* 
* ip_in_range.php - Function to determine if an IP is located in a 
*     specific range as specified via several alternative 
*     formats. 
* 
* Network ranges can be specified as: 
* 1. Wildcard format:  1.2.3.* 
* 2. CIDR format:   1.2.3/24 OR 1.2.3.4/255.255.255.0 
* 3. Start-End IP format: 1.2.3.0-1.2.3.255 
* 
* Return value BOOLEAN : ip_in_range($ip, $range); 
* 
* Copyright 2008: Paul Gregg <[email protected]> 
* 10 January 2008 
* Version: 1.2 
* 
* Source website: http://www.pgregg.com/projects/php/ip_in_range/ 
* Version 1.2 
* 
* This software is Donationware - if you feel you have benefited from 
* the use of this tool then please consider a donation. The value of 
* which is entirely left up to your discretion. 
* http://www.pgregg.com/donate/ 
* 
* Please do not remove this header, or source attibution from this file. 
*/ 


// decbin32 
// In order to simplify working with IP addresses (in binary) and their 
// netmasks, it is easier to ensure that the binary strings are padded 
// with zeros out to 32 characters - IP addresses are 32 bit numbers 
Function decbin32 ($dec) { 
    return str_pad(decbin($dec), 32, '0', STR_PAD_LEFT); 
} 

// ip_in_range 
// This function takes 2 arguments, an IP address and a "range" in several 
// different formats. 
// Network ranges can be specified as: 
// 1. Wildcard format:  1.2.3.* 
// 2. CIDR format:   1.2.3/24 OR 1.2.3.4/255.255.255.0 
// 3. Start-End IP format: 1.2.3.0-1.2.3.255 
// The function will return true if the supplied IP is within the range. 
// Note little validation is done on the range inputs - it expects you to 
// use one of the above 3 formats. 
Function ip_in_range($ip, $range) { 
    if (strpos($range, '/') !== false) { 
    // $range is in IP/NETMASK format 
    list($range, $netmask) = explode('/', $range, 2); 
    if (strpos($netmask, '.') !== false) { 
     // $netmask is a 255.255.0.0 format 
     $netmask = str_replace('*', '0', $netmask); 
     $netmask_dec = ip2long($netmask); 
     return ((ip2long($ip) & $netmask_dec) == (ip2long($range) & $netmask_dec)); 
    } else { 
     // $netmask is a CIDR size block 
     // fix the range argument 
     $x = explode('.', $range); 
     while(count($x)<4) $x[] = '0'; 
     list($a,$b,$c,$d) = $x; 
     $range = sprintf("%u.%u.%u.%u", empty($a)?'0':$a, empty($b)?'0':$b,empty($c)?'0':$c,empty($d)?'0':$d); 
     $range_dec = ip2long($range); 
     $ip_dec = ip2long($ip); 

     # Strategy 1 - Create the netmask with 'netmask' 1s and then fill it to 32 with 0s 
     #$netmask_dec = bindec(str_pad('', $netmask, '1') . str_pad('', 32-$netmask, '0')); 

     # Strategy 2 - Use math to create it 
     $wildcard_dec = pow(2, (32-$netmask)) - 1; 
     $netmask_dec = ~ $wildcard_dec; 

     return (($ip_dec & $netmask_dec) == ($range_dec & $netmask_dec)); 
    } 
    } else { 
    // range might be 255.255.*.* or 1.2.3.0-1.2.3.255 
    if (strpos($range, '*') !==false) { // a.b.*.* format 
     // Just convert to A-B format by setting * to 0 for A and 255 for B 
     $lower = str_replace('*', '0', $range); 
     $upper = str_replace('*', '255', $range); 
     $range = "$lower-$upper"; 
    } 

    if (strpos($range, '-')!==false) { // A-B format 
     list($lower, $upper) = explode('-', $range, 2); 
     $lower_dec = (float)sprintf("%u",ip2long($lower)); 
     $upper_dec = (float)sprintf("%u",ip2long($upper)); 
     $ip_dec = (float)sprintf("%u",ip2long($ip)); 
     return (($ip_dec>=$lower_dec) && ($ip_dec<=$upper_dec)); 
    } 

    echo 'Range argument is not in 1.2.3.4/24 or 1.2.3.4/255.255.255.0 format'; 
    return false; 
    } 

} 
?> 
+2

No olvide que dijo que son/24 subredes que no completan las direcciones IP. Creo que probablemente tendrías que pasar el ipAllowed y comprobar si la dirección era válida en base a 'strpos'. –

+0

no, porque "192.192.192" nunca será REMOTE_ADDR, ya que las direcciones IP contienen cuatro octetos. –

+0

y tenga en cuenta que $ _SERVER ['REMOTE_ADDR'] puede ser falso, así que tenga cuidado con esto para deshacerse de los ataques – jondinham

0
<?php 

$ips = array(
    '192.160.0', 
    '172.0.0' 
); 

/** 
* Strip off the last number. 
*/ 
$_SERVER['REMOTE_ADDR'] = '192.160.0.254'; 
$ip = preg_replace('~\.(\d+)$~', '', $_SERVER['REMOTE_ADDR']); 

if(in_array($ip, $ips)) { 
    var_dump('allowed'); 
} 
+0

¡sí! hace lo que debería, pero ese fue exactamente mi problema de que debería funcionar de manera más inteligente y rápida. Como strpos es más rápido que preg y cortar la última parte, como yo también lo hice, no funciona en ningún caso. – amstegraf

Cuestiones relacionadas