АСѾԐД Создание и продвижение сайтов

Fast Site Engine

CMS для сайтов

Создать сайт

Карта сайта
Переходим на Линукс
Политика конфиденциальности
Сделать сайт на основе Fast Site Engine

Установка
Документация
Список изменений
Лицензионное соглашение

Скачать
О движкеОбо мнеДеятельностьПортфолиоКонтакты

PHP класс для обработки IP адресов

В классе заложены все минимально необходимые функции для обработки IP адресов на PHP (Internet Protocol address (IP address)), по умолчанию приводит адреса к короткому(сжатому) виду, в том числе переводя IPv4 адреса зашифрованные в IPv6 адресе к чистому IPv4 виду. Дополнительно преобразовывает в long числа для удобного хранения и сравнения.

В конце страницы приведу функцию благодаря которой проверял работоспособность и сгенерировал диапазоны масок IP адресов разной версии, дополнительно в них объясню как банить IPv4 и IPv6 адреса. На странице преобразования IP адресов, демонстрирующих работу библиотеки, можно проверить как будет распознана та или иная запись..

PHP класс сделан в большей части статическим и самодостаточным, для возможности использования без создания объекта и в любом месте. Для сравнения диапазонов используется расширение PHP BCMath из-за диапазонов выходящих за пределы int64 (IPv6). Насколько могу судить, в данный момент BCMath по умолчанию установлено на большинстве серверов.

Функции класса ip

Подключение библиотеки:
require D.'deny/ip.php';
Служебные функции помечены таким цветом.

public переменные

$ip->cidr='' //CIDR
$ip->first='' //IP v4 или v6 в сжатой форме
$ip->last='' //Если задан диапазон - второй адрес (конец диапазона)
$ip->firstlong='' //IP в виде long числа
$ip->lastlong='' 
Переменные станут доступны после создания экземпляра класса
$ip=new ip('127.0.0.1');
$ip=new ip('ffff::f0f0');
ссылка-якорь на переменные

new ip($s) - создание объекта

$s - строка содержащая IP адрес/а.
Вызов метода __construct() класса.
Всеяден, принимает как единичные IP адреса в любой форме, 
так и диапазоны через минус(тире) - или сидр(CIDR).
Сжимает IPv6 к короткому виду, преобразует IPv4 закодированные в IPv6 к их IPv4 виду.
Примеры:
Равнозначны и приведут IP к виду 192.168.1.2
$ip=new ip('0000:0000:0000:0000:0000:ffff:c0a8:0102');
$ip=new ip('0:0:0:0:0:ffff:c0a8:102'); //Укороченный
$ip=new ip('::ffff:c0a8:102'); //IPv6 Compressed address (short) сжатый уплотненный
$ip=new ip('::ffff:192.168.1.2'); //Mapped address
$ip=new ip('2002:c0a8:58fe::'); //Маршрутизация IPv6 в IPv4 - 
  маршрутный адрес роутеров/маршрутизаторов..
echo $ip->first; //192.168.1.2
$ip=new ip('fe80:0000:0000:0000:c1f5:6fc7:eef9:3341');
echo $ip->first; //fe80::c1f5:6fc7:eef9:3341
Диапазон адресов
$ip=new ip('192.168.0.0 - 192.168.255.255');
$ip=new ip('192.168.');
$ip=new ip('192.168');
echo $ip->first,' - ',$ip->last; //192.168.0.0 - 192.168.255.255
$ip=new ip('fe80::c1f5:6fc7:eef9:3341 - fe80::c1f5:6fc7:eef9:3341');
$ip=new ip('fe80:ff:c1f5:6fc7:* - fe80:ff:c1f5:6fc7:eef9:3341');
$ip=new ip('fe80:ff:c1f5:6fc7:*');
$ip=new ip('fe80:ff:c1f5:6fc7');
И в виде long
$ip=new ip('2130706431 - 22312312312321334534534');
CIDR диапазон адресов
$ip=new ip('192.168.1.2/16'); //mask = 255.255.0.0
$ip=new ip('192.168/16');
echo $ip->first,' - ',$ip->last; //192.168.0.0 - 192.168.255.255
$ip=new ip('fe80:1111:1222:1333:c1f5:6fc7:eef9:3341/64');
//mask = ffff:ffff:ffff:ffff:0000:0000:0000:0000
//fe80:1111:1222:1333:0000:0000:0000:0000 - fe80:1111:1222:1333:ffff:ffff:ffff:ffff
echo $ip->first,' - ',$ip->last; 
//fe80:1111:1222:1333:: - fe80:1111:1222:1333:ffff:ffff:ffff:ffff
Как уже заметили, IP адреса можно сокращать, избегайте употреблять
  с сокращением IPv6 :: функция не будет его дополнять до полной формы, 
  что приведёт к ошибке в обработке.
