::: PHP.com.ua - учимся вместе. ::: ::: PHP.com.ua - учимся вместе. :::



 
   - Разработка CRM для туристического бизнес...
  - тестування по прив"язці до часу...
  - СРОЧНО! Требуется талантливый PHP програ...
  - Оплачу FLASH-сайт под ключ.
  - выборка одним запросом нескольких похожи...
  - функции верификации строк.
  - Помогите вытянуть скрипт отправки почты ...


Главная
Новости
Статьи
Шпаргалки
Файлы
О проекте
Форум
Футболки


FREEhost.com.ua - купил хостинг 10 у.е. на Begun в подарок.

iName.com.ua - регистрация доменных имен и хороший хостинг.

Библиотека программиста - нужный вам исходник или документация по необходимому для вас языку программирования.

Designclub - Клуб дизайнеров Украины.

Регистрация доменов
Хостинг

 HowtoForge.ORG.UA - Это первый Украинский ресурс развития open source программного обеспечения


Путь: Шпаргалки

Шпаргалки

Автор: - Yurik
Дата публикации - 08.01.2006
Просмотров: - 4838

Борьба с баннерами в локальных сетях и сетях провайдеров


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

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

Кроме того в корпоративных сетях возникают вопросы блокирования определенных сайтов с нежелательным контентом (например порно-сайты), которые посещают сотрудники или гости компании.

В то же время с "чумой 21 века" можно крайне эфективно бороться на прокси-сервере. Мною выбран самый популярный и ефективный HTTP-proxy работающий как под Unix так и под Windows - Squid.

Он представляет две возможности обработки URL:

1. Через регулярные выражения

squid.conf:
===========
acl Banners url_regex '/usr/local/etc/squid/ban'
acl Porno url_regex '/usr/local/etc/squid/porno'
acl NoBanners url_regex '/usr/local/etc/squid/noban'

http_access allow NoBanners
http_access deny Banners
http_access deny Porno
===========

даный способ самый простой, но неефективный, т.к. запрошенный УРЛ все равно скачивается но отдается клиенту страница 403 Forbidden. Эта страница с ошибкой портит верстку основной страницы (картинку, фреймы) и она "плывет".

2. Через redirector.

squid.conf:
===========
redirect_program /path/to/executable
redirect_children 5
redirect_rewrites_host_header on
===========

эти директивы говорят Squid запустить изначально 5 копий процесса `executable` и все запросы клиентов перенаправлять ему на обработку. А то что возвратит редиректор - уже реально скачивать, отдавать клиенту и писать в лог.

От Squid редиректор получает на STDIN запрос в таком формате:

url=http://example.com/path?var=val]http://example.com/path?var=val/url] 10.0.1.12/user_name ident_string method

user_name берется из модуля ncsa_auth. Если модуль не активирован или юзер конектится без использования авторизации то вместо имени юзера будет дефис: 10.0.1.12/-

ident_string берется из IDENT запроса Squid клиенту (113 порт), если такие запросы запрещены и/или клиент не отдаёт никакого ответа, то будет тоже прочерк (дефис)

method - GET/POST/HEAD или другой.

В таком же формате редиректор должен отдать строку назад на STDOUT.

Осталось написать ефективный и удобный скрипт или программу редиректора. На данную тему в интернете можно найти существующие скрипты. Но мы напишем свой, на PHP, т.к. он простой в разработке и сопровождении, а встроенные функции работы со строками и массивами написаны на С, поэтому достаточно эфективны в плане быстродействия.

Основной недостаток редиректора на PHP (как и на другом скриптовом языке, например Perl) - это относительно большой объем занимаемой процессом памяти (нужной для работы /usr/local/bin/php). Это критично на серверах с высокой нагрузкой по количеству одновременных клиентов (Squid создаст много chidren) и ограниченным объемом RAM.

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

При написании скрипта автор постарался максимально учесть эти недостатки.

Перейдем к коду нашего скрипта:

