|
Ключевые слова: cisco, banner, limit, filter, http, perl, (найти похожие документы)
From: Соколов Александр <sokoloff@sendmail.ru.> Newsgroups: email Date: Mon, 29 Dec 2004 14:31:37 +0000 (UTC) Subject: Фильтрация баннеров на Cisco Введение. --------- Как известно устройства Cisco позволяют фильтровать исходящие HTTP запросы (команды filter url и url-server), посылая запрашиваемые URL на внешний сервер для проверки. Но поддерживаются только коммерческие продукты фирм Websensc (http://www.websense.com) и N2H2 (http://www.n2h2.com). Но если задача только обрезать баннеры и не пустить людей на порно сайты, можно попытаться сделать это своими руками. Анализ протокола. Был выбран продукт Sentian от N2H2, и UDP протокол. Сервер Sentian использует порт 4005. Протокол довольно простой, в нем есть 2 фазы: проверка того, что сервер жив и собственно проверка запрошенного URL. Формат пакетов. Все передаваемые пакеты начинаются с 2-х байтного идентификатора типа. Следующие 4-е байта - номер пакета, в каждом запросе номер уникален, а в ответном пакете он совпадает с номером из запроса. Далее идут данные, про которые поговорим позже. Проверка доступности сервера. Cisco периодически (определяется параметром timeout команды url-server) посылает alive запрос. |Длина Байт |Описание |Значение 2 идентификатор типа (запрос URL-а) 02 03 4 Номер запроса Уникально 14 В alive-запросе эта часть всегда одинаковая и не используется. 00 00 00 00 00 00 00 00 00 01 00 01 00 00 Пример. 02 03 Идентификатор типа 00 01 78 24 Номер запроса 00 00 00 00 00 00 00 00 00 Данные 01 00 01 00 00 Сервер на alive-request отвечает alive-response пакетом |Длина Байт |Описание |Значение 2 Идентификатор типа (запрос URL-а) 03 02 4 Номер запроса на который отвечаем Совпадает с номером запроса 4 В alive-ответе эта часть всегда 00 00 00 00 одинаковая. Пример. 03 02 Идентификатор типа 00 01 78 24 Номер запроса 00 00 00 00 Данные Проверка запрошенного URL. Когда пользователь открывает URL, Cisco пересылает на сервер IP адрес и имя клиента, IP и URL запрошенного сервера. |Длина Байт |Описание |Значение 2 идентификатор типа (запрос URL-а) 02 00 4 Номер запроса Уникально 4 IP клиента 4 IP запрошенного сервера 2 Длинна URL с завершающим 0 2 Длинна имени с завершающим 0 ~Переменная Запрошенный URL Строка заканчивающаяся 0 ~Переменная Имя пользователя Строка заканчивающаяся 0 Пример. 02 00 Идентификатор типа 00 01 78 25 Номер запроса AC 12 0A 01 IP клиента C2 55 22 E2 IP сервера 00 17 Длина URL 00 09 Длина имени 68 74 74 70 3A 2F 2F 77 Запрошенный URL: http://www.opennet.me/ 77 77 2E 6F 70 65 6E 6E 65 74 2E 72 75 2F 00 73 6F 6B 6F 6C 6F 66 66 Имя пользователя: sokoloff 00 В ответ сервер может послать либо разрешающий, либо запрещающий пакет. Разрешающий пакет очень прост: |Длина Байт |Описание |Значение 2 идентификатор типа (запрос URL-а) 00 02 4 Номер запроса на который отвечаем Совпадает с номером запроса 4 Ответ 00 00 00 00 Пример. 02 00 Идентификатор типа 00 01 78 25 Номер запроса 00 00 00 00 Данные Теперь самое интересное, запрещающий пакет. |Длина Байт. |Описание |Значение 2 идентификатор типа (запрос URL-а) 01 02 4 Номер запроса на который отвечаем Совпадает с номером запроса 4 Длинна URL ~Переменная URL на который перенаправляем клиента Строка заканчивающаяся 0 Пример. 01 02 Идентификатор типа 00 01 78 25 Номер запроса 00 00 00 1D Длина URL 68 74 74 70 3A 2F 2F 6C URL на который перенаправляем: http://localserver/stop.html 6F 63 61 6C 73 65 72 76 65 72 2F 73 74 6F 70 2E 68 74 6D 6C 00 Теперь клиент вместо запрошенной страницы увидит http://localserver/stop.html. Очень похоже на работу баерорезалки в SQUID. Пример реализации. Пишем на perl простенький скрипт. #!/usr/bin/perl use IO::Socket::INET; use strict; my $REQ_ALIVE=0x0203; my $RES_ALIVE=0x0302; my $REQ_REQUEST=0x0200; my $RES_ACCEPT=0x0002; my $RES_DENIED=0x0102; my @banners; open (FILE, '/root/banners.txt') || die "Can't open file"; while(){ chomp; push(@banners, $_); } close FILE; &main; sub checkurl{ my $url=$_[0]; foreach (@banners){ if ($url=~/$_/i,) { return 'http://localserver/stop.html'}; }; return ''; }; sub main{ my $socket= IO::Socket::INET->new(Proto=>'udp', LocalPort=>4005); my $request; while ($socket->recv($request, 4096)){ my($code,$id,$data)=unpack("nNa*", $request); if ($code==$REQ_ALIVE) { $socket->send(pack("nNN",$RES_ALIVE,$id,0)); # Посылаем ответ, что мы живые } elsif($code==$REQ_REQUEST){ my($cl_ip1,$cl_ip2,$cl_ip3,$cl_ip4, $serv_ip1,$serv_ip2,$serv_ip3, $serv_ip4, $url_len, $name_len, $url, $name)=unpack("CCCCCCCCnnZ*Z*",$data); if (my $replace=&checkurl($url)) { print STDERR "$replace\n"; $socket->send(pack("nNN",$RES_DENIED,$id,length("$replace\x00")) . "$replace\x00"); # В ответе посылаем URL куда перенаправить. } else{ $socket->send(pack("nNN",$RES_ACCEPT,$id,0)); # Посылаем ответ, что можно }; }; }; }; В данном примере проверяется только URL ($url), но можно проверять IP сервера($serv_ip1 - $serv_ip4), IP клиента ($cl_ip1 - $cl_ip4), имя клиента ($name). На Cisco выполняем команды: url-server (inside) vendor n2h2 host 192.168.0.2 port 4005 timeout 5 protocol UDP filter url http 0.0.0.0 0.0.0.0 0.0.0.0 0.0.0.0 allow Здесь 192.168.0.2 - адрес машины где работает скрипт. Вот и все. 2004. Соколов Александр. [email protected]
|
Обсуждение | [ Линейный режим | Показать все | RSS ] |
|
Добавить комментарий |
Закладки на сайте Проследить за страницей |
Created 1996-2024 by Maxim Chirkov Добавить, Поддержать, Вебмастеру |