Ответить в теме

[QUOTE="Master, post: 1940, member: 10"]

update 11.12.2016

Список IP госорганов обновлен.

Обновлены скрипты.

Появился скрипт для тестирования (test.php, пример здесь).

Добавлена админка для кодировки windows-1251 (файл в архиве admin_win1251.php).


update 07.10.2016

Скрипт и список IP госорганов обновлены.

Появилась админка.


------


Подобный скрипт уже существует  - Котозапрет от Antizapret.info. Их скрипт проверяет IP по диапазонам ip-адресов госорганов и выводит фотографию котика, если вхождение найдено. Но Котозапрет нам показался не оптимальным, поэтому мы решили сделать собственный.


Что же не так в Котозапрете?

Во-первых, мало ip-адресов - у нас получилось на порядок больше. Во-вторых, алгоритм не оптимальный, что может тормозить работу посещаемых сайтов. И в-третьих, сомнительное решение повысить производительность скрипта за счет кэширования госоргановских IP.

[PHP]

    /*

  * @brief производится загрузка базы и запись ip адреса блокируемого при включеном файловом кэшировании (с целью снижения нагрузки на разбор массива, так как is_file быстрее)

     *

     */

    public function parseBase($ip, $store = 0) {

        $networks = explode("::", file_get_contents($this->cache_path . "/" . $this->cache_file));

        foreach ($networks AS $network) {

            if (self::match($network, $ip)) {

                if ($store)

                    file_put_contents($this->cache_path . "/" . $ip, "");

                self::goBlock();

            }

        }

    }

[/PHP]

Может есть смысл заносить в лог госоргановские IP, чтобы понимать, какие органы проверяют сайт, но кэшировать с целью снижения нагрузки - сомнительная затея, ведь мы ориентированы на пользователей, а не на госорганы, зачем для них нам нагрузку снижать.


Непонятно также почему частота обновления файла с данными выставлена в 30 минут, когда списки диапазонов обновляются раз в паятилетку. Мы выставили примерно в 5 дней, но можно и реже.


Скрипт Роскомсос.

Скрипт реализован в виде класса Roscomsos, который только определяет принадлежность IP к госорганам. В случае попадания можете показывать котиков или Сашу Грей, а лучше отдать измененный, незапрещенный контент. Например, если у вас киносайт, то госорганам вы можете показывать трейлеры фильмов, а остальным пользователям фильмы целиком.


В целях повышения производительности скрипт использует два файла: в одном файле собраны только первые два байта госовских айпи, а в другом полный список всех известных диапазонов. Проверка осуществляется в три этапа: сначала ищем совпадение двух байтов IP в первом файле (большинство пользователей отфильтруется уже на этом этапе, что снизит нагрузку на сервер), затем, если IP похож на госовский, то ищем первые три байта в полном списке, далее, если совпадений не найдено, IP ищется в диапазонах, но не во всех, а только с такими же первыми двумя байтами.


Сам класс:

[PHP]

<?PHP


class Roscomsos {


    public $time_update='5'; // Обновляем список каждые 5 дней, можно поставить и 10 и 30

  //  public $url_update='https://roscenzura.com/roscomsos/'; // Если урл не указан, то обновление данных не происходит

    public $file_ip='gosip.data'; // Полный массив данных

    public $file_short='gosip_short.data'; // Сокращенный массив данных с первыми двумя байтами госовских IP для предварительной проверки

    public $file_log='gosiplog.txt'; // Закомментируйте, если не хотите логировать IP госорганов

    public $d; // директория скрипта

    public $ip;


    public function __construct()

    {

        $this->d = $_SERVER['DOCUMENT_ROOT'].'/roscomsos/'; // не забудьте назначить права 0777 на папку

    }


    public function update_data()