Например, если мы захотим заблокировать одну из подсетей Роскомнадзора, 
 равнозначно можно записать это так:
217.106.0.0 - 217.106.255.255 = 217.106.0.0/16 = 217.106./16 = 217.106/16 = 217.106.* = 
217.106 = 217.106.0 - 217.106.255
Ещё примеры:
10.0.0.0 - 10.255.255.255 = 10/8 = 10. = 10
192.168.0.0 - 192.168.255.255 = 192.168/16 = 192.168
1.0.0.15 - 1.255.255.25 = 1.* = 1. - 1. =  1.*.*.15 - 1.*.*.25
1.2.3.0 - 1.2.3.255 = 1.2.3.0/24 = 1.2.3/24 = 1.2.3.*
1.2.0.0 - 1.2.255.255 = 1.2.0.0/16 = 1.2/16 = 1.2.*
1.0.0.0 - 1.255.255.255 = 1.0.0.0/8  = 1/8 = 1.*
ссылка-якорь на конструктор new ip

ip::cidr2bin($i,$v=4) - преобразует CIDR с бинарный вид

$i - число, CIDR.
$v - число, версия протокола IPv4 или IPv6.
CIDR - Classless Inter-Domain Routing - Бесклассовая междоменная маршрутизация
echo ip::cidr2bin(16); //11111111111111110000000000000000 [32]
echo ip::cidr2bin(16,6); //11111111111111110000...00000000 [128]
ссылка-якорь на функцию cidr2bin

ip::cidr2mask($i,$v=4) - преобразует CIDR в маску сети

$i - число, CIDR.
$v - число, версия протокола IPv4 или IPv6.
CIDR - Classless Inter-Domain Routing - Бесклассовая междоменная маршрутизация
echo ip::cidr2mask(16); //255.255.0.0
echo ip::cidr2mask(16,6); //ffff::
ссылка-якорь на функцию cidr2mask

ip::cidrverify($i,$v=4) - проверяет корректность CIDR

$i - число, CIDR.
$v - число, версия протокола IPv4 или IPv6.
Приводит и возвращает $i к int, 
  проверяет диапазон возможных значений CIDR в зависимости от протокола.
Необходима во избежание последующих ошибок при преобразовании, 
  в случае некорректного CIDR - inet_pton начнёт сыпать предупреждениями.
echo ip::cidrverify(16,4); //16
echo ip::cidrverify(160,4); //32
echo ip::cidrverify(16,6); //16
echo ip::cidrverify(160,6); //128
ссылка-якорь на функцию cidrverify

ip::clear($s,$f=0,$a=[]) - восстанавливает форму IP

$s - строка, IP адрес в виде строки или числа, или сокращённого IP адреса.
$f - дополнить нулями в конце или 1 - максимальным значением 255 / ffff.
$a - массив символов после которых обрезать адрес (включая символ). 
Приводит IP адрес к чистой/полной форме, если это IPv4 в форме IPv6 - вернёт IPv4.
Если IP в виде числа, преобразует к обычной форме 127.0.0.1 итп.
Если IP адрес сокращён, дополняет "хвост" .0.0.. или .255 / :ffff (параметр $f).
Возвращает массив [0=>'восстановленный IP адрес', 1=>4/6 (версия протокола)];
$a=ip::clear('172.16.*',0,['/','*']);
echo $a[0],' version = ',$a[1]; //172.16.0.0 version = 4
$a=ip::clear('ffff:ffff',0,['/']);
echo $a[0],' version = ',$a[1]; //ffff:ffff:: version = 6
ссылка-якорь на функцию clear