[php]
#!/usr/local/bin/php -c /usr/local/redir/redir.ini
<?php
Class SquidRedir {
    var 
$conf$config;
    var 
$arrblack$arrwhite;
    var 
$timeblack$timewhite$timeconfig;

    function 
readconfig(){
        
$this->config=@parse_ini_file($this->conftrue);
        
$this->config=$this->config['redir'];
        
$this->config['banner']=$this->config['path'].$this->config['banner'];
        
$this->config['noba']=$this->config['path'].$this->config['noba'];

        if (!
file_exists($this->config['banner'])) die ('Ban definition ['$this->config['banner'].'] not found');
        if (!
file_exists($this->config['noba'])) die ('White list definition ['$this->config['noba'].'] not found');
        if (!
is_readable($this->config['banner'])) die ('Ban definition ['$this->config['banner'].'] not readable');
        if (!
is_readable($this->config['noba'])) die ('White list definition ['$this->config['noba'].'] not readable');

     if (!
file_exists($this->config['log'])){
        if (
is_writable(dirname($this->config['log']))){
            
$fp=fopen($this->config['log'], 'a');    // create log file
            
fclose($fp);
        } else die (
'Log file ['$this->config['banner'].'] could not be created');
     }
        
$this->timeconfig=filemtime($this->conf);
    }

    function 
myTrim(& $item$key){
        
$item=trim($item);
    }

    function 
readblack(){
        
$this->arrblack=file($this->config['banner']);
        
array_walk($this->arrblack, array($this'myTrim'));
    }

    function 
readwhite(){
        
$this->arrwhite=file($this->config['noba']);
        
array_walk($this->arrwhite, array($this'myTrim'));
    }

    function 
updateConfig(){
        if (
$this->timeconfig!=filemtime($this->conf))    $this->readconfig();
    }

    function 
updateBases(){
        if (
$this->timeblack!=filemtime($this->config['banner'])) $this->readblack();
        if (
$this->timewhite!=filemtime($this->config['noba'])) $this->readwhite();
    }

    function 
writeLog(& $record){
        
$flog fopen($this->config['log'], 'a');
        
$d=date('Y-m-d H:i:s');
        
$log=$d."\t".$record['type']."\t".$record['ip']."\t".$record['url'];
        
fputs($flog,$log."\n");
        
fclose($flog);
    }

    function 
parseSquid($in){
        
$tmp=explode(' ',$in);
        
$path=explode('?',$tmp[0]);
        
$out['url']=$tmp[0];
        
$out['path']=@$path[0];
        
$out['ip']=@$tmp[1];
        
$out['ident']=@$tmp[2];
        
$out['method']=@$tmp[3];
        return 
$out;
    }

    function 
debugWrite($debugstr){
        
$flog fopen($this->config['debug'], 'a');
        if (!
$flog) die('Debug could not be created');
        
fputs($flog,$debugstr."\n");
        
fclose($flog);
    }

    function 
SquidRedir($conf='/usr/local/redir/redir.ini'){
        
$this->conf=$conf;
        if (!
file_exists($conf)) die('Config file not found');
        
$this->timeconfig=0;

        while(
1) {
            
clearstatcache();
            
$this->updateConfig();
            
// Read query from squid
            
$input=trim(fgets(STDIN));
            if (
$this->config['debugon'])    $this->debugWrite($input);

            
// parse string and init vars
            
if (!$this->config['enabled']){
                
$output=$input;
            } else {
                
$this->updateBases();

                
$raw=$this->parseSquid($input);
                
$found=false;
                foreach (
$this->arrblack as $value) if (strpos($raw['path'], $value)!==false){$found=true; break;}
                if (!
$found){
                    
// not found in black list, do nothing
                    
$newurl=$raw['url'];
                    
$raw['type']='[none]';
                    
//$this->writeLog($raw);
                
} else {
                    
// found in black list
                    
$found=false;
                    foreach (
$this->arrwhite as $value) if (strpos($raw['path'], $value)!==false){$found=true; break;}
                    if (!
$found){
                        
$newurl=$this->config['reurl']; //do redirect and log;
                        
$raw['type']='[black]';
                    } else {
                        
$newurl=$raw['url']; //don't redirect, only log
                        
$raw['type']='[white]';
                    }
                    if (
$this->config['logging']) $this->writeLog($raw);
                }
                
$output=$newurl." ".$raw['ip']." ".$raw['ident']." ".$raw['method'];                
            }
            echo 
$output."\n";
            if (
$this->config['debugon'])    $this->debugWrite($output);

        }
    
// end constructor
    
}

// End class definition
}

$s=new SquidRedir();
?>
[

/php]

