Cgi sElf surviving Tree Structure (CETS), или Фантазия на предмет Сетевого зоопарка.
АрхивСетевое окружение (архив)О прелести работы с автономными скриптами cgi-bin, плюс подробные примеры.
В далёком 91-ом году, в Европейском Центре Физики Высоких Энергий (CERN [1]), пытаясь удовлетворить потребность универсального доступа к данным научных исследований, Тим Бернес-Ли Tim Berness-Lee) разработал World-Wide Web (WWW). Впоследствии это превратилось в мощную отрасль hi-tech индустрии с многомиллиардными инвестициями, которые, явно пошли не зря, даже в контексте разочарований начала 2000 года. Теперь же основное, что ассоциируется со словом интернет, это, конечно же, www. Одним из характерных результатов эволюции технологий доступа к визуальной информации, стал индивидуальный подход к посетителю, учёт его реакции, и потребность получить нужные данные не только клиенту от сервера, но и наоборот (различного рода формы и т.п.). Реализовать эту идею явилась технология, под общим названием cgi-bin. Суть её заключается в автоматической генерации ответа пользователю, в зависимости от действий последнего. Передача данных web серверу осуществляется, в основном двумя способами: методы POST и GET
- Метод GET передаёт данные серверной части посредством параметров, которые отображаемются в адресе: http://server/cgi-bin/program.cgi?param1=value1¶m2=value2 HTTP демон на сервере, при получении такого запроса [2], зная, что program.cgi нужно выполнить (для *nix случая - атрибут x), запускает её. А в параметр окружения QUERY_STRING записывает, всё, что находится после вопросительного знака. Таким образом, довольно часто приходится видеть в поле адреса своего браузера, строчку типа …/login.cgi?username=fisha&password=greenpeace
- Метод POST, поступает похоже, но на этот раз browser сообщает демону, что данные программа должна получить из потока stdin [3]. А в параметр окружения CONTENT_LENGTH заносится их размер. На этот раз в поле адреса ничего уже видно не будет.
Впоследствии, на базе байтов, направляемых program.cgi на stdout формируется новый html файл, который должен будет отобразить браузер.
В интернете существуют множество серверов, бесплатно раздающих место под web site-ы, с поддержкой cgi-bin. Другими словами, всем позволяется, выполнять свои программы, на этом сервере! Во избежания несанкционированных действий (например, DoS атака, как и себя (рекурсивного замовызов), так и других объектов Сети, случайное зависание, и т.п.) были придуманы ряд защитных средств. Основными являются: ограничение на время выполнения [4], и ограничение на число одновременно запущенных копий одной программы.
Ниже описан метод создания самоподдерживающейся структуры, на базе web серверов, с учётом возможности существования описанных ограничений, способной выполнять широкий круг задач: от распределённых вычислений (на web серверах), до DoS атаки третей стороны.
Основу метода составляет следующий алгоритм:
- Все сервера (Node) объединяются в кластер, по 3 в каждом. Кластер является минимальной самоподдерживающейся единицей.
- На базе кластеров создаётся дерево. Корнем является кластер с максимальным доверием, либо top trustedкомпьютер Сети [5].
- На каждом сервере находятся 2 программы: work.cgi, и kernel.cgi и ещё конфигурационный файл: kernel.conf
- Первая, выполняет полезную работу и, если нужно, результат записывает в log файл.
- Основная задача kernel.cgi состоит в обеспечении вызова work.cgi по расписанию. Это осуществляется следующим образом:
Рассмотрим кластер:
При первом старте, kernel1 вызывает kernel2, и если нужно (время наступило) work1, потом kernel2 - kernel3 и work2 и т.д. (так же, kernel.cgi осуществляет запись в kernel.log статистики).
Очевидно, что при появлении значительных коллизий в сети, кластер будет выходить из строя. Для избежания подобных ситуаций, у данного кластера должен существовать предок (кластер, в дереве), который периодически проверяет состояние своего потомка: заглядывает в файл kernel.log, либо вызывает kernel с соответствующими параметрами, и в случае обнаружения того, что потомок успел заснуть, запускает его заново [6].
В итоге мы определили ещё одну задачу, возложенную на плечи ядра: периодическая проверка своих потомков (их адреса берутся, либо из конфигурационного файла, либо запросом у datanode-а [7] (ведь проверять потомков можно довольно редко)). В результате вырастает древовидная самоподдерживающаяся структура, которой можно управлять.
Прошу обратить внимание, что структура основывается на принципе "минимального знания", т.е. каждая нода, знает только про существование всего нескольких её подобных (например, одну соседнюю ноду (того же кластера), и потомка).
Рассмотрим алгоритмы управления:
Состав kernel.conf:
- Все временные константы (расписание/частота запуска work.cgi, частота проверки потомков и т.п.).
- Хэш собственного пароля. (Пароли у всех нод различные и хранятся только у администратора)
- Адрес data_node (если используется)
- Адреса потомков.
Администратор системы знает всю структуру, и каждый узел в ней пронумерован, поэтому предоставляется лёгкий алгоритм конфигурирования: администратор распространяет kernel.conf.new только корню дерева [8]. В этом файле могут находиться следующие данные:
- Состав kernel.conf, для каждой ноды. (который нужно передать всем нодам).
- Пароли всех нод.
Последнее требуется для авторизации предков у потомков (при переконфигурировании последних). Причём использованные пароли сразу же "забываются", а оставшиеся передаются потомкам [9] (только необходимые; это достигается расположением паролей в kernel.conf.new в правильном порядке (ведь администратор, знает, структуру дерева))
В результате, как Вы понимаете, можно перестроить и всё дерево. (Менять IPадрес соседей по кластеру, потомков и т.п.)
Для большей защиты, (в случае, если злоумышленник перехватит (не модифицировав) kernel.conf.new, где содержатся все пароли) в этом же файле можно передавать и хэш новых паролей. Таким образом, система будет функционировать на базе одноразовых паролей.
В случае же выхода из строя хотя бы одной ноды, об этом узнает её родитель, который помимо того, что сможет известить администратора (например, по e-mail-у), ещё сообщит своему предку, а тот своему и в результате информация дойдёт до корня структуры, которое, в зависимости от своих "интеллектуальных" способностей, принимает решение о перестройке дерева в наиболее стабильную структуру в новой обстановке.
В итоге мы получаем систему, в которой, даже, если, злой администратор, какого ни будь web site-a, заподозрит использование его сервера не по назначению, и заглянет в наши исходники. То, единственное, что он сможет сделать - исключить эту ноду из самоподдерживающейся структуры. Можно придумать, и другой вариант развития событий: при ранении виртуального организма (если ноду убил администратор сайта, т.е. этот хост продолжает отвечать на ping), оно начинает массированную DoS атаку места обитания погибшей ноды соответствующим сообщением (например: "Уважаемый администратор, верните пожалуйста ноду"). И если этот организм будет достаточно сильным, то он победит, т.к. не стоит забывать, о том, что не все смогут выдержать массированную DоS атаку, и некоторые предпочтут воскресить тихонькую ноду вместо того, что бы выслушивать рёв раненного животного, и том, что для его усыпления придется одновременно выключить довольно все ноды, что потребует немалых координационных усилий.
И это всё можно создать всего лишь, на базе бесплатных сервисов.
Но, к счастью на пути роста этого животного стоит преграда: в настоящий момент число бесплатных хостинг компаний, пропускающие cgi программы во вне, не так уж и много. Но, всё-таки, достаточно для выращивания первой маленькой зверюшки нового пространства.
Однако, на минутку представим, что вдруг, на большинстве постоянно подключенных к интернету компьютерах, завелись живые клетки столь грозного зверя (уже не обязательно на базе cgi-bin технологии)…
Ведь кто знает, какие дыры ещё предстоит найти в столь повсеместно используемой ОСи известной компании, и вдруг, там уже сможет поместиться такая живучесть…
<Не стоит забывать, что эволюция на Земле шла от появления вирусов до зарождения млекопитающих>
[1] Centre European pour la Recherche Nucleare [обратно к тексту]
[2] "GET /cgi-bin/program.cgi?param1=value1¶m2=value2 HTTP/1.1", "/n", различные настройки параметров соединения, "/n/n" и сервер обрывает соединение. [обратно к тексту]
[3] Запрос составляется следующим образом: "POST /cgi-bin/program.cgi HTTP/1.1","/n", различные настройки, "Content-Length: 26", "/n/n", в этот момент httpd запускает program.cgi, которая сможет прочитать из stdin на предмет уже пришедших данных. Соединение всё ещё не закрыто, и клиент должен послать обещанные 26 байт: "param1=value1¶m2=value". (Таким способом по http передаются целые файлы). [обратно к тексту]
[4] Ведь, в случае корректной работы максимум, что требуется, так это - поискать в базе данных, что обычно не должно занимать более считанных секунд. [обратно к тексту]
[5] Например, компьютер администратора (если не требуется сохранить анонимность). [обратно к тексту]
[6] Под словами кластер имеется в виду, какая ни будь нода этого кластера [обратно к тексту]
[7] Какая-нибудь trusted нода. (не обязательно использовать). [обратно к тексту]
[8] При желании этот процесс можно обезопасить, что бы не потерять контроль над структурой (если третья сторона сможет посмотреть исходный код kernel.cgi): передачу осуществлять запуском kernel.cgi с передачей пароля (например, методом GET). Причём в исходном коде должен храниться только значения хэша от пароля (например, MD5). [обратно к тексту]
[9] Ведь у этих потомков есть свои дети. [обратно к тексту]