ip::compress($s,$m=1) - сжимает IP адрес

$s - IP адрес в виде строки.
$m - преобразовывать IPv4 в mapped address форму,
(по умолчанию inet_ntop(inet_pton($s)) вернёт mapped - ::ffff:192.168.1.2)
Вернёт строку - IPv6 Compressed address (short) сжатый уплотненный
Допускает наличие CIDR в адресе.
echo ip::compress('192.168.1.2/16'); //92.168.1.2/16
echo ip::compress('0000:0000:0000:0000:0000:ffff:b934:01ed'); //::ffff:192.168.1.2
echo ip::compress('0000:0000:0000:0000:0000:ffff:b934:01ed',0); //::ffff:c0a8:102
echo ip::compress('2002:b934:01ed::'); //2002:b934:1ed::
echo ip::compress('2002:b934:01ed::',0); //2002:b934:1ed::
echo ip::compress('0:0:0:0:0:ffff:b934:1ed',0); //::ffff:c0a8:102
echo ip::compress('2001:0:0:0:6dcd:0:0:0'); //2001::6dcd:0:0:0
ссылка-якорь на функцию compress

ip::count($f,$l=0) - подсчитывает количество адресов

$f - начальный IP адрес (или в виде числа long (в строке)).
$l - конечный IP адрес.
Возвращает строку с числом.
//max: IPv4=4294967296; IPv6=340282366920938463463374607431768211456
echo ip::count('192.168.1.0'); //3232235777
echo ip::count('192.168.1.0','192.168.1.0'); //1
echo ip::count('192.168.1.1','192.168.1.0'); //2
echo ip::count('192.168.1.10','192.168.1.20'); //11
echo ip::count('::ffff:192.168.1.2','::ffff:192.168.1.8'); //7
echo ip::count('192.168.1.2','::ffff:192.168.1.3'); //281470681743362
echo ip::count('192.168.1.2','ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'); 
  //340282366920938463463374607428535975678
echo ip::count('68719476736','125544568719476736'); //125544500000000001
ссылка-якорь на функцию count

ip::expand($s,$f=1) - разворачивает IP адрес

$s - IP адрес.
$f - 1 в полной или 0 в сокращённой форме.
echo ip::expand('192.168.1.2'); //192.168.1.2
echo ip::expand('192.168.1.2',0); //192.168.1.2
echo ip::expand('::ffff:192.168.1.2'); //0000:0000:0000:0000:0000:ffff:c0a8:0102
echo ip::expand('::ffff:192.168.1.2',0); //0:0:0:0:0:ffff:c0a8:102
echo ip::expand('ffff::c0a8:0102'); //ffff:0000:0000:0000:0000:0000:c0a8:0102
echo ip::expand('ffff::c0a8:0102',0); //ffff:0:0:0:0:0:c0a8:102
//преобразование к маршрутному типу 2002:... IPv4 не делал, если необходимо, то:
echo str_replace('0:0:0:0:0:ffff','2002',ip::expand(ip::v4to6('192.168.1.2'),0)).'::';
//2002:c0a8:102::
ссылка-якорь на функцию expand

ip::fill($s,$f=0) - заполняет IP адрес

