Главная страница » Статьи и уроки » PHP статьи » Проверка IP-адреса по маске подсети в массиве php
Опрос
Вы занимаетесь разработкой сайтов?
Выделенные и виртуальные серверы в Европе

Проверка IP-адреса по маске подсети в массиве php

Автор: administrator Дата: 30-12-2018, 11:38 Категория: Статьи и уроки / PHP статьи
Наверняка перед многими web-мастерами вставала задача — определить по маске подсети вхождение IP-адреса посетителя сайта. Цели при этом могут быть разными: выдать содержимое на странице в зависимости от географической принадлежности посетителя (что арабу хорошо, то еврею смерть), заблокировать доступ к сайту по IP… Впрочем, блокировать доступ к сайту удобнее с помощью файла .htaccess.

В общем, однажды подобная задача встала и передо мной — нужно было телефон на странице выводить в зависимости от страны посетителя сайта. Хождение по Google мало что дало. На многих блогах и форумах я находил какие-то обрезки php-скриптов, в большинстве своем не работающие. А если и попадались работающие скрипты, то проверка производилась только по одному диапазону IP-адресов. Пришлось писать свой php-код, коим и хочу поделиться.

В файл ipbase.txt вносим подсети IP-адресов нужной страны, берем их здесь: ipdeny.com

Пишем php-скрипт:


<?php
// Функция проверки вхождения IP-адреса в подсеть:
$ip = $_SERVER['REMOTE_ADDR'];

function ip_in_net($ip, $net, $mask)
{
// Преобразование IP в беззнаковое десятичное целое число:
    $ip = (int) sprintf("%u", ip2long($ip));
    $mask = (int) sprintf("%u", ip2long($mask));
    $net = (int) sprintf("%u", ip2long($net));
    if (($ip & $mask) == $net) {
        return 1;
    } else {
        return 0;
    }
}

// Поскольку подсети записаны в формате 127.0.0.0/8, то понадобится функция перевода CIDR в обычную маску: 127.0.0.0/255.0.0.0:
function cidr_to_mask($mask)
{
    return long2ip(pow(2, 32) - pow(2, (32 - $mask)));
}

// Загружаем файл с базой подсетей, не забываем указать правильный путь к файлу:
$file = $_SERVER['DOCUMENT_ROOT'] . '/ПУТЬ_К_ФАЙЛУ/ipbase.txt';
// Если файл существует и доступен для чтения:
if (is_readable($file)) {
    // Считываем файл в массив:
    $nets = @file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    // Проходим массив циклом:
    for ($i = 0, $size = sizeof($nets); $i < $size; $i++) {
        // Если строка существует:
        if ($nets[$i]) {
            // Разбиваем строку на массив, в качестве значений используются адрес и маска подсети:
            $line = explode('/', $nets[$i]);
            $mask = cidr_to_mask($line[1]); // Переводим CIDR в обычную маску
            $net = $line[0];
            // Проверяем вхождение IP-адреса в подсеть:
            if (ip_in_net($ip, $net, $mask)) {
                // Если IP-адрес входит в подсеть, выводим результат:
                echo 'Адрес ' . $ip . ' входит в подсеть ' . $net . '/' . $mask;
                // Или задаем значение переменной $ip для использования за пределами данного цикла (в правиле ниже):
                $ip = 'yes';
                break; // Прерываем цикл
            }
        }
    }
}
?>



Скрипт удобнее разместить в отдельном файле, подключая его к нужной странице функцией include. Путь к файлу с базой подсетей также можно вынести из скрипта и прописывать на нужной странице. Так вы сможете использовать различные файлы для разных страниц, используя только один скрипт. При соответствии IP-адреса маске подсети в скрипте выводится только значение переменной $ip = 'yes', по которому на страницах сайта задаются определенные правила:


<?php
$file = $_SERVER['DOCUMENT_ROOT'] . '/ПУТЬ_К_ФАЙЛУ/ipbase_egypt.txt';
include($_SERVER['DOCUMENT_ROOT'] . '/ПУТЬ_К_ФАЙЛУ/ipsearch.php');
if ($ip == 'yes') {
    // IP-адрес входит в подсеть, например, Египта, пишем приветствие для друзей-арабов:
    echo 'Рахат-лукум!';
} else {
    // В противном случае приветствуем остальной мир, а арабы из Египта пусть идут руслом Нила — можно и в Крыму отдыхать, далась вам эта пустыня:
    echo 'Миру — мир, Крыму — Крым!';
}
?>


Напоследок привожу оптимизированный код:


<?php
$file = $_SERVER['DOCUMENT_ROOT'] . '/ПУТЬ_К_ФАЙЛУ';
if (is_readable($file)) {
    $cidr = array('0.0.0.0', '128.0.0.0', '192.0.0.0', '224.0.0.0', '240.0.0.0', '248.0.0.0', '252.0.0.0', '254.0.0.0', '255.0.0.0', '255.128.0.0', '255.192.0.0', '255.224.0.0', '255.240.0.0', '255.248.0.0', '255.252.0.0', '255.254.0.0', '255.255.0.0', '255.255.128.0', '255.255.192.0', '255.255.224.0', '255.255.240.0', '255.255.248.0', '255.255.252.0', '255.255.254.0', '255.255.255.0', '255.255.255.128', '255.255.255.192', '255.255.255.224', '255.255.255.240', '255.255.255.248', '255.255.255.252', '255.255.255.254', '255.255.255.255');
    $ip = intval(sprintf("%u", ip2long($_SERVER['REMOTE_ADDR'])));
    $nets = @file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    for ($i = 0, $size = sizeof($nets); $i < $size; $i++) {
        if ($nets[$i]) {
            $line = explode('/', $nets[$i]);
            $net = intval(sprintf("%u", ip2long($line[0])));
            if (isset($cidr[$line[1]])) {
                $mask = $cidr[$line[1]];
            } else {
                $mask = long2ip(pow(2, 32) - pow(2, (32 - $line[1])));
            }
            $mask = intval(sprintf("%u", ip2long($mask)));
            if (($ip & $mask) == $net) {
                $mark = 1; // Маркер вхождения $ip в подсеть $net/$mask
                break;
            }
            unset($line, $mask, $net);
        }
    }
    unset($cidr, $ip, $nets, $i, $size);
}
unset($file);

if (!empty($mark)) {
    // Адрес $ip входит в подсеть $net/$mask
}
?>


Данная статья была взята с сайта: mycrimea.su
  • Не нравится
  • 0
  • Нравится
Просмотров: 2 716 Напечатать Жалоба
Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь. Мы рекомендуем Вам зарегистрироваться либо зайти на сайт под своим именем.
Написать комментарий
Ваше Имя:
Ваш E-Mail:
  • bowtiesmilelaughingblushsmileyrelaxedsmirk
    heart_eyeskissing_heartkissing_closed_eyesflushedrelievedsatisfiedgrin
    winkstuck_out_tongue_winking_eyestuck_out_tongue_closed_eyesgrinningkissingstuck_out_tonguesleeping
    worriedfrowninganguishedopen_mouthgrimacingconfusedhushed
    expressionlessunamusedsweat_smilesweatdisappointed_relievedwearypensive
    disappointedconfoundedfearfulcold_sweatperseverecrysob
    joyastonishedscreamtired_faceangryragetriumph
    sleepyyummasksunglassesdizzy_faceimpsmiling_imp
    neutral_faceno_mouthinnocent
Код: Кликните на изображение чтобы обновить код, если он неразборчив
Введите код: