div.main {margin-left: 20pt; margin-right: 20pt}Эхо боя, оптимизация логов
DL 16.08.2001
Дал знакомому посмотреть сайт, который дома тестирую. Он посмотрел, похвалил,
а я решил посмотреть, что он видел. Открываю логи Апача, смотрю и через
некоторое время обнаруживаю, что кроме товарища ещё кто-то лазил на мой домашний
сервер.
Вот он, вирус CodeRed, о котором так долго твердили
большевики.
"GET
/default.ida?XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX%u9090%u6858%ucbd3%u780 1%u9090%u6858%ucbd3%u7801%u9090%u6858%ucbd3%u7801%u90 90%u9090%u8190%u00c3%u0003%u8b00%u531b%u53ff%u0078%u0 000%u00=a
HTTP/1.0" 404 270
В те моменты, когда я подключался к сети по диалапу со включенным Апачем, ко
мне, словно звуки далёкой канонады, приходили такие запросы. Учитывая то, что в
IPv4 2^32 адресов, по которым вирус рассылается случайным образом, можно
восхищаться масштабами его распространения.
Заодно перенастроил правила в
Atguard, чтобы не разрешать соединяться с Апачем откуда-то ни было кроме
127.0.0.1.
Кстати, именно как по эху — вернее как по кругам на
воде — недавно замерили активность и направленность DoS-атак во всём
интернете (русский комментарий к результатам — здесь [1]). При
отправке запроса на соединение хулиган, чтобы не быть пойманным, меняет обратный
адрес IP-пакета на случайный. Имея много ip-адресов, можно собирать приходящие
ответы от атакуемых серверов и делать расчёты. Интересно, можно ли, слушая
запросы из сети и имея алгоритм выбора случайного числа вируса CodeRed
(насколько я понял из сетевых обзоров, две его версии можно отличить по строке
запроса), подсчитывать количество заражённых?
RomikChef прислал
описание оптимизации работы с логами.
О! Какая статья интересная, а я
и не читал :-( А может, и хорошо, что не читал, потому что всё по-другому
сделал. Мне кажется, что у Димы не очень удачная организация базы.
У меня
запись занимает ровно 20 байт. может быть, это тоже не самая удачная, но, сами
понимаете, размер на порядок, а то и на два меньше.
id — 4
байта ip — 4 байта таймстамп — 4 байта дальше идут ссылки на
словари, каждая по 2 байта page — $PHP_SELF agent —
бровзер реферер — реферер баннер — баннер
Теперь по
пунктам.
- ip, упакованный в 4 байта, это, конечно, короче, чем хост. Тем
более, что толку от хоста в базе нет. И группировать по int, мне кажется, база
будет быстрее, чем по строкам. Да, вывод информации происходит медленнее,
поскольку надо ресолвить сразу кучу адресов. Но я могу и подождать — при
просмотре торопиться некуда. Имхо. А вот при записи на ресолвинг времени не
тратится. - таймстамп не родной, а юниксовский. И не потому, что родной
занимает на 1 байт больше, а потому, что когда пришлось логи малость подправить,
сами понимаете, стампы все сбились. - page. Это понятно. Словарь всех страниц
сайта. Таблица небольшая, всё летает. - агент. То же самое. -
баннер — тоже понятно. Какой баннер был показан. - реферер. Самое шаткое
место. Да, таблица растет. но, как вы понимаете, 90% рефереров — со своего
сайта. В принципе, одиночные реферера можно и почистить. Query_string у
внутренних рефереров отсекается. У чужих — отсекается тоже и пишется
отдельно, для анализов.
Теперь по замечаниям в обсуждениях. Да, я пишу
все хиты. Во-первых, при моем размере записи это не напряжно. во-вторых, если
чувак нажал релоад, ему показался другой баннер, мне это надо
учитывать.
И ещё. Вопрос. Кто как отличает роботов от людей? Я определяю
по включенной графике. И в принципе, моя статистика не сильно разнится со
спайлоговской.
Что там у меня было раньше?
CREATE TABLE logs (
date datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
(можно TIMESTAMP)
ip varchar(16) NOT NULL,
host varchar(255) NOT NULL,
browser varchar(64) NOT NULL,
referer varchar(255) NOT NULL,
request_uri varchar(255) NOT NULL,
);
Признаться, я делал эту систему, когда не знал существования функций ip2long [2] и long2ip [3]. Потом
переделывать руки не доходили. А преобразуется ip-адрес в целое число
переведением всех четырёх чисел адреса в двоичный код (с дополнительными нулями:
255 переводится в 11111111, а 4 — в 00000100), убираются точки, и
получившееся число переводится обратно в десятичный. В IPv4 может быть 2^32
адресов, т.е. (2^8)^4 — итого число занимает четыре байта.
Timestamp
из Юникса пишется просто — функция UNIX_TIMESTAMP. Выбирается так же
просто — для группировки по дням, неделям, дням недели или чему-то ещё
используется стандартная функция MySQL FROM_UNIXTIME:
SELECT
DATE_FORMAT(FROM_UNIXTIME(date),'%e.%m.%Y') AS date_group, COUNT(ip) AS visits
FROM logs GROUP BY date_group ORDER BY
DATE_FORMAT(FROM_UNIXTIME(date),'%Y%m%d');
Чем больше узнаёшь возможностей MySQL, тем больше кажется, что ты ничего не
знаешь. Каких там функций только нет!
В чём я не уверен, так это в
целесообразности держания словарей адресов, рефереров и броузеров. Надо при
записи лога выбирать идентификаторы, проверять, вставлять новую запись, если
таковой не нашлось.
$page_result = mysql_query("SELECT id
FROM page WHERE address='$PHP_SELF'"); if
(@mysql_num_rows($page_result)==1) $page_id =
mysql_result($page_result, 0); elseif (!mysql_error())
{ mysql_query("INSERT INTO page (address) VALUES
('$PHP_SELF')"); $page_id =
mysql_insert_id(); };
Не хочется объединять таблицы при запросе, хотя меньше данных надо
обрабатывать — в главной таблице объём файла становится гораздо меньше, что
ускоряет работу. Неясно, правда, сколько дополнительного времени это займёт при
записи логов. По этому вопросу и мне, и Ромику хотелось бы услышать мнение
общественности. Прошу высказываться в отзывах.
Ссылки, использованные в выпуске:1)
http://ww.cnews.ru/topnews/2001/05/28/content3.shtml 2)
http://www.php.net/manual/en/function.ip2long.php 3)
http://www.php.net/manual/en/function.long2ip.php
Полная версия выпуска: http://detail.phpclub.net/news/01-08-16/
© Дмитрий Лебедев <dnl@au.ru> © Клуб
PHP-разработчиков <http://phpclub.net/>
|