$s - IP адрес.
$f - дополнить конец 0 = 0; 1 = 255|ffff.
Возвращает массив [0=>'ip адрес', 1=>0|1 изменён ли ip];
Функция дополняет до полного количества разрядов IP адрес.
Допускает наличие CIDR в адресе.
$a=ip::fill('10/8');
echo $a[0],', ip изменён: ',$a[1]; //10.0.0.0/8, изменён: 1
$a=ip::fill('192.168/8',1);
echo $a[0],', ip изменён: ',$a[1]; //192.168.255.255/8, изменён: 1
$a=ip::fill('ffff::c0a8:0102');
echo $a[0],', ip изменён: ',$a[1]; //ffff::c0a8:0102, изменён: 0
$a=ip::fill('ffff:c0a8');
echo $a[0],', ip изменён: ',$a[1]; //ffff:c0a8:0:0:0:0:0:0, изменён: 1
$a=ip::fill('ffff:c0a8',1);
echo $a[0],', ip изменён: ',$a[1]; //ffff:c0a8:ffff:ffff:ffff:ffff:ffff:ffff, изменён: 1
ссылка-якорь на функцию fill

ip::frombin($s) - преобразует бинарную запись в IP

$s - IP адрес в бинарной форме.
echo ip::frombin('11111111111100111111111111111100'); //255.243.255.252
ссылка-якорь на функцию frombin

ip::fromlong($s) - преобразует число в IP

$s - IP адрес в виде числа long.
echo ip::fromlong('3232235778'); //192.168.1.2 
echo ip::fromlong('281473913979138'); //::ffff:192.168.1.2
echo ip::fromlong('281473913979138'); //::ffff:192.168.1.2
echo ip::fromlong('28147391123434273453979138'); //::17:4871:215a:c5d2:71f1:3602
ссылка-якорь на функцию fromlong

$ip->in($s) - сравнение диапазонов адресов

$s - IP адрес, диапазон итп. Через запятую , или точку с запятой ;
Функция станет доступна после создания экземпляра класса
$ip=new ip('127.0.0.1');
echo $ip->in('10000000 - 281473911234342734, 128.0.0.0 - 10.255.255.255; 10/8'); //1
echo $ip->in('100.100./16'); //0
echo $ip->in('127.0-::17:4871:215a:c5d2:71f1:3602'); //1
ссылка-якорь на функцию in

ip::inlong($i,$f,$l='') - сравнение адресов

Все адреса в виде числовой строки в виде long.
$i - проверяемый IP адрес.
$f - начало диапазона.
$l - конец диапазона, не обязателен.
echo ip::inlong('23434567676756','234563453734567','45634565678696789'); //0
Более быстрый способом проверки - хранить в long все IP адреса:
require D.'deny/ip.php';
$banned=0;
$testip=ip::tolong(IP);
$banips='2130706431 - 22312312312321334534534; 3434523453452345';
$a=explode(';',str_replace(' ','',$banips));
foreach($a as $k=>$v){
  if(ip::sp($v,'-'))$b=explode('-',$v);
  else $b=[0=>$v,1=>''];
  if(ip::inlong($testip,$b[0],$b[1])){$banned=1;break;}
}
if($banned){header('HTTP/1.1 403 Forbidden');exit('banned');}
ссылка-якорь на функцию inlong

ip::isint($v) - является ли переменная целым числом

$v - проверяемая переменная.
echo var_dump(ip::isint('23434567676756')); //bool(true)
echo var_dump(ip::isint(23434567676756)); //bool(true)
echo var_dump(ip::isint('2343456.00')); //bool(false)
echo var_dump(ip::isint(2343456.00)); //bool(true), хвост .00 срежет PHP
  (особенности хранения переменных).
ссылка-якорь на функцию isint

$ip->get($f=1,$l=0) - вернуть ip адрес

$f - 1 первый адрес $ip->first. 0|2 - Последний $ip->last. 
$l - вернуть числом - $ip->firstlong, $ip->lastlong;
Возвращает строку, пустую если ip нет.
Функция станет доступна после создания экземпляра класса
$ip=new ip('127.0.0.1 - ffff::');
echo $ip->get(); //127.0.0.1
echo $ip->get(2); //ffff::
echo $ip->get(1,1); //2130706433
echo $ip->get(2,1); //340277174624079928635746076935438991360
ссылка-якорь на функцию get

