php5 bir CIDR maskesi bir IP eşleşen?

7 Cevap php

Ben arıyorum eşleştirmek için, yöntem (belki de ben daha önce hiç fark dahili) / basit / hızlı bir IP4 bir CIDR notasyonu maskesi dörtlü IP noktalı verilmiştir.

Ben onlar IP aralığını maç olmadığını görmek gerekir IP'ler bir grup var.

Örnek:

$ips = array('10.2.1.100', '10.2.1.101', '10.5.1.100', '1.2.3.4');

foreach($ips as $IP)
{
    if( cidr_match($IP, '10.2.0.0/16') == true )
    { print "you're in the 10.2 subnet\n"; }
}

cidr_match çözmek için ()

gerçekten basit olmak zorunda değil, ama hızlı iyi olurdu. (Bana bunu yapar armut şey göstermek için bir kişi almak olasıdır olduğum gibi, ama armut ya da benim kod dağıtılan nerede paketi yüklü olmasına bağlıdır olamaz) tek / ortak fonksiyonları inşa kullanır şey bir bonus

7 Cevap

IPv4 kullanarak Eğer sadece:

  • ip2long() uzun tamsayı içine IP'leri ve alt ağ aralığı dönüştürmek için kullanabilirsiniz
  • Bir alt ağ maskesine dönüşüyor / xx dönüştürmek
  • bir bit 've' (yani ip ve mask) yapmak 've kontrol o' sonuç = alt '

böyle bir şey çalışması gerekir:

function cidr_match($ip, $range)
{
    list ($subnet, $bits) = explode('/', $range);
    $ip = ip2long($ip);
    $subnet = ip2long($subnet);
    $mask = -1 << (32 - $bits);
    $subnet &= $mask; # nb: in case the supplied subnet wasn't correctly aligned
    return ($ip & $mask) == $subnet;
}

PHP 5.2 sonra bu yöntemi kıran birçok bulundu. Ancak aşağıdaki çözüm sürümleri 5.2 ve üstünde çalışıyor:

function cidr_match($ip, $cidr)
{
    list($subnet, $mask) = explode('/', $cidr);

    if ((ip2long($ip) & ~((1 << (32 - $mask)) - 1) ) == ip2long($subnet))
    { 
        return true;
    }

    return false;
}

Example results

cidr_match("1.2.3.4", "0.0.0.0/0"):         true
cidr_match("127.0.0.1", "127.0.0.1/32"):   true
cidr_match("127.0.0.1", "127.0.0.2/32"):   false

Source: http://www.php.net/manual/en/function.ip2long.php#82397

Bazı fonksiyonu değiştirildi:

  • explode ile bölünmüş

function cidr_match($ip, $range)
{
    list ($subnet, $bits) = explode('/', $range);
    $ip = ip2long($ip);
    $subnet = ip2long($subnet);
    $mask = -1 << (32 - $bits);
    $subnet &= $mask; 
    return ($ip & $mask) == $subnet;
}

Benim teknik alt ağı ve maske kullanarak bit eşleme bit kullanır.

function cidr_match($ip, $range){
    list ($subnet, $bits) = explode('/', $range);
    $ip = substr(IP2bin($ip),0,$bits) ;
    $subnet = substr(IP2Bin($subnet),0,$bits) ;
    return ($ip == $subnet) ;
}

function IP2Bin($ip){
    $ips = explode(".",$ip) ;
    foreach ($ips as $iptmp){
        $ipbin .= sprintf("%08b",$iptmp) ;
    }
    return $ipbin ;
}

Sadece bir not, Alnitak cevabı 32/64 bit çalışır.

İşte ülkeye göre hızlı spam koruması için bunun bir pişmiş sürümü, IP her yerde alabilirsiniz listeler olduğunu. google ülke ip listesi veya ülke ip bloğu için (burada, birini vermek gerçekten zor onu bulmak zorunda olduğu siteler sayfa gezinme: Country ip block generator)

String $ cidrs için cidr ip listesini kopyala-yapıştırın. Ve muhtemelen header.php dosyasında, sadece sayfa html önce bu kodu koyabilirsiniz.

Ayrıca ülkeye göre sayfa şablonları adsense kullanımı filtre kullanılabilir.

Bu sadece bir in-the-middle-of-the-gece-aciliyet çözüm. Bazen bir dün hızlı bir şekilde müşteri için böyle bir şey ile gelip gerekiyor, bu yüzden burada.

//++++++++++++++++++++++
//COUNTRY SPAM PROTECTOR
//speed: ~5ms @ 2000 cidrs
//comments start with #
//++++++++++++++++++++++
$cidrs=
'
#yourcountry
1.3.4.5/21
#mycountry
6.7.8.9/20
';
//$cidrs.="\n".'123.12.12.12/32';//test, your ip
$cidrs_ar=preg_split('/\s+/',$cidrs,-1,PREG_SPLIT_NO_EMPTY);
$ip=@$_SERVER['REMOTE_ADDR'];
$iplong=ip2long($ip);
//var_export($cidrs_ar);var_export($ip);var_export($iplong);
if($iplong)
  foreach($cidrs_ar as $cidr)
    {
    $ar=explode ('/', $cidr);
    $netiplong=ip2long($ar[0]);
    if($netiplong===false) continue;
    $mask=intval(@$ar[1]);
    if(!$mask) continue;
    $bitmask=-1 <<(32-$mask);
    if(($iplong & $bitmask) == ($netiplong & $bitmask))
        {
        header('Location: http://www.someotherwebsite.com/',true,303);
        exit;
        }
    }

Da kullanabilirsiniz Net_IPv4 PEAR library.

function cidr_match($ip, $net){
  include_once("Net/IPv4.php");
  $objIP = new Net_IPv4();
  return $objIP->ipInNetwork($ip, $net);
}

Ben de CIDR maskeleri karşı IP sitesini test etmek gerekiyordu. Ben gayet iyi çalışıyor, mükemmel açıklama ve kaynak kodu ile bir web sitesi buldum.

Web sitesi http://pgregg.com/blog/2009/04/php-algorithms-determining-if-an-ip-is-within-a-specific-range/

Web sitesi bir gün ortadan kalkıncaya Çünkü, burada kodu

<?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 <pgregg@pgregg.com>
 * 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;
  }

}
?>

(Ben bu geliştirmek değil, bu Paul Gregg tarafından geliştirilen (http://pgregg.com/)