|
 |
Путь: Шпаргалки
Шпаргалки
Автор: - 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->conf, true);
$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.
|
|