ip::long2bin($s,$v=4) - преобразует число в бинарный вид

$s - число, long IP адрес.
$v - версия протокола, можно пропускать - необходима исключительно для 
  правильного отображения 0 адреса.
//127.0.0.1
echo ip::long2bin('2130706433',4); //01111111000000000000000000000001
echo ip::long2bin('2130706433',6); //01111111000000000000000000000001
echo ip::frombin(ip::long2bin('340277174624079928635746076935438991360',4)); //ffff::
echo ip::frombin(ip::long2bin('340277174624079928635746076935438991360',6)); //ffff::
echo ip::long2bin(0); //00000000000000000000000000000000 [32]
echo ip::long2bin('',4); //00000000000000000000000000000000 [32]
echo ip::long2bin('',6); //00000000000000...000000000000000 [128]
ссылка-якорь на функцию long2bin

ip::tobin($s,$v=4) - преобразует IP в бинарный вид

$s - IP адрес.
$v - версия протокола, можно пропускать - необходима исключительно для 
  правильного отображения 0 адреса.
echo ip::tobin('127.0.0.1'); //01111111000000000000000000000001
echo ip::tobin(0); //00000000000000000000000000000000 [32]
echo ip::tobin('',4); //00000000000000000000000000000000 [32]
echo ip::tobin('',6); //00000000000000...000000000000000 [128]
ссылка-якорь на функцию tobin

ip::tolong($s,$v=0) - преобразует IP в число

$s - IP адрес.
$v - версия протокола, если не задана - функция сама определит, 
  оставлена для внешней оптимизации.
echo ip::tolong('192.168.1.2'); //3232235778
echo ip::tolong('::ffff:192.168.1.2'); //281473913979138
echo ip::tolong('0000:0000:0000:0000:0000:ffff:c0a8:0102'); //281473913979138
echo ip::tolong('ffff::'); //340277174624079928635746076935438991360
ссылка-якорь на функцию tolong

ip::shorten($s) - преобразует IP в укороченную форму

$s - IP адрес.
Производит подвызов функции ip::expand($s,0);
echo ip::shorten('192.168.1.2'); //192.168.1.2
echo ip::shorten('::ffff:192.168.1.2'); //0:0:0:0:0:ffff:c0a8:102
echo ip::shorten('0000:0000:0000:0000:0000:ffff:c0a8:0102'); //0:0:0:0:0:ffff:c0a8:102
echo ip::shorten('0:0:0:0:0:ffff:c0a8:102'); //0:0:0:0:0:ffff:c0a8:102
echo ip::shorten('::ffff:b934:1ed'); //0:0:0:0:0:ffff:b934:1ed
ссылка-якорь на функцию shorten

ip::sp($s,$f) - проверяет вхождение строки в другую

$s - строка.
$f - что ищем.
Производит подвызов mb_strpos.
echo var_dump(ip::sp('string b','%b')); //bool(false)
echo var_dump(ip::sp('string %b','%b')); //bool(true)
ссылка-якорь на функцию sp

ip::v4to6($s,$m=1) - преобразует IPv4 в IPv6

$s - IP адрес.
$m - преобразовывать IPv4 в mapped address форму
echo ip::v4to6('192.168.1.2'); //::ffff:192.168.1.2
echo ip::v4to6('192.168.1.2',0); //::ffff:c0a8:102
//По факту система адресов разная и выделение провайдером/роутером 
  дополнительного IPv6 адреса, вовсе не значит что он хоть как-то будет равен IPv4.
ссылка-якорь на функцию v4to6

ip::v6to4($s) - преобразует IPv6 в IPv4

$s - IP адрес.
Вернёт пустую строку в случае неудачи.
echo ip::v6to4('ffff:b934:1ed:ffc::'); //''
echo ip::v6to4('::ffff:192.168.1.2'); //192.168.1.2
echo ip::v6to4('2002:c0a8:102:0000:0000:0000:0000:0000'); //192.168.1.2
echo ip::v6to4('2002:c0a8:102:0:0:0:0:0'); //192.168.1.2 
  2002: = Маршрутизация IPv6 в IPv4  - маршрутный адрес роутеров..