Вся конфигурация этого редиректора берется из файла /usr/local/redir/redir.ini :

[php]
[PHP]
implicit_flush = On
max_execution_time = 0
error_reporting = E_ALL
log_errors = On
error_log = /var/log/redir/phperror.log ; use it if have start-up problems!


[redir]
enabled = yes ; yes|no
reurl    = http://192.168.0.1/blank.gif ; URL with blank pic
path    = /usr/local/etc/squid/ ; path to 'banner' and 'noba' files
banner    = ba ; black list definition file
noba    = noba ; white list definition file
logging    = yes ; yes|no - enable to log blocked URLs
log    = /var/log/redir/redir_new.log
debugon    = no ; yes|no - enable to log all i/o with squid
debug    = /var/log/redir/redir_debug.log ; path for debug output
[

/php]

[РНР] раздел конфигурирует поведение /usr/local/bin/php через опцию -c запуска скрипта:
[php]
#!/usr/local/bin/php -c /usr/local/redir/redir.ini[

/php]

[redir] раздел конфигуриует поведение собственно редиректора.
enabled - если выставлен в NO, то не будет переписывать никаких URL, эквивалентно полному отключению редиректора
reurl - на все запрещенные страницы будет выдаваться этот URL. Там должна быть картинка (например пустой пиксел), иначе будет портиться рендеринг страниц в броузере. Если сеть не локальная, то URL должен быть реальным.
path - путь к папке в которой хранятся "черные" и "белые" списки. Выбрана директория конфигурации собственно Squid.
banner и noba - текстовые файлы со списком "черных" и "белых" URL
logging - если не выключен, то все запросы на "черные" и "белые" URL попадут в отдельный лог (полезно для сбора статистики а также выяснения причин почему некоторый сайт был заблокирован и добавление его в "белый" список или для корректировки "черного"). Формат лога: Дата-время IP/user URL
debugon - включить полное логирование всего STDIN/STDOUT

Любые изменения в секции [redir] подхватываются сразу и не требуют рестарта Squid.
Любые изменения в файлы banner/noba тоже подхватываются сразу.
Для редактирования этих текстовых файлов можно создать веб-интерфейс.
Пополнять "черные" списки можно двумя основными путями:
- запустить SARG анализатор Squid-овского access.log и посмотреть самые весомые банерные сети
- при личном посещении страниц изучить URL отображаемых банеров/счетчиков и добавить (например через веб-интерфейс)

[p]Инсталяция[/p]
# vi /usr/local/etc/squid/squid.conf (добавить директивы redirect_program)
# cd /usr/local/
# mkdir redir
# chown squid:wheel redir
# chmod 575 redir
# cd redir
# cp /home/download/redir.ini redir.ini
# cp /home/download/redir_new.php redir.php
# chmod 575 redir_new.php
# chmod 464 redir.ini
# cd /var/log
# mkdir redir
# chown squid:wheel redir
# chmod 775 redir
# cd /usr/local/etc/squid
# cp /home/download/ba ba
# cp /home/download/noba noba
# chmod +r ba
# chmod +r noba
# /usr/local/redir/redir_new.php (запустить и протестировать коректную работу)

Перезапустить Squid и протестировать работу. Файл reurl закачать на любой доступный HTTP сервер

Скачать нужные файлы можно отсюда:
[url=http://rv.uar.net/~yp/squid/redir_new.php.txt]redir_new.php.txt[/url]
[url=http://rv.uar.net/~yp/squid/redir.ini]redir.ini[/url]
[url=http://rv.uar.net/~yp/squid/ba.txt]ba.txt[/url]

[p]Эфективность[/p]
Двумесячное тестирование при сумарном веб-трафике 4,5 Гб (включая разные downloads) порезало 135 тыс. банеров

[p]TODO[/p]
- Разделить списки banner/noba из 2 файлов на произвольный массив файл (например порно в одном, баннеры в другом)
- Сделать возможность включения/отключения модуля в зависимости от IP/USER клиента (т.е. кто хочет, кто не хочет)

P.S. Если заниматься этим "по взрослому", то ставьте SquidGuard, но как же наш любимый PHP? ;)



Обсудить в ФОРУМе - комментариев (12)


Путь: Шпаргалки

Если вы заметили орфографическую, стилистическую или другую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
Контакты Design by webFaction Ukrainian PHP Group 2004-2005