    {

     $file=$this->d.$this->file_ip;


     if ($this->url_update=='') return;


     if (!is_file($file) or (filemtime($file)+ $this->time_update * 24 * 3600 < time()) )

     {

       file_put_contents($file, file_get_contents($this->url_update.$this->file_ip));

        file_put_contents($this->d.$this->file_short, file_get_contents($this->url_update.$this->file_short));


       if (!is_file($file)) die('Установите права для записи на папку ' . $this->d);

     }

    }


    // Ищем IP в диапазоне, например, таком 155.39.133.161-155.39.133.174

    public function find_range($range)

    {

    $range=explode('-', $range);

    if (!isset($range[1])) return false;


    return ( ip2long($this->ip)>=ip2long($range[0]) && ip2long($this->ip)<=ip2long($range[1]) );

    }


    // Ищем IP в подсети, например, 151.224.182.0/23

    public function find_subnet($range)

    {

     list ($subnet, $bits) = explode('/', $range);


     $ip = ip2long($this->ip);

     $subnet = ip2long($subnet);


     $mask = -1 << (32 - $bits);

     $subnet &= $mask;


     return ($ip & $mask) == $subnet;

    }


    // Проверяем IP в три этапа

    public function check_ip($ip=false, $log=true)

    {

     if ($ip) $this->ip=$ip;


     if ($this->ip != long2ip(ip2long($this->ip))) return; // Если IP6, отметаем


     if (!is_file($this->d.$this->file_short)) $this->update_data(); else if( date("d") % $this->time_update == 0) $this->update_data(); // Если файл данных не найден или давно не обновлялся - обновляем



     $bytes=explode('.', $this->ip);


    // var_dump(file_get_contents($this->d.$this->file_short));


     if (strpos(file_get_contents($this->d.$this->file_short), '|'.$bytes[0].'.'.$bytes[1].'|' )===false) return false; // Ищем первые два байта в первом списке, большинство негосовских IP отфильтруется здесь



     $file=file_get_contents($this->d.$this->file_ip);

 

     if (strpos($file, '|'.$bytes[0].'.'.$bytes[1].'.'.$bytes[2].'.')!==false) return $this->logGosIp($log);  // Жесткий режим блокировки: если три байта совпадают, блокировать



     $find_m='||'.$bytes[0].'.'.$bytes[1].'||';


     // Берем диапазон только с такими же первыми двумя байтами, чтобы не прогонять по всему списку

     $file=substr($file, strpos($file, $find_m)+strlen($find_m) );

     $file=substr($file, 0, strpos($file, '||') );


     // Проверяем вхождение IP в диапазоны

     $ip_c=explode('|', $file); $check=false;

     foreach ($ip_c as $i=>$gip)

     {

        if (strpos($gip, '/')) $check=$this->find_subnet($gip); else $check=$this->find_range($gip);


        if ($check==true) return $this->logGosIp($log);


     }

    }


    // Сохраняем IP госорганов

    public function logGosIp($log=false)

    {

        if ($log) file_put_contents($this->d.$this->file_log, $this->ip.chr(13).chr(10), FILE_APPEND);


        return true;

    }


}

?>

[/PHP]


Этот код нужно вставить на сайте (в файл index.php).

[PHP]

require_once($_SERVER['DOCUMENT_ROOT']."/roscomsos/roscomsos.php");


$Roscomsos=new Roscomsos();

$check_gos_ip=$Roscomsos->check_ip($_SERVER['REMOTE_ADDR']); // Если true, то IP вероятно принадлежит диапазону адресов госорганов


if ($check_gos_ip)

{

   echo 'Доступ на сайт запрещен';

}

[/PHP]


Не забудьте установить права на запись для следующих файлов: gosip.data, gosip_short.data, gosiplog.txt.


Файл с актуальными диапазонами IP госорганов и Роскомнадзора теперь находится по ссылке: https://roscenzura.com/roscomsos/gosip.txt.

Для получения дополнительной информации пишите нам в ЛС.


Ссылка на скачивание скрипта: https://roscenzura.com/roscomsos/roscomsos.zip

Тестирование: https://roscenzura.com/roscomsos.php

[/QUOTE]

Сверху