Роскомсос - скрипт для определения IP госорганов

Master

Master

Модератор
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();
            }
        }
    }
Может есть смысл заносить в лог госоргановские 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;
    }

}
?>
Этот код нужно вставить на сайте (в файл 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 'Доступ на сайт запрещен';
}
Не забудьте установить права на запись для следующих файлов: 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
 
Последнее редактирование модератором:
В

Водный

Member
Мне кажется не особо эффективен этот способ. Там ведь тоже не совсем идиоты сидят, айпишники начнут менять чаще, а их ещё надо выявить. Старые при этом могут раздать обычным пользователям, которые в итоге на ресурс не попадут. Как вариант могут начать через прокси ходить или использовать агентуру – тех самых добровольных помощников.
 
Master

Master

Модератор
Где не идиоты сидят в Роскомнадзоре? ) И депутаты наши тоже не идиоты такие законы принимать ) И народ тоже не идиоты который им верит ) Мы здесь собрались из-за идиотов, чтобы показать, что мы не дураки )

Как показывает практика все с точностью до наоборот - раньше меняли, а теперь нет. Видимо поняли что смысла нет менять - быстро выявим. Но тут не только роскомнадзоровские адреса, но и все известные подсети госорганов.
 
Последнее редактирование модератором:
А

Александр Матросов

New Member
Можете скинуть подробное описание установки данного скрипта, так и не смог понять как его устанавливать, просто заливать файлы php или вставлять код в корень самой страницы, так и не понял.
Заранее спасибо.
 
Master

Master

Модератор
Можете скинуть подробное описание установки данного скрипта, так и не смог понять как его устанавливать, просто заливать файлы php или вставлять код в корень самой страницы, так и не понял.
Заранее спасибо.
Содержимое архива распаковать в папку /roscomsos/.

А в исполняющем файле (index.php) прописать следующее:
Код:
require_once($_SERVER['DOCUMENT_ROOT']."/roscomsos/roscomsos.php"); // подгружаем скрипт

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

Александр Матросов

New Member
Содержимое архива распаковать в папку /roscomsos/.

А в исполняющем файле (index.php) прописать следующее:
Код:
require_once($_SERVER['DOCUMENT_ROOT']."/roscomsos/roscomsos.php"); // подгружаем скрипт

$Roscomsos=new Roscomsos();
$check_gos_ip=$Roscomsos->check_ip($_SERVER['REMOTE_ADDR']); // Если true, то IP вероятно принадлежит диапазону адресов госорганов
Только убедитесь, что переменная $_SERVER['REMOTE_ADDR'] содержит IP пользователя а не IP сервера.
Большое спасибр за подсказку.

Только все дело в том, что все мои сайты .html.
Вставлял скрипт в код страницы, скрипт не работает :(
 
Master

Master

Модератор
На сервере нет ПХП? Это совсем печально.

А если все же есть, нужно переименовать хтмл в пхп и вверху вставить код
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==true) exit;
?>
И должно заработать.
 
N

netcenzure222

Member
Почему бы в качестве хранилища не использовать специально созданный для этого велосипед под названием MySQL? Или как вариант писать в файл и одновременно в Memcached, а читать только из Memcached, с диска - только в случае отсутствия данных в последнем.
 
Master

Master

Модератор
Почему бы в качестве хранилища не использовать специально созданный для этого велосипед под названием MySQL? Или как вариант писать в файл и одновременно в Memcached, а читать только из Memcached, с диска - только в случае отсутствия данных в последнем.
Что вы хранить собираетесь в базе?
 
Master

Master

Модератор
Это сделает скрипт более ресурсоемким. А вместо мемкешес лучше сохранять в сессию результат.
PHP:
<?PHP
session_start();

if (!isset($_SESSION['check_ip']))
{
  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==true) exit; else $_SESSION['check_ip']=true;
}
?>
 
free-lanser-ananas

free-lanser-ananas

New Member
Здравствуйте, расскажите пожалуйста понятно как установить скрипт . (Прям для чайников) Заранее спасибо.
Беру в корне сайта создаю папку roscomsos. Туда заливаю все файлы из архива.
Куда закидывать blacklist.txt?
Прописывать во всех страницах сайта код
<?PHPrequire_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==true) exit;?>


Я правильно понимаю?
Помогите девушке, заранее благодарю
 
free-lanser-ananas

free-lanser-ananas

New Member
А что за ошибка? И самое главное - какая CMS?
Вообще сайт на html
Переименовала все страницы в php
Далее надо вставить на каждую страницу код в самый верх
этот

<?PHPrequire_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==true) exit;?>


Я правильно понимаю?
 
Master

Master

Модератор
Какую ошибку пишет?

Сам скрип залили в папку /roscomsos?

Попробуйте так?
PHP:
<?PHP
error_reporting(0);

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==true) exit;
?>
 
free-lanser-ananas

free-lanser-ananas

New Member
Вставлять код на каждой странице сайта в самый верх. Так?

А blacklist.txt куда девать??? Там же все ip

И как я понимаю госорганы не смогут просмотреть сайт??
 
Последнее редактирование модератором:
N

netcenzure222

Member
Во-первых, надо убедиться, что на хостинге точно работает php, например вставить в любую страницу

Если ничего не появится, то нужно в файл .htaccess добавить

AddHandler application/x-httpd-php .php .html .htm
Если и это не поможет, тогда обращайтесь к хостеру.
 
free-lanser-ananas

free-lanser-ananas

New Member
Сделала, вставила код, залила в папку roscomsos скрипт.
ЧТо дальше?
Как он работает вообще?
 
Master

Master

Модератор
Обновил архив, добавил файл instruction.txt, скачайте заново там подробно расписано.

Если возникнут проблемы - пишите в лс, сделаю.

Как он работает вообще?
PHP:
require_once($_SERVER['DOCUMENT_ROOT']."/roscomsos/roscomsos.php"); // подгружаем сам класс

$Roscomsos=new Roscomsos();
$check_gos_ip=$Roscomsos->check_ip($_SERVER['REMOTE_ADDR']); // Проверяем, есть ли айпи в списке

if ($check_gos_ip==true) { echo 'Извините, проводятся технические работы'; exit; } // Если IP есть в списке показываем сообщение о технических работах
Для проверки работы скрипта можно назначить переменной $_SERVER['REMOTE_ADDR'] любой ip из списка.
 
Master

Master

Модератор
Просто вставляете в самый верх код
Код:
<?PHP
require_once($_SERVER['DOCUMENT_ROOT']."/roscomsos/roscomsos.php"); // подгружаем сам класс

$Roscomsos=new Roscomsos();
$check_gos_ip=$Roscomsos->check_ip($_SERVER['REMOTE_ADDR']); // Проверяем, есть ли айпи в списке

if ($check_gos_ip==true) { echo 'Извините, проводятся технические работы'; exit; } // Если IP есть в списке показываем сообщение о технических работах
?>
B все должно заработать.
 
K

Komikos

New Member
Добрый вечер.
Установил скрипт, все сделал по инструкции, но при заходе на сайт выдает ошибку
Код:
Warning: require_once(/roscomsos/roscomsos.php) [function.require-once]: failed to open stream: No such file or directory in
 
Master

Master

Модератор
Содержимое архива надо залить в папку /roscomsos/ на сервере. Судя по ошибке, вы эту папку не создали.
 
Сверху