PHP IPv6 adresleri ile çalışma

5 Cevap php

Biraz iyice çevresinde arama sonra ben IPv6 işlemek için PHP fonksiyonları hafif bir eksikliği fark ettim. Benim kendi kişisel tatmin için ben geçişine yardımcı olmak için birkaç işlevleri yarattı.

IPv6ToLong() function buraya kadar getirdi için geçici bir çözümdür: How to store IPv6-compatible address in a relational database. Bu iki tamsayılar için IP bölmek ve onları bir diziye dönecektir.

/**
 * Convert an IPv4 address to IPv6
 *
 * @param string IP Address in dot notation (192.168.1.100)
 * @return string IPv6 formatted address or false if invalid input
 */
function IPv4To6($Ip) {
    static $Mask = '::ffff:'; // This tells IPv6 it has an IPv4 address
    $IPv6 = (strpos($Ip, '::') === 0);
    $IPv4 = (strpos($Ip, '.') > 0);

    if (!$IPv4 && !$IPv6) return false;
    if ($IPv6 && $IPv4) $Ip = substr($Ip, strrpos($Ip, ':')+1); // Strip IPv4 Compatibility notation
    elseif (!$IPv4) return $Ip; // Seems to be IPv6 already?
    $Ip = array_pad(explode('.', $Ip), 4, 0);
    if (count($Ip) > 4) return false;
    for ($i = 0; $i < 4; $i++) if ($Ip[$i] > 255) return false;

    $Part7 = base_convert(($Ip[0] * 256) + $Ip[1], 10, 16);
    $Part8 = base_convert(($Ip[2] * 256) + $Ip[3], 10, 16);
    return $Mask.$Part7.':'.$Part8;
}

/**
 * Replace '::' with appropriate number of ':0'
 */
function ExpandIPv6Notation($Ip) {
    if (strpos($Ip, '::') !== false)
    	$Ip = str_replace('::', str_repeat(':0', 8 - substr_count($Ip, ':')).':', $Ip);
    if (strpos($Ip, ':') === 0) $Ip = '0'.$Ip;
    return $Ip;
}

/**
 * Convert IPv6 address to an integer
 *
 * Optionally split in to two parts.
 *
 * @see http://stackoverflow.com/questions/420680/
 */
function IPv6ToLong($Ip, $DatabaseParts= 2) {
    $Ip = ExpandIPv6Notation($Ip);
    $Parts = explode(':', $Ip);
    $Ip = array('', '');
    for ($i = 0; $i < 4; $i++) $Ip[0] .= str_pad(base_convert($Parts[$i], 16, 2), 16, 0, STR_PAD_LEFT);
    for ($i = 4; $i < 8; $i++) $Ip[1] .= str_pad(base_convert($Parts[$i], 16, 2), 16, 0, STR_PAD_LEFT);

    if ($DatabaseParts == 2)
            return array(base_convert($Ip[0], 2, 10), base_convert($Ip[1], 2, 10));
    else    return base_convert($Ip[0], 2, 10) + base_convert($Ip[1], 2, 10);
}

Bu fonksiyonlar için ben genellikle önce bu fonksiyonu çağırarak bunları uygulamak:

/**
 * Attempt to find the client's IP Address
 *
 * @param bool Should the IP be converted using ip2long?
 * @return string|long The IP Address
 */
function GetRealRemoteIp($ForDatabase= false, $DatabaseParts= 2) {
    $Ip = '0.0.0.0';
    if (isset($_SERVER['HTTP_CLIENT_IP']) && $_SERVER['HTTP_CLIENT_IP'] != '')
    	$Ip = $_SERVER['HTTP_CLIENT_IP'];
    elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR'] != '')
    	$Ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    elseif (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] != '')
    	$Ip = $_SERVER['REMOTE_ADDR'];
    if (($CommaPos = strpos($Ip, ',')) > 0)
    	$Ip = substr($Ip, 0, ($CommaPos - 1));

    $Ip = IPv4To6($Ip);
    return ($ForDatabase ? IPv6ToLong($Ip, $DatabaseParts) : $Ip);
}

Ben burada tekerleği yeniden yaşıyorum veya yanlış bir şey yaptık eğer birisi bana lütfen söyle.