//По факту система адресов разная и выделение провайдером/роутером 
  дополнительного IPv6 адреса, вовсе не значит что он хоть как-то будет равен IPv4.
ссылка-якорь на функцию v6to4

ip::ver($s) - определяет версию протокола IP

$s - IP адрес в виде строки или long.
Вернёт пустую строку в случае неудачи.
echo ip::ver('abracadabra'); //0
echo ip::ver('192.168.1.2'); //4
echo ip::ver('3232235778'); //4
echo ip::ver('ffff:b934:1ed:ffc::'); //6
echo ip::ver('::ffff:192.168.1.2'); //6
echo ip::ver('281473913979138'); //6
echo ip::ver(281473913979138); //6
echo ip::ver('::ffff:c0a8:0102'); //6
echo ip::ver('281473913979138'); //6
ссылка-якорь на функцию ver

В SQL базе данных можно хранить ip адреса в запакованном(inet_pton) виде, в виде бинарных данных BINARY(16), но при этом необходимо понимать в битовых операциях для выборок и сравнения, плюс встаёт вопрос дампов базы данных и возможном попадании туда некорректных данных и последующих проблем "на ровном месте". И это противоречит заложенному постулату о простоте движка, поэтому хранить ip в базе рекомендую как DECIMAL(39,0), при этом можно будет делать выборку по диапазонам средствами SQL и используя long функции (ip::tolong(), ip::fromlong()).
ip DECIMAL(39,0) NOT NULL DEFAULT 0,

136111847226264995686342697210517200896  =39

Ещё вариант хранения в VAR/CHAR(39), число или IPv6 поместится:
ip char(39) NOT NULL DEFAULT '',

0000:0000:0000:0000:0000:0000:0000:0000  =39

Функция генерации диапазонов масок IP

require D.'deny/ip.php';
//$v=ver(4|6); f=format (d - symbols space); $r=revers
function maskmap($v=4,$f='/%i %s = %b; %m; %n<br>',$r=1){
  $b=ip::sp($f,'%b');//bin
  $c=ip::sp($f,'%c');//compacted mask v6
  $l=ip::sp($f,'%l');//long
  $m=ip::sp($f,'%m');//mask
  $n=ip::sp($f,'%n');//ip count
  if(4==$v){$z=33;$q='';}else{$z=129;$q='&nbsp;';}
  $k=$r?$z-1:0;
  $a=$t=$s=$u=$p='';
  for($i=0;$i<$z;$i++){
    if(10>$k)$s=$q.'&nbsp;';
    elseif(100>$k)$s=$q;
    else $s='';
    $u=str_replace('%i',$k,$f);
    $u=str_replace('%s',$s,$u);
    $a=ip::cidr2bin($k,$v);
    if($b)$u=str_replace('%b',$a,$u);
    $p=ip::frombin($a);
    if($c)$u=str_replace('%c',$p,$u);
    $p=ip::expand(ip::frombin($a));
    if($m)$u=str_replace('%m',ip::expand($p),$u);
    if($n){
      $y=ip::tolong($p);
      $j=inet_pton($p);
      $e=ip::tolong(inet_ntop($j|~$j));
      $u=str_replace('%n',bcadd(bcsub($e,$y),1),$u);
    }
    if($l)$u=str_replace('%l',ip::tolong($p,$v),$u);
    $t.=$u;
    $k=$r?$k-1:$k+1;
  } return $t;
}
echo '<h2>Таблица сетевых масок IPv4</h2>',maskmap(4);
echo '<h2>Таблица сетевых масок IPv6</h2>',maskmap(6);




21.07.2026
21.8.7534 от С.М.З.Х.
Unix time: 1784615100
© Все права защищены 2004 - 2026