Bu uygulama IPv6 IPv4 dönüştürür. Herhangi bir IPv6 o dokunmaz adresi.

5 Cevap

Peki inet_ntop() ? Then instead of chopping things into integers, you just use a varbinary(16) bunu saklamak için.

PHP.net 's Filter extension adresini kontrol için yararlı olabilir ki, some constants IPv4 ve IPv6 adresleri eşleşen içerir. Ama herhangi bir dönüştürme programları görmedim.

) Ayrıca mysql (16), bir ikili adresini saklamak, böylece (IPv6ToLong ikili olarak çıktı bunu için bir seçenek olmalıdır.

Bu gerçekten web sunucuları etkin birçok IPv6 rapor, özellikle PHP yerel olarak ilave edilmesi gereken bir şey, :: FFFF olduğu: istemci IP olarak 1.2.3.4 ve ip2long ile uyumsuz, ve bir sürü şey kıracak.

İşte filter_var kullanarak alternatif bir fonksiyon (PHP> = 5.2) olduğu

function IPv4To6($ip) {
 if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === true) {
  if (strpos($ip, '.') > 0) {
   $ip = substr($ip, strrpos($ip, ':')+1);
  } else { //native ipv6
   return $ip;
  }
 }
 $is_v4 = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
 if (!$is_v4) { return false; }
 $iparr = array_pad(explode('.', $ip), 4, 0);
    $Part7 = base_convert(($iparr[0] * 256) + $iparr[1], 10, 16);
    $Part8 = base_convert(($iparr[2] * 256) + $iparr[3], 10, 16);
    return '::ffff:'.$Part7.':'.$Part8;
}

Geri gidiyor, ben iki işlevi, dtr_pton ve dtr_ntop IPv4 hem de IPv6 ile çalışır yazdı. Bu yazdırılabilir ve ikili arasında ileri ve geri çevirebiliriz olacaktır.

Verilen argümanı geçerli IPv4 veya geçerli IPv6 ise ilk fonksiyon, dtr_pton kontrol edecektir. Sonucuna bağlı olarak, bir özel durum olabilir, ya da IP ikili gösterimi iade edilebilir. Bu fonksiyonu kullanarak, daha sonra (alt ağ / whathaveyou için) sonucu karşı AND'ing veya OR'ing gerçekleştirebilirsiniz. Ben size veritabanında bu depolamak öneririm VARBINARY(39) veya VARCHAR(39) gibi.

/**
* dtr_pton
*
* Converts a printable IP into an unpacked binary string
*
* @author Mike Mackintosh - mike@bakeryphp.com
* @param string $ip
* @return string $bin
*/
function dtr_pton( $ip ){

    if(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)){
        return current( unpack( "A4", inet_pton( $ip ) ) );
    }
    elseif(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)){
        return current( unpack( "A16", inet_pton( $ip ) ) );
    }

    throw new \Exception("Please supply a valid IPv4 or IPv6 address");

    return false;
}

İkinci fonksiyon, dtr_ntop geri yazdırılabilir IP adresine IP ikili gösterimine dönüştürmek olacaktır.

/**
* dtr_ntop
*
* Converts an unpacked binary string into a printable IP
*
* @author Mike Mackintosh - mike@bakeryphp.com
* @param string $str
* @return string $ip
*/
function dtr_ntop( $str ){
    if( strlen( $str ) == 16 OR strlen( $str ) == 4 ){
        return inet_ntop( pack( "A".strlen( $str ) , $str ) );
    }

    throw new \Exception( "Please provide a 4 or 16 byte string" );

    return false;
}

Ayrıca, burada IPv6 adreslerini genişleyen hızlı bir yoludur found on StackOverflow

function expand($ip){
    $hex = unpack("H*hex", inet_pton($ip));         
    $ip = substr(preg_replace("/([A-f0-9]{4})/", "$1:", $hex['hex']), 0, -1);

    return $ip;
}

Ayrıca, konuyla ilgili iyi bir okuma HighOnPHP: 5 Tips for Working With IPv6 in PHP de bulunamadı. Bu makalede, GitHub: mikemackintosh\dTR-IP bulunabilir nesne yönelimli sınıfında, yukarıda tarif edilen yöntemlerden bazılarını kullanarak