93
№12(25) декабрь 2004 подписной индекс 81655 www.samag.ru Единая учетная запись для Windows и UNIX в Active Directory Копирование файлов в автоматическом режиме с множества компьютеров через SSH Защита сетевых сервисов с помощью stunnel Использование аппаратных ключей в целях аутентификации в Linux Система обнаружения атак SHADOW Биллинг для АТС на базе PostgreSQL Обработка переадресованных http-запросов Автоматизация FTP с помощью Python Единая учетная запись для Windows и UNIX в Active Directory Копирование файлов в автоматическом режиме с множества компьютеров через SSH Защита сетевых сервисов с помощью stunnel Использование аппаратных ключей в целях аутентификации в Linux Система обнаружения атак SHADOW Биллинг для АТС на базе PostgreSQL Обработка переадресованных http-запросов Автоматизация FTP с помощью Python №12(25) декабрь 2004

025 Системный Администратор 12 2004

Embed Size (px)

DESCRIPTION

№12(25) декабрь 2004 подписной индекс 81655 www.samag.ru №12(25) декабрь 2004 82 Идеальный карманный компьютер для системного администратора Часть 2 Копирование файлов в автоматическом режиме с множества компьютеров через SSH Содержание журнала за 2004 год 92 Железный login: ломаем зубы грубой силе Защита сетевых сервисов с помощью stunnel БЕЗОПАСНОСТЬ 4 1 2 репортажрепортажрепортажрепортажрепортаж Делай раз: установка администрирование 4 администрирование 5 Ðèñóíîê 1. Êëèåíò Click-N-Run

Citation preview

Page 1: 025 Системный Администратор 12 2004

№12(25) декабрь 2004подписной индекс 81655

www.samag.ru

Единая учетная запись для Windowsи UNIX в Active Directory

Копирование файловв автоматическом режимес множества компьютеров через SSH

Защита сетевых сервисовс помощью stunnel

Использование аппаратных ключейв целях аутентификации в Linux

Система обнаружения атак SHADOW

Биллинг для АТС на базе PostgreSQL

Обработка переадресованныхhttp-запросов

Автоматизация FTP с помощью Python

Единая учетная запись для Windowsи UNIX в Active Directory

Копирование файловв автоматическом режимес множества компьютеров через SSH

Защита сетевых сервисовс помощью stunnel

Использование аппаратных ключейв целях аутентификации в Linux

Система обнаружения атак SHADOW

Биллинг для АТС на базе PostgreSQL

Обработка переадресованныхhttp-запросов

Автоматизация FTP с помощью Python

№12

(25)

де

кабр

ь 20

04

Page 2: 025 Системный Администратор 12 2004
Page 3: 025 Системный Администратор 12 2004

1№12(25), декабрь 2004

оглавление

Идеальный карманный компьютердля системного администратораЧасть 2

Андрей Маркелов[email protected] 8

Дистрибутив для всех

Сергей Яремчук[email protected] 10

Linspire одним глазком

Валентин Синицын[email protected] 4

Копирование файловв автоматическом режимес множества компьютеров через SSH

Рашид Ачилов[email protected] 12

Единая учетная записьдля Windows и UNIXв Active Directory

Игорь Полянский[email protected] 18

FreeBSD tips: настройка VLANСергей Супрунов[email protected] 24

Биллинг для АТС на базе PostgreSQL

Георгий Толоконников[email protected] 26

АДМИНИСТРИРОВАНИЕ

Пакетный фильтр OpenBSDЧасть 2

Денис Назаров[email protected] 30

Защита сетевых сервисовс помощью stunnel

Андрей Бешков[email protected] 42

Настоящий UNIX в наши дни

Александр Байрак[email protected] 34

Автоматизируем FTP с помощью Python

Сергей Супрунов[email protected] 36

БЕЗОПАСНОСТЬ

Железный login:ломаем зубы грубой силе

Александр Похабов[email protected] 48

Тени исчезают в полдень

Сергей Яремчук[email protected] 54

PHP-GTK

Андрей Уваров[email protected] 60

Обработка переадресованныхhttp-запросов

Алексей Мичурин[email protected] 62

Запись дисков CD-R/RW в LinuxЧасть 2

Владимир Мешков[email protected] 68

Файловая система NTFS извне и изнутриЧасть 2

Крис Касперски[email protected] 76

WEB

HARDWARE

ОБРАЗОВАНИЕ

Разработка сценария регистрациипользователей в сетиЧасть 2

Иван Коробко[email protected] 82

РЕПОРТАЖ 2

Содержание журнала за 2004 год 92

BUGTRAQ 33, 53, 91, 94

Page 4: 025 Системный Администратор 12 2004

2

репортажрепортажрепортажрепортажрепортаж

3 декабря 2004 года компания Agnitum (www.agnitum.com) –разработчик популярного персонального брандмауэраOutpost Firewall Pro анонсировала выход новой версии свое-го продукта – Outpost Office Firewall, нацеленного на исполь-зование в корпоративных локальных сетях в качестве сред-ства персональной защиты клиентских компьютеров. Новаяразработка явилась продолжением работы над очереднойверсией брандмауэра – Outpost Firewall Pro 2.5. Стоит отме-тить, что речь идет не о серверном варианте Outpost Firewall,а именно об офисной версии, то есть специализированномПО, предназначенном для массового развертывания в кор-поративной сети, на компьютерах пользователей.

Презентация проходила в Санкт-Петербурге, на бортулегендарного крейсера «Аврора», что само по себе явилосьудивительным сюрпризом. Главный менеджер по продажамНиколай Васильев и координатор российского проекта,организатор презентации Ольга Величко (на фото) расска-зали, что они давно хотели провести презентацию на этомисторическом крейсере под лозунгом «Революция в миреинформационных технологий».

В назначенное время у трапа крейсера собрались жур-налисты практически всех популярных IT-изданий России.На борту представителей прессы встречали В.И. Ленин ивоенные матросы, вручая каждому морскую бескозырку сленточкой, на которой было написано «Outpost Firewall Pro».

Расскажем о впечатлениях от анонса и о заявленныхвозможностях нового продукта.

В качестве клиентской части Outpost Office Firewall бу-дет содержать некоторое подобие Outpost Firewall Pro 2.5.Дистрибутив брандмауэра поставляется в формате MSI, чтопозволяет для развертывания его в домене Active Directoryиспользовать групповые политики. К сожалению, в пилот-ной версии другие возможности удаленной установки под-держиваться пока не будут. Таким образом, автоматичес-кое развертывание Outpost Firewall будет возможно тольков доменах Active Directory и только на компьютерах сWindows 2000 и старше. В остальных случаях установкупридется произвести вручную. Возможность удаленной ус-тановки при помощи RPC, а не через групповые политикипланируется реализовать в следующих версиях.

Клиентская часть после установки взаимодействует ссервером и нацелена на работу в корпоративной сети. Вчастности, контроль компонентов приложений (ComponentControl) и контроль скрытых процессов (Hidden ProcessControl) будут выключены по умолчанию, а брандмауэр бу-дет загружаться в фоновом режиме. Это обеспечит мини-мальное вовлечение пользователя в процесс защиты ком-пьютера – многочисленные запросы сетевого доступа при-ложениями могли бы ввести неопытного пользователя взамешательство. К сожалению, клиентская часть OutpostOffice Firewall несовместима с предыдущими версиями про-граммы. Если на некоторых компьютерах уже установленаодна из предыдущих версий, включая Outpost Firewall 2.5,ее необходимо полностью удалить перед установкой офис-ного варианта. Новых серьезных изменений по сравнениюс версией 2.5 в клиентской части практически не будет. Фун-кциональность нового продукта будет постоянно улучшать-ся, а переговоры с создателями антивирусных продуктов ореализации совместных решений помогут привести к со-зданию надежной комплексной защиты. Например, реали-зовать защиту от программ типа Ad-Aware, количество ко-торых в последнее время угрожающе растет.

Средством управления и мониторинга будет служитьOutpost Command Center, выполненный в виде оснастки «Кон-соли управления» (MMC snap-in), через который осуществ-ляется управление службами, запуск редактора настроек ипубликация конфигураций для клиентских машин. Одновре-менно с ним устанавливается редактор настроек, предназ-наченный для конфигурирования брандмауэра на клиентс-ких машинах, а также «Служба обновлений» и «Служба пуб-ликации».

Конфигурации клиентам передает «Служба публика-ции». Она запускается на том же сервере, где и «Команд-ный центр» Outpost, и также управляется с его помощью.При каждой загрузке компьютер пользователя запрашива-ет у сервера конфигурацию. Если были созданы и опубли-кованы новые настройки, то «Служба публикации» пере-дает клиенту файл по внутреннему протоколу. После полу-чения настроек брандмауэр на компьютере пользователяприменяет их. Период запроса клиентами обновлений кон-фигурации – изменяемый параметр. Однако форсироватьнемедленное обновление на клиентах пока нельзя. Возмож-но, это появится в следующих версиях.

В первой версии Outpost Office Firewall не предвидитсявозможности назначения разных конфигураций различнымгруппам клиентов, а также не планируется разрешать ре-дактирование отдельных записей в конфигурации без зат-рагивания остальных параметров.

По словам представителей компании выпуск коммер-ческой версии продукта ожидается примерно в феврале2005 года.

Роман МарковФото автора

AGNITUM OUTPOST OFFICE FIREWALLНОВЫЙ АСПЕКТ КОРПОРАТИВНОЙ ЗАЩИТЫ

Page 5: 025 Системный Администратор 12 2004
Page 6: 025 Системный Администратор 12 2004

4

администрирование

Фирма Linspire (www.linspire.com) – ветеран движения за по-пуляризацию Linux, хотя самой торговой марке едва насчи-тывается пять месяцев. Между тем компания была основа-на в далеком 2001 году. С тех пор и по сей день ее бес-сменным управляющим является всемирно известный аван-тюрист-инноватор Майкл Робертсон (Michael Robertson), со-здатель портала MP3.com. Первоначально компания назы-валась Lindows, а ее основное детище и герой сегодняш-ней статьи, настольный дистрибутив Linux, – LindowsOS.Такое явное созвучие с «Окнами» не могло понравитьсякорпорации Microsoft и очень быстро стало предметом мно-гочисленных судебных разбирательств как на территорииСША, так и за их пределами. Тяжба не утихала в течениенескольких лет, причем фортуна практически равным об-разом благоволила как той, так и другой стороне. Вконецпогрязнув в пучине судебных баталий, Lindows, Inc. иMicrosoft в июле этого года пришли к мировому соглаше-нию, по которому все права на торговую марку «Lindows» исоответствующие доменные имена отошли в «Редмонд»,правда, не безвозмездно. Размер контрибуции составилоколо 20 млн. долларов. Вполне удовлетворенная исходомдела, Lindows сменила имя на Linspire и с большой выго-дой продала свою прежнюю вывеску на аукционе eBay.

На сегодняшний день компания представляет широкиймодельный ряд, включающий базовую редакцию Linspire4.5, профессиональную Linspire 4.5 Developers Edition, заг-ружаемый диск LinspireLive! и специальную версиюLinspireEspaсol для испаноязычных пользователей. Поми-мо этого имеются различные дополнения, например,LinspireOffice. Ранее существовала еще одна разновид-ность – Laptop Edition, предназначенная для ноутбуков, носейчас она, по-видимому, слилась с базовой версией.

Как и многие настольные дистрибутивы, Linspire явля-ется коммерческим программным продуктом. Цена базо-вой редакции – 49,95 доллара. Версия для разработчиковстоит чуть дороже – $59,95. LinspireLive! можно приобрестиза $19,95 или (официально!) загрузить через файлообмен-ную сеть BitTorrent. Выбрав столь оригинальный (для по-

ставщиков закрытого ПО) канал доставки, компания выз-вала сильное удивление у коллег по цеху, а г-н Робертсон вочередной раз подтвердил звание большого затейника.Подробности доступны по адресу: http://info.linspire.com/p2p/p2p-pr.html. Иногда (правда, в последнее время все реже иреже) Linspire проводит промо-акции, в ходе которых тре-буется угадать текст купона (как правило, это нечто оче-видное для тех, кто внимательно следит за заголовкаминовостных лент), ввести его и получить стопроцентную скид-ку в интернет-магазине компании. После этого ISO-образдистрибутива можно загрузить бесплатно через HTTP иливсе тот же BitTorrent.

В данном обзоре мы рассмотрим основные возможнос-ти Linspire 4.5.189 Developers Edition, датированной янва-рем 2004 года. С тех пор было выпущено несколько исправ-лений (об их роли в этой истории мы поговорим чуть поз-же), однако базовая функциональность системы не претер-пела существенных изменений.

Делай раз: установкаИтак, вставляем компакт-диск с Linspire в оптический при-вод и перезапускаем компьютер. Нашему взору представ-ляется графический splash-экран с логотипом компании именю с двумя загрузочными опциями: Install и Diagnostic. Пос-ледний вариант может использоваться для тонкой (эксперт-ной) настройки параметров или восстановления системы.Выбрав его и подождав достаточное время, можно попастьв текстовую консоль и, например, переразбить жесткий диск,пользуясь командой fdisk или же реанимировать файловуюсистему с помощью fsck. Из важных утилит в этом режимене доступен, пожалуй, один hdparam (читатели, у которыххотя бы раз «взрывался» хорошо раскрученный CD-ROM,меня поймут). Впрочем, развитие промышленности идет се-мимильными шагами и несбалансированные/некачествен-ные диски сейчас встречаются все реже и реже.

Сделав все необходимое, можно начать установкуLinspire командой startx или же выйти из диагностическогорежима, набрав exit.

LINSPIRE ОДНИМ ГЛАЗКОМ

ВАЛЕНТИН СИНИЦИН

Page 7: 025 Системный Администратор 12 2004

5№12(25), декабрь 2004

администрирование

Программа-инсталлятор, напротив, является воплоще-нием простоты. Достаточно упомянуть, что она состоит мак-симум из четырех экранов. Вначале пользователю предла-гается выбрать один из двух режимов: Take Over An EntireHard Disk («Занять жесткий диск целиком» – режим по умол-чанию, хорошо подходит для установки на чистый нераз-меченный диск и не требует вмешательства пользователя)или Advanced Install. «Продвинутость» в данном случае оз-начает возможность указать существующий раздел для ин-сталляции корневой файловой системы. Изменить их струк-туру программа не позволяет, вероятно, для того, чтобы нео-пытный пользователь нечаянно не уничтожил данные на со-седнем Windows-разделе. После осуществления выбора мыпереходим на третий экран, где предлагается ввести имядля нашего компьютера и пароль. Последняя настройка яв-ляется необязательной, что очень понравится пользовате-лям Windows 9x и приведет в ужас бывалых администрато-ров. Программа не проверяет введенные пароли на проч-ность: хотите «123456» – пожалуйста. После заполненияданных полей ваше участие в процессе заканчивается исистема приступает к копированию файлов. Вполне оправ-дывающий себя подход, по крайней мере до тех пор, покане возникнет внештатная ситуация.

Сообщения инсталлятора об ошибках малоинформатив-ны и обычно состоят из числового кода, краткого описания(например: «200: rsync failed» или «255 Unspecified Error») ипредложения обратиться в службу технической поддерж-ки, которая, как следует из периодически появляющейся входе установки рекламной картинки, доступна через Web ипо телефону, правда, не круглосуточно. Опыт показывает,что специалисты откликаются достаточно быстро, однакона вопрос о причинах неудачи разводят руками: мол ошиб-ка, знаем, работаем. Возможно, build 189 был в этом отно-шении не слишком успешным (как уже упоминалось ранее,с тех пор вышло несколько исправлений, и текущий релизимеет номер 444), но мне с трудом удалось найти компью-тер, на который Linspire поставился без сучка и задоринки.Особенно обидно, что в число «неприкасаемых» попал имой ноутбук, с помощью которого предполагалось прове-рить на практике, насколько хорошо система поддержива-ет работу с беспроводными сетями. Эта возможность ши-роко рекламируется в руководстве пользователя, что вну-шает некоторое уважение: прочие дистрибутивы Linux, ори-

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

В процессе установки программа сама отформатируетпредназначенный системе раздел. В качестве файловой си-стемы по умолчанию (впрочем, этот термин здесь не впол-не уместен, ведь ничего другого выбрать не предложили)используется ReiserFS, что неудивительно – Linspire спон-сирует ее разработчиков, о чем красноречиво свидетель-ствует лейбл на сайте Namesys (www.namesys.com). Этакомпания вообще поддерживает или принимает участие вдостаточно большом числе открытых проектов, в том чис-ле KDE (www.kde.org) и Mozilla (www.mozilla.org), и даже снекоторых пор имеет собственную Open Source инициати-ву – Nvu (www.nvu.com), задача которой ни много ни мало –создать свободный аналог Macromedia DreamWeaver иMicrosoft Frontpage. В качестве основы используется редак-тор Mozilla Composer. Проект делает определенные успе-хи: по крайней мере все новые страницы на сайте Linspireразработаны с помощью Nvu.

Завершив (ура!) копирование файлов, инсталлятор вы-даст соответствующее сообщение и предложит перезагру-зить систему. Добро пожаловать в мир настольного Linux!

Делай два: первый запуски постинсталляционная настройкаПосле неизбежного перезапуска мы видим уже знакомуюзаставку и меню, на этот раз содержащее три опции. Двеиз них нам хорошо известны и предназначены для нормаль-ного старта системы и перехода в экспертный режим. Сред-няя, «Redetect», используется для обнаружения нового обо-рудования. Дождавшись загрузки системы (наберитесь тер-пения – как и многие настольные дистрибутивы, Linspire неслишком легок на подъем. Это неизбежная плата за отсут-ствие тонкой настройки) и введя пароль (если таковой име-ется), мы окажемся в окне мастера первого запуска, кото-рый предложит нам ознакомиться с лицензией и установитьряд параметров. Беглый взгляд на соглашение конечногопользователя (EULA) обнаруживает занятную вещь – лицен-зия Linspire является Family Friendly. Говоря русским язы-ком, одну копию системы можно легально установить нанеограниченное число компьютеров, владельцы которых со-ставляют одну семью. Не вдаваясь в юридические тонко-сти, отметим явное преимущество такого договора как длянас с вами, так и для производителя: если отечественныйпользователь худо-бедно свыкся с мыслью о том, что про-граммы имеют лицензию, которую надо соблюдать, то пла-тить за себя, за маму и за папу он точно не станет. Нажавна расположенную в окне кнопку «Advanced», можно доба-вить новые учетные записи (по умолчанию вы заходите всистему как root) или настроить экранное разрешение, глу-бину цвета и частоту развертки (в состав Linspire входятфирменные драйверы ATI и Nvidia, поэтому приготовьтеськ высокому refresh rate). Программа также предложит вамнастроить системное время. Выполнив все необходимыеоперации, можете спокойно выходить из мастера. Вас ждетсюрприз: одно из фирменных аудиоруководств Linspire! В

Ðèñóíîê 1. Êëèåíò Click-N-Run

Page 8: 025 Системный Администратор 12 2004

6

администрирование

ходе интерактивных уроков, выполненных с использовани-ем технологии Macromedia Flash (конечно, проигрывательFlash-роликов также включен в комплект поставки), пользо-ватель может получить представление о возможностях си-стемы и приобрести базовые навыки работы с нею. Значи-тельная часть первого руководства посвящена технологииCNR («Click-N-Run»), речь о которой пойдет чуть ниже. Ксожалению, эта красота требует жертв: после несколькихуроков, прослушанных на моем компьютере, диктор стал«заикаться», а потом и вовсе умолк. Пришлось лечить сис-тему с помощью Quick Restart, по-простому – перезагрузкиX-сервера.

Как и многие современные дистрибутивы, Linspire не-мыслим без Интернета. По утверждению разработчиков,кабельное подключение система распознает и конфигу-рирует в полуавтоматическом режиме (пользователю мо-жет потребоваться ввести IP-адрес и т. п.). Для «счастли-вых» владельцев модемов на рабочий стол вынесена спе-циальная пиктограмма – Internet Connection Tools. Созда-тели Linspire позаботились о клиентах крупнейших интер-нет-провайдеров США (AOL, Juno, Earthlink и т. д.) – имдостаточно просто щелкнуть по иконке с нужным именем.Остальным предлагается настроить KPPP (а именно этаутилита используется для доступа в Интернет) вручную –подробное руководство прилагается. Сверх указанных ав-торами мер мне пришлось лишь указать устройство, к ко-торому подсоединен мой модем, в настройках этой заме-чательной утилиты.

Теперь, когда вы подключены к Всемирной паутине, на-стало время познакомиться с «жемчужиной» Linspire – CNRWarehouse.

Делай три: Кладовая «Раз – и готово»Не пугайтесь непривычных слов: примерно так переводитсяна русский язык словосочетание «Click-N-Run Warehouse»,обозначающее технологию, разработанную в Linspire с це-лью упрощения установки нового ПО и обновления систе-мы. Зависимости всегда были бичом Linux, и любой созда-тель дистрибутива, претендующий на место в сердцах сред-нестатистических пользователей, должен позаботиться оскруглении «острых углов». В настоящий момент с помо-щью CNR Warehouse можно установить более 1900 про-

грамм, как открытых, так и коммерческих. Для этого потре-буется доступ в Интернет и несколько щелчков мышью. Кли-ент Click-N-Run (рис. 1) автоматически скачает и установитвыбранные вами программы, а также позволит добавитьиконку на рабочий стол или в меню Autostart. Вы можетеинсталлировать как отдельные приложения, так и целые на-боры – «Aisles», созданные разработчиками Linspire илидругими пользователями. Членство в CNR платное (4,95доллара в месяц или 49,95 год), однако «прикоснуться кпрекрасному» можно и даром. Достаточно ввести номеркредитной карточки, и в течение 15 дней вы можете пре-кратить подписку, не заплатив ни цента за загруженныйсофт. Переведя эти деньги в отечественную валюту, полу-чим 120-150 рублей в месяц, то есть намного меньше, чембольшая часть жителей нашей страны тратит на сотовыйтелефон. Важным ограничивающим фактором является ши-рина канала: скачать большую часть интересных приложе-ний по модему практически нереально, а оплата трафикапри использовании выделенной линии может влететь в ко-пеечку.

Таким образом, целевая аудитория CNR Warehouse унас в России, по сути, ограничена пользователями unlimited-тарифов. Большая часть репозитария CNR бесплатна дляподписчиков, исключения составляют коммерческие при-ложения, на которые предоставляются ощутимые скидки.Единожды загрузив какую-либо программу из CNRWarehouse, вы становитесь ее собственником навеки и смо-жете вновь получить к ней доступ, когда потребуется. Су-ществование этого банка программ создает определеннуюспецифику Linspire. В состав системы включен самый ми-нимум приложений (нет ни офисного пакета, ни графичес-кого редактора, ни проигрывателя видеофильмов). Все ос-тальное предлагается загружать из CNR. Каждый пунктменю «Launch» (аналог кнопки «Пуск» Windows) включаетобязательную ссылку на Warehouse, поэтому логотип дан-ной технологии – бегущий человек в зеленом круге – выбудете видеть довольно часто.

Постоянное желание «выклянчить пару баксов» являет-ся несомненным минусом Linspire. Впрочем, выход, как все-гда, есть. Дистрибутив основан на Debian и содержит необ-ходимый для опытного пользователя инструментарий: dpkgи apt-get, с помощью которого можно устанавливать пакетыв формате deb. Редакция Developers Edition, помимо этого,включает в себя полный комплект средств разработки (втом числе среду KDevelop), что позволяет собирать пакетыиз исходных текстов. Может быть, это и неэстетично, но покрайней мере дешево. Таким образом я скомпилировал «про-грамму в правом нижнем углу» – системный монитор gkrellm(http://web.wt.net/~billw/gkrellm/gkrellm.html).

В меню утилита не появилась, но зато работала какчасы. Другое дело, захочет ли Пользователь с большойбуквы связываться с инструментами командной строки?Можно сказать, что CNR Warehouse отражает идеологиюOpen Source: брать деньги не за ПО, а за услуги, то есть зажелание клиента не делать чего-то самостоятельно.

Однако, несмотря на все многообразие приложений дляLinux, пользователь может захотеть запустить и какую-топрограмму для Win32, например, игру. Что же предостав-ляет Linspire для этой категории граждан? Исходной целью

Ðèñóíîê 2. Linspire 4.5: ðàáî÷èé ñòîë ïî óìîë÷àíèþ

Page 9: 025 Системный Администратор 12 2004

7№12(25), декабрь 2004

администрирование

разработчиков Lindows была практически стопроцентнаясовместимость с Windows-приложениями (отчасти поэтомуей и было присвоено столь «неудачное» имя). Стремясь до-стичь ее, компания не жалела денег на инвестиции, в пер-вую очередь, в проект Wine (http://www.winehq.com). Одна-ко, спустя некоторое время г-н Робертсон изменил курс.Сославшись на дороговизну продуктов для Windows, онпредложил сконцентрировать все усилия на написании ихполноценных аналогов (чем компания сейчас и занимает-ся, достаточно вспомнить тот же Nvu). Было ли это реаль-ной причиной или же стопроцентная эмуляция Win32 APIоказалась чересчур трудоемкой задачей, науке доподлин-но неизвестно, но факт остается фактом: в смысле двоич-ной совместимости с Windows у пользователей Linspire нетособых преимуществ перед «простыми смертными». ЧерезCNR Warehouse доступны все те же Wine, NeTraverseWin4Lin (около 70 долларов с учетом «клубной скидки») иWineX (приблизительно 15 долларов). Весьма популярныйпакет CrossOver Office, базирующийся на Wine, и входящийв комплект поставки конкурентов Linspire (Lycoris Desktop/LX и Xandros), в CNR Warehouse отсутствует.

Как вы уже, наверное, обратили внимание, названия ин-терфейсных элементов в данной статье приводятся на анг-лийском языке. Это происходит вовсе не из-за прозапад-ной ориентации автора – английский является языкомLinspire по умолчанию, а помимо него, система официаль-но поддерживает лишь испанский. В отличие от Linare (см.статью «Заметки о Linare», журнал «Системный админист-ратор», №11, ноябрь 2004 г.), где поддержка кириллицывыдрана с корнем, научить Linspire хоть как-то говорить по-русски возможно. Для этого потребуется установить стан-дартный пакет локализации KDE и шрифты все из того жеCNR Warehouse.

Среди заслуживающих внимания приложений, входящихв состав «Кладовой», следует назвать авторские разработ-ки Linspire: аудиоплейер в стиле «все в одном2 Lsongs (http://info.linspire.com/lsongs), аналогичный iTunes и фотоальбомLphoto (http://info.linspire.com/lphoto), заменяющий iPhoto.Обе программы бесплатны для подписчиков CNR и стоятоколо 20 долларов для остальных.

Делай четыре: приступаем к работеИтак, все подготовительные операции завершены, допол-нительное ПО установлено, и мы можем наконец-то при-ступить к тому, ради чего все и затевалось, – работе. Вне-шний вид Linspire 4.5 представлен на рис. 2. В качестве ра-бочего стола используется KDE. Содержимое меню«Launch» (зеленая буква «L» в левом нижнем углу) стара-тельно повторяет привычное пользователям Windows (кро-ме тех, кто успел основательно обжиться в XP): те жеPrograms, Settings, Search и Run Command. В устоявшийсяпорядок вещей добавлен всего один штрих – опция«Terminate Program» («Снять программу»). При ее выборе(равно как и при нажатии магической комбинации <Ctrl-Alt-Del>) на экране появляется дерево запущенных процессов.Во время своего старта система автоматически загружаетапплет, извещающий пользователя о наличии новых сооб-щений в почтовом ящике (конверт в правом нижнем углу) –мелочь, а удобно. Для чтения писем, а также просмотра Web

и создания HTML-документов используется интернет-пакетMozilla.org. Не так давно компания MozDev Group (http://www.mozdevgroup.com) по заказу создателей дистрибути-ва расширила его возможности интегрированным поиском(по любому слову на странице, в теле письма и т. д.) и про-веркой правописания. Функция имеет название Hot Words(http://info.linspire.com/suite.html) и доступна, как и все в миреLinspire, через CNR Warehouse. В состав Linspire 4.5 вклю-чены также интернет-пейджер GAIM (gaim.sourceforge.net)и IP-телефон SIPphone (www.sipphone.com).

Поинтересуйтесь у начинающего линуксоида, что емукажется самым непонятным в этой системе. Уверен, в «го-рячую десятку» непременно попадет процедура подключе-ния (mount) разделов, особенно остро встающая для съем-ных носителей: дискет, компакт-дисков, USB Flash и т. д.Здесь Linspire оказался на высоте. Вставленный в USB-разъем «брелок» система опознала сразу, о чем уведоми-ла меня, разместив пиктограмму «Flash Disk» на рабочемстоле. Вставленный в привод DVD-ROM оптический дискбыл также легко опознан и смонтирован, а вот с его отклю-чением возникли небольшие проблемы. В случае, если оноказывался занят (в понимании Linux – например, было от-крыто окно с деревом расположенных на нем каталогов),система игнорировала нажатие на кнопку Eject на переднейпанели. Такое поведение родного компьютера может сму-тить и испугать новичка. Было бы лучше, если бы Linspireвыдавала диалог с сообщением о невозможности извлече-ния диска и списком потенциальных причин (или даже на-званием приложения, использующего CD/DVD-ROM в дан-ный момент).

Вот и подошел к концу этот небольшой обзор. Что мож-но сказать в заключение? По-моему, Linspire – это непло-хой дистрибутив, страдающий излишним интересом к день-гам своего владельца и отсутствием полноценной русифи-кации, но, несмотря на это, предоставляющий достаточныйкомфорт для домашнего и офисного применения. Если увас есть широкий канал в Интернет – загрузите LinspireLive.Возможно, он вам понравится. Если что-то не получилось,не расстраивайтесь – Linspire не единственный в своемроде. В январском номере журнала мы рассмотрим LycorisDesktop/LX, загадочный дистрибутив от компании, ранееизвестной как Redmond Linux.

Ðèñóíîê 3. Ïîíàäîáèëñÿ îôèñ? Äîáðî ïîæàëîâàòü â CNR Warehouse!

Page 10: 025 Системный Администратор 12 2004

8

администрирование

Обновляем системное программноеобеспечение КПКЗа время, прошедшее с выхода первой части статьи1, ком-пания Sharp успела выпустить преемника рассматриваемоймодели карманного компьютера, в основном отличающе-гося наличием четырехгигабайтного жесткого диска. Однакопока еще эта модель под названием SL-C3000 заговоритхотя бы по-английски, а не по-японски, и доберется до на-шего рынка, пройдет очень много времени. А пока идеаль-ным КПК для системного администратора как был, так иостается Sharp Zaurus SL-C860. Кстати, с появлением трех-тысячной модели, цена на восемьсот шестидесятую долж-на упасть, что сделает Zaurus более доступными. Продол-жим же наш разговор об этом карманном компьютере, ра-ботающем под управлением ОС Linux.

В первой части статьи я уже рассказывал о существую-щем многообразии «прошивок» ROM для Zaurus. Две ос-новных из них – это pdaXrom (http://www.pdaxrom.org) иCacko ROM (http://cacko.biz/cacko). Первая в качестве гра-фической среды использует X11, а вторая, как и роднаяшарповская – Qtopia. Доставшийся мне «карманник» шелс довольно устаревшей русифицированной для «МакЦент-ра» версией Cacko ROM. Поэтому я хочу начать вторуючасть с описания процесса перепрошивки ROM, которыйвесьма не тривиален. После окончания операции по срав-нению с макцентровской версией, помимо исправленийошибок, мы должны дополнительно получить огромное чис-ло бонусов:

Наиболее заметные изменения:! переделаны все значки и обои;! значительно обновлена программа kino2 – оболочка для

mplayer;! включена поддержка NLS для всех языков в ядре;! модернизирована программа переключения клавиатур-

ных раскладок;

! включены версии баузеров Opera 7.25 и NetFront 3.1;! улучшена поддержка USB-устройств через CF USB Host;! добавлена поддержка эмуляторов SNES и Scumvm.! поддержка файловых систем ext3 (позволяет создавать

отказоустойчивые ext3 разделы на больших внешних кар-тах памяти) и squashfs (предоставляет очень хорошуюстепень сжатия данных при невысоком использованиисистемных ресурсов), fuse (FileSystem in User Space);

! обновлены драйвера bluetooth и WiFi (используютсядрайвера HostAp, поддерживаются Wireless Extentionsверсии 15, WPA);

! добавлен модуль брандмауэра iptables;! bash «дорос» до версии 3.0;! в прошивку включен Midnight Commander;! включены в прошивку unrar, diff, smbmount и другие кон-

сольные утилиты, которые иначе пришлось бы доуста-навливать вручную;

! созданы новые версии многих консольных утилит (wget,fdisk, OpenSSL/OpenSSH);

! обновлена программа эмулятора терминала;! добавлена поддержка целого ряда новых bluetooth и WiFi

CF-карт.

Как видите, список изменений весьма внушителен, длятого чтобы приступить к обновлению прошивки. Нужно ска-зать, что к этому процессу стоит отнестись со всей ответ-ственностью, так как можно легко привести КПК в нерабо-тоспособное состояние. Снимки с экрана Zaurus во времявыполнения этого увлекательного процесса вы можете най-ти по адресу www.markelov.net/z860upd.html, а далее я по-стараюсь подробно описать само действо.

Начнем с того, что на всякий случай сохраним копию те-кущей прошивки. Для этого нам необходимо попасть в такназываемое «диагностическое меню» карманного компью-тера – аналог BIOS настольных ПК. Для того чтобы зайти в

ИДЕАЛЬНЫЙ КАРМАННЫЙ КОМПЬЮТЕРДЛЯ СИСТЕМНОГО АДМИНИСТРАТОРАЧАСТЬ 2

АНДРЕЙ МАРКЕЛОВ

1 Маркелов А. Идеальный карманный компьютер для системного администратора. Часть 1. – Журнал «Системный администратор», №10,

октябрь, 2004 г.

Page 11: 025 Системный Администратор 12 2004

9№12(25), декабрь 2004

администрирование

него, необходимо на некоторое время вынуть батарею, либопросто отодвинуть на некоторое время защелку батареи.После чего возвращаем все в исходное состояние, и привключении «завра» держим нажатыми клавиши <D+M>. Пе-ред вами меню на английском языке. Я настоятельно реко-мендую не экспериментировать с его пунктами, так как мож-но легко «убить» ваш КПК. Теперь перемещаемся на третьюстраницу меню. Там выбираем пункт «NAND Flash Back Up».Перед этим необходимо убедиться, что в КПК вставлена от-форматированная в файловой системе FAT карточка. Местаже должно хватить для 135 Мб файла с полной копией ваше-го текущего содержимого NAND ROM. По окончании про-цесса на флэшке будет лежать файл systc860.dbk. Обратнов диагностическое меню можно будет вернуться по клавише«Cancel», а из самого диагностического меню выход осуще-ствляется выбором подпункта «Reset» пункта «Extra menu».При необходимости вернуться к сохраненной прошивке мож-но выполнить обратную операцию по восстановлению черезпункт «NAND Flash Restore».

Теперь приступим непосредственно к замене нашей ус-таревшей версии на новую прошивку. Это делается из спе-циального меню на японском языке. Не забудьте, что Sharpофициально не продает Zaurus за пределами Японии! По-лучить доступ в это меню можно, если после «горячего»рестарта включать КПК кнопкой «Power» с одновременнонажатой клавишей «Ок». В меню выбираем четвертый, ниж-ний пункт. После КПК спросит, с какого носителя мы будемобновлять прошивку. Три файла из архива – initrd.bin,tools.tar и updater.sh должны лежать в корне либо CF – либоSD-карты. Кроме того, убедитесь, что подключили блокпитания, иначе процесс не начнется. До этого момента онне должен был быть подключенным. Итак, выбираем вто-рой или третий пункт, и спустя некоторое время попадаемв загрузочное меню установщика.

Далее, для корректной работы новой прошивки нам не-обходимо переразбить внутреннюю flash-память КПК, вы-делив под root-раздел 28 Мб. Выбираем пятый пункт «Flashrepartition», и в ответ на вопрос вводим 28. По окончаниипереразбивки КПК предложит перезагрузиться. Заново вхо-дим в японское меню, и повторяем все действия вплоть допопадания в загрузочное меню установщика прошивки. На-конец, выбираем «Install new ROM» и ожидаем окончанияпроцесса.

После обновления ROM, вам, возможно, захочется по-пробовать собрать какую-нибудь программу на Zaurus изисходников. К сожалению, из-за относительно небольшогообъема запоминающего устройства на КПК по умолчаниюне стоят средства разработки. Тем более что все в основ-ном собирается кросс-компилятором на «большом» линук-се. Однако все-таки возможность разработки непосред-ственно на КПК есть. Для этого необходимо скачать и уста-новить «Developer image» – образ сжатой файловой систе-мы, который занимает порядка 35 Мб. В нем содержитсякомпилятор gcc, заголовочные файлы, утилиты и библио-теки для сборки утилит командной строки и Qtopia. Ска-чать его можно с http://www.zaurususergroup.com. Там женаходятся и RPM-пакеты для кросс-компилятора.

Надеюсь, статьи, посвященные замечательному карман-ному компьютеру от фирмы Sharp, не только помогли со-

ставить о нем представление тем, кто только собрался об-завестись карманной Linux-системой, но окажутся полез-ными и обладателям Zaurus. На возникшие вопросы авторс удовольствием ответит по электронной почте, либо на фо-руме журнала.

Хочу поблагодарить Антона Масловского, предоставив-шего мне предварительную версию Cacko ROM 1.22, кото-рая к моменту публикации статьи наверняка уже выйдет всвет.

Ðèñóíîê 2. Îáíîâëåííûé èíòåðôåéñ

Ðèñóíîê 1. Çàãðóæàåòñÿ îáíîâëåííàÿ âåðñèÿ Cacko ROM

Ðèñóíîê 3. Ñèñòåìíàÿ èíôîðìàöèÿ

Page 12: 025 Системный Администратор 12 2004

10

администрирование

Какие бы доводы ни приводились в вечных спорах Windowsvs Linux, но изучать компьютерные технологии, мне кажет-ся, лучше все-таки на UNIX-системах. Открытость, возмож-ность разобраться во внутреннем строении, наличие огром-ного числа удобных и свободных инструментов – все этопозволяет при желании в совершенстве освоить любую про-фессию, связанную с компьютерами. Но не всегда имеетсявозможность установить еще одну операционную систему.Сегодня пойдет речь об интересном дистрибутиве, которыйпозволяет изучить возможности GNU/Linux и, думаю, при-дется по вкусу некоторым администраторам и пользовате-лям.

Цель австралийского LiveCD дистрибутива ADIOS – Auto-mated Download and Installation of Operating Systems (http://dc.qut.edu.au/adios) – дать возможность быстро и легко заг-рузить и использовать операционную систему для лабора-торных исследований. Первоначально образ ADIOS черезвеб-сервер использовался для установки операционной си-стемы на жесткие диски компьютеров, дополнительно воз-можно было сохранять копии образов OС на запасные дис-ковые разделы, и только относительно недавно появиласьвозможность запускать с CD-ROM. Базируется дистрибу-тив на Fedora 1.0. Поэтому ADIOS присущи поддержка боль-шого количества оборудования и его автоматическое оп-ределение, реализуемое при помощи kudzu, а также все тепонятные и удобные инструменты для настройки системы.Система включает популярные графические среды – KDE,GNOME и IceWM, так что первое знакомство с Linux прой-дет в благоприятной обстановке. Ядро 2.4.24 собрано с под-держкой loopback squashfs (http://squashfs.sourceforge.net),файловой системы, использующей zlib для уменьшения раз-мера, в результате в дистрибутив поместилось больше чем2 Гб приложений. В составе имеются ядра, поддерживают-ся защищенные режимы – LIDS (Linux Intrusion DetectionSystem), SELinux (NSA Security Enhanced Linux), в будущемпланируется добавить Grsecurity или RSBAC. И кроме тогоподдерживается UML (User Mode Linux), при помощи кото-рого возможно разбить одиночную систему на нескольконезависимых виртуальных машин, общающихся между со-бой через виртуальные Ethernet-интерфейсы. Поэтому поль-зователи, желающие изучить на досуге эти технологии,получают готовый и уже настроенный инструмент. Систем-ные требования невысоки, поддерживаются все процессо-ры от 486 до Pentium 4 и минимально рекомендуемый объемОЗУ – 64 Мб.

Работа с дистрибутивомADIOS в первую очередь LiveCD, и для удобства пользова-телей в дистрибутиве заложены широкие возможности посохранению части данных на разделах жесткого диска (DOSFAT или Linux EXT2/3), флоппи-диске или USB-устройствах.При каждом запуске система сканирует разделы жесткогодиска и, если находит готовый swap-раздел, предлагает под-

ключить его. При появлении приглашения boot: возможновыбрать несколько вариантов загрузки. При нажатии на Enter(или ввести linux) загружается обычное ядро, если набратьlids, загрузится ядро с поддержкой этого режима, возможныеще варианты: 11 (переход сразу к 11 пункту см. ниже), 4 (к4 пункту), s4 (4 пункт с поддержкой LIDS), lock (пункт lock).

Далее перед пользователем появляется меню:

Как видите, выбор большой. Возможно запустить ADIOSтолько с CD-ROM, примонтировать раздел /var с других ис-точников либо установить его на жесткий диск и запускатьв дальнейшем оттуда, изменить уровень запуска системы(по умолчанию 5). Но это еще не все пункты, если выбрать«g» – guru, то их количество удвоится (появятся и опции 11и lock). Отсюда при необходимости можно прямо из менюсоздать/удалить swap-раздел или swap-файл (только на FATили ext2/3). Установку на жесткий диск система может вы-полнить автоматически, в том числе и переразбить разде-лы (как FAT, так и NTFS). Эта несколько рискованная опе-рация может быть выполнена и вручную при помощи ути-литы ntfsresize. За подробностями работы которой обращай-тесь к документации дистрибутива или к моей статье «Linuxи NTFS» (журнал «Системный администратор», №8, август2004 г.). В системе заведены четыре пользователя: root,super (Alternate Administrator), cso (Chief Security Officer) иadios. Первые два представляют собой администраторов,причем в графическом режиме root система не позволитзарегистрироваться, только super, cso необходим для ра-боты с SELinux и adios предназначен для повседневной ра-боты. Пароль у всех этих пользователей один – 12qwaszx(легко запомнить по две клавиши слева в каждом ряду),поэтому рекомендуется сразу же его сменить. Все найден-ные разделы система монтирует в режиме «только чтение»,при необходимости записи перемонтируйте их с опцией –oremount,rw. Дистрибутивы, основанные на RedHat, всегдаотличались большим списком поддерживаемого оборудо-вания, поэтому в большинстве для выхода в сеть остаетсявыставить только нужные параметры. Те, кто не знаком сработой консольных утилит вроде /sbin/ifconfig, найдут боль-шое количество графических front-end для настройки сети,например internet-druid (рис. 1).

Программное обеспечение на диске содержит коллекциюутилит управления и сетевого администрирования. Здесьвсе: веб-сервер Apache; прокси-сервер Squid; FreeS/WANIPSec для создания VPN; маршрутизатор zebra; пакет Samba,

ДИСТРИБУТИВ ДЛЯ ВСЕХДИСТРИБУТИВ ДЛЯ ВСЕХСЕРГЕЙ ЯРЕМЧУК

1) Run Linux from CD-ROM with /var in RAM only

2) Run Linux from CD-ROM with /var on FAT/EXT2 disk

3) Run Linux from FAT/EXT2 disk (incorporates Option 2)

4) Run Linux from CD-ROM with /var on USB storage

5) Install ADIOS repartition disk and create EXT3 filesystem

9) Create Swap file on FAT/EXT2 disk

x) Remove hardware and X windows configuration information

r) Change run-level (default 5 for X windows)

i) Display Copyright, License and System Information

h) Display Help

g) Display the 'guru' menu options

Page 13: 025 Системный Администратор 12 2004

11№12(25), декабрь 2004

администрирование

который позволит работать в сетях Windows; сервер аутен-тификации openldap; сетевая система обнаружения атакSnort c ACID; сканеры Nessus и Nmap; снифферы tcpdumpи ethereal позволят проанализировать сетевые пакеты; фай-рвол iptables с графическим интерфейсом firestarter;traceroute и графический xtraceroute позволят выяснить путьк интересующему узлу, и еще много сетевых утилит, тра-диционно входящих в состав любой UNIX-системы. Имеют-ся утилиты для работы в беспроводных сетях.

Если набрать в строке веб-браузера IP-адрес своего ком-пьютера, то обнаружится еще одна положительная сторо-на ADIOS – ARK (Administrators Resource Kit) (рис .2), со-держащий большое количество различной документациии коллекцию ссылок по Linux/UNIX вообще, настройке от-дельных сервисов, защите, языкам программирования, ко-торые придутся по душе новичкам. Отсюда же можно полу-чить доступ к man-страницам дистрибутива.

Для удобства администрирования системы в комплектвходит webmin, для его запуска достаточно ввести /sbin/service webmin start и затем набрать в строке браузера http://localhost:10000, после чего использовать для входа пользо-вателя root. Этот сервис может оказаться полезным еще ипотому, что дистрибутив практически не содержит данных,необходимых для локализаций, отличных от английской, итолько webmin можно заставить общаться на русском.

Для работы с данными, содержащимися на жестких дис-ках, в том числе для их восстановления и исследований по-следствий взлома в комплекте имеется Sleuthkit file system

analysis tools (http://www.sleuthkit.org/sleuthkit). О возможно-стях утилит, входящих в его комплект, уже писалось на стра-ницах журнала. Для наглядности работы этих утилит раз-работчиками также установлен Autopsy Forensic Browser(http://www.sleuthkit.org/autopsy), позволяющий использоватьдля вывода результатов веб-интерфейс. Для этого доста-точно набрать в консоли autopsy & и вставить появившую-ся строку в браузер.

Далее Squirrelmail Webmail также дает возможность ис-пользовать браузер для работы, в данном случае это по-чта. Для его использования достаточно разрешить запусксервиса IMAP в /etc/xinetd.d/imap (disable = no) и запуститьxinetd, который по умолчанию не работает.

И затем sendmail.

Проверяем, работает ли веб-сервер /sbin/service httpdstatus (для проверки всех запущеных /sbin/service --status-all).Если все работает, набираем http://localhost/webmail.

В комплект программ также включен Swish-e (http://swish-e.org), позволяющий легко создать небольшой, но эф-фективный поиск по сайту. При этом поиск по документам,имеющимся на ADIOS CD, уже настроен. В любом другомслучае это просто организовать самому. Настраиваем пара-метры поиска в /etc/swish.conf, затем индексируем файлы.

И в html-код страницы вставляем что-то вроде:

для возможности поиска документов из браузера.Также в дистрибутиве имеются сервер переадресации

rinetd и утилита контроля Nagios. Плюс принятые в боль-шинстве UNIX утилиты для программирования в bash, nasm,C, C++, Perl, Python, PHP и Ruby со средствами отладки. Аеще офисные программы, утилиты для работы с мультиме-диа, графикой, игры. Так что комплект на все случаи жиз-ни. Работа с поддержкой SELinux возможна только послеустановки ADIOS на жесткий диск.

Для тех, кто хочет создать свой собственный LiveCD,проект представляет набор скриптов ADIOS development kit(ADK), работа с которыми хорошо описана в документации.

Изучение UNIX-систем никогда не было легким, требу-ется затратить некоторые усилия и проявить терпение,прежде чем появится первый результат. ADIOS представ-ляет собой хороший инструмент, который поможет сделатьэти первые шаги. Кроме того, это неплохой инструмент длядемонстрации возможностей GNU/Linux, при организациивсевозможных курсов, особенно когда используется обо-рудование, задействованное в других задачах. И, конечноже, его можно использовать при решении задач админист-рирования, когда нет под рукой других инструментов, по-зволяющих решить вдруг возникшие проблемы.

Ðèñóíîê 1

Ðèñóíîê 2

# /sbin/service xinetd start

# /sbin/service sendmail start

#cd /var/www/swish#swish-e -c /etc/swish.conf -f index.swish

<form action=�/cgi-bin/search.cgi� target=�main�>

Page 14: 025 Системный Администратор 12 2004

12

администрирование

Постановка задачиПредположим, имеется некоторое количество компьютеровпод управлением операционной системы UNIX (Windows) сзапущенным SSH-сервером, на которых автоматически порасписанию в некоторое время стартует программа, созда-ющая резервные копии некоторых каталогов (например,/etc, /usr/local/etc) и складывающая их в определенное мес-то. Пример такого скрипта, адаптированного под системуperiodic во FreeBSD, можно скачать с http://www.granch.ru/~shelton/fileZ/130.backup-dirs. Все используемые парамет-ры описаны в начале скрипта. Для обеспечения сохраннос-ти данных архивов было бы неплохо копировать их все водну точку, откуда их можно было бы перенести на съем-ный носитель, например. Копирование должно проводить-ся в автоматическим режиме, все имена каталогов – бытьуникальными, требовать минимум настроек и обеспечиватьмаксимум безопасности при передаче данных по сети (если,например, архив /etc попадет в чужие руки, можно полу-чить столько проблем, что мало не покажется). С этой це-лью был разработан скрипт копирования файлов черезSCP2 (программу безопасного копирования, входящую вкомплект SSH2) без ввода паролей, используя авториза-цию с помощью публичных ключей. Скрипт выполняет ко-пирование файлов, размещенных в некотором, заранееобусловленном каталоге, отмечает каждое действие в соб-ственном файле журнала. В статье скрипт будет приводить-ся по частям (которые, будучи объединены вместе, тем неменее дадут полноценный скрипт), полный текст скриптаможно загрузить с http://www.granch.ru/~shelton/fileZ/safecopy.

Для разработки скрипта, отладки и применения исполь-зовался компьютер с операционной системой FreeBSD 4.10-STABLE и SSH2 от SSH Communications Inc., установлен-ный из портов (/usr/ports/security/ssh2). Скрипт имеет неко-торые адаптационные возможности для работы с OpenSSH,но работоспособность этих возможностей не проверяласьи может содержать ошибки. Для работы скрипта использо-валось имя пользователя rmbackup.

Настройка SSHSSH – это протокол связи двух компьютеров через TCP/IPc шифрованием передаваемых данных. Этот протокол обес-печивает надежный и безопасный доступ к удаленному ком-пьютеру, расположенному... да неважно где, лишь бы у негобыл выход в Интернет. С точки зрения рядового системно-го администратора SSH обычно рассматривается как бе-зопасное средство удаленного управления сервером, длячего ранее использовалась программа telnet. Конечно, естьи другие средства шифровки трафика, но их мы рассмат-ривать не будем.

Разумеется, шифрование сессии во время работы поSSH выполняется, но возможности SSH не исчерпываютсятолько этим. Я не буду приводить здесь описание всех воз-можностей SSH, это тема для отдельной статьи, всех инте-ресующихся отсылаю к документации на SSH2 (http://www.ssh.fi/support/documentation/online/ssh/adminguide/32).

Одной из возможностей SSH является то, что он можетвыполнять авторизацию пользователей и организовыватьудаленное выполнение команд в SSH-сессии без ввода па-роля, с помощью так называемого публичного ключа. Этавозможность основана на стандартном методе авториза-ции с помощью асимметричных ключей – приватного и пуб-личного.

Приватный ключ доступен только пользователю и тща-тельно им оберегается от хищения, публичный же ключ, на-оборот, размещается во всех местах, где только можно егоразместить. На мой взгляд, наиболее удачное описаниетого, как работает SSH и как его использовать (не считая,конечно, man ssh2, man ssh.conf и прочих манов) – это кни-га «SSH, the Secure Shell: Definitive Guide» [1].

После того как принято решение о включении данногокомпьютера в автоматическое копирование файлов, но пе-ред тем как начинать собственно копирование, необходи-мо выполнить следующие шаги по настройке SSH:

1. Создаем пользователя, от имени которого будет вы-полняться копирование файлов. Пользователь может не

РАШИД АЧИЛОВ

КОПИРОВАНИЕ ФАЙЛОВВ АВТОМАТИЧЕСКОМ РЕЖИМЕС МНОЖЕСТВА КОМПЬЮТЕРОВЧЕРЕЗ SSH

Page 15: 025 Системный Администратор 12 2004

13№12(25), декабрь 2004

администрирование

иметь пароля («*» в поле пароля в /etc/master.passwd), нодолжен иметь действительный shell, поскольку он (shell)будет выполнять некоторые команды. Пользователь долженбыть создан на всех компьютерах, с которых будут копиро-ваться файлы, и на всех компьютерах иметь одинаковыенастройки и имя. Это не обязательно с точки зрения SSH,но необходимо для скрипта, поскольку тот использует однофиксированное имя пользователя. Интерактивной работына компьютерах, с которых будут копироваться данные,никогда не будет, поэтому /bin/sh будет вполне достаточно.На компьютере, на котором будет выполняться скрипт (на-зовем его «мастер») установите любой привычный shell.

2. Создаем ключевую пару для данного пользователяна данном компьютере. Для этого используется программаssh-keygen2. Порядок создания ключей не важен, следуеттолько помнить, что мастер-компьютер обращается ко всемкомпьютерам, с которых копируются данные, а к самомумастер-компьютеру не обращается никто. Поскольку пред-полагается автоматическая работа, то создается ключеваяпара, не защищенная паролем. Пример создания ключе-вой пары приведен ниже:

Опускать -P здесь нельзя – опция указывает на необхо-димость создания ключа, не защищенного паролем. Послесоздания ключевой пары появляются файлы id_dsa_2048_a(приватный ключ) и id_dsa_2048_a.pub (публичный ключ).Подробную информацию о создании ключевой пары см. manssh-keygen2. Публичный ключ мастер-компьютера, пере-именованный, например, в rmbackup_master.pub, нужно по-местить в подкаталог .ssh2 домашнего каталога пользова-теля rmbackup на всех компьютерах, с которых будут копи-роваться файлы.

3. Настраиваем конфигурационные файлы идентифи-кации и авторизации. Эти файлы определяют имя файла(файлов – в SSH2 их может быть несколько) приватногоключа (ключей) и имена файлов, задающие ключи, автори-зация с которыми разрешена на данном компьютере дляданного пользователя. По умолчанию имена этих файловidentification и authorization. На мастер-компьютере файлauthorization можно не создавать – на него никто не будетзаходить данным пользователем. На компьютерах, с кото-рых будут копироваться данные, файл authorization обяза-тельно должен содержать имя файла ключа мастер-компь-ютера. Примеры файлов:

Следует иметь в виду, что если планируется заходить снескольких компьютеров, ключ каждого компьютера дол-жен быть помещен в подкаталог .ssh2 данного компьютераи описан в файле authorization. Более подробная информа-ция о настройке авторизации по публичному ключу приве-дена в man ssh.conf и man sshd.conf.

4. В первый раз заходим с мастер-компьютера на ком-пьютер, с которого будут копироваться файлы в интерак-

тивном режиме. Это необходимо для создания хост-клю-чей в подкаталоге hostkeys каталога .ssh2. Хост-ключи иден-тифицируют SSH-сервер в целом. При отсутствии хост-клю-ча в подкаталоге hostkeys перед началом сессии мастер иудаленный компьютер обмениваются хост-ключами, и хост-ключ удаленного компьютера помещается в подкаталогhostkeys для пользователя rmbackup. При этом на консолипоявляется следующий запрос:

Проверка того, что авторизация настроена правильно,очень проста – набираете команду ssh remote на мастер-компьютере, где remote – имя или адрес удаленного компь-ютера. Удаленная SSH-сессия должна начаться сразу же,без дополнительных запросов пароля. Если появится зап-рос пароля на разблокировку ключа:

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

Если же появляется стандартный запрос пароля:

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

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

Что это такое? Это отдельная настройка SSH-сервера,при которой он передает клиенту информацию о том, чтодомашний каталог пользователя – это корень файловойсистемы. Естественно, выше корня двигаться невозможно.Технология изоляции критичных системных сервисов в «пе-сочницы» (sandboxes) применяется уже достаточно давнои успешно. Правда тут есть одно «но» – нам понадобитсяобеспечить работоспособность сервера в данном окруже-нии. Поскольку абсолютно все, что находилось выше до-машнего каталога в режиме chroot, недоступно, следует со-здать собственную иерархию каталогов со всем необходи-мым. Правда, этого необходимого крайне мало. В домаш-

>ssh-keygen2 -P

identification:IdKey id_dsa_2048_aauthorization:Key rmbackup_master.pub

>ssh mybox

Host key not found from database.

Key fingerprint:

xocob-bicub-vatun-mofos-nutym-parok-sahet-hefer-papuh-kepyz-rexox

You can get a public key's fingerprint by running

% ssh-keygen -F publickey.pub

on the keyfile.

Are you sure you want to continue connecting (yes/no)? yes

Host key saved to /usr/home/rmbackup/.ssh2/hostkeys/key_22_mybox.pub

host key for mybox, accepted by rmbackup Wed Nov 03 2004 23:44:10 +0600

>ssh mybox

Passphrase for key "/usr/home/rmbackup/.ssh2/id_dsa_2048_a"

with comment "2048-bit dsa, [email protected],

Fri Jul 23 2004 12:50:25 +0700":

>ssh mybox

rmbackup's password:

Page 16: 025 Системный Администратор 12 2004

14

администрирование

нем каталоге пользователя rmbackup на удаленном компь-ютере следует создать каталоги /bin и /etc. В каталог /binпоместить файлы (переписать из стандартного /bin) ls, sh и(ВНИМАНИЕ!) исполняемый файл sftp-server, собранныйтаким образом, что у него отсутствуют динамические ссыл-ки на библиотеки. Такой режим обычно применяется дляпрограмм, используемых в процессе восстановления сис-темы. Исполняемый файл sftp-сервера должен быть обяза-тельно собран с отключением динамических библиотек,иначе придется дублировать всю структуру динамическойзагрузки – /usr/libexec/ld-elf.so, /var/run/ld-so.hints и все ос-тальное. Исполняемый файл такого типа можно получить,дописав в каталоге, где лежат исходные тексты ssh, в под-каталоге apps/ssh в файл Makefile в строчку 273 (или околотого) LDADD=<флаги> флаг -static и пересобрать SSH. Какпроверить, является ли полученный исполняемый файл ста-тически или динамически собранным?

Приведенный выше ответ является правильным, есливместо него появляется что-то типа:

значит, это динамически собранный исполняемый файл, ион не годится. На самом деле его тоже можно использо-вать. Но для этого придется создать /usr/libexec в домаш-нем каталоге пользователя rmbackup, перенести туда ls-elf.so, создать /usr/lib и поместить туда все библиотеки, пе-речисленные в выводе ldd, создать /var/run/ld-so.hints ко-мандой ldconfig. С моей точки зрения, пересобрать програм-му значительно проще.

В каталог /etc помещаются файлы group и master.passwd.Из файла group удаляются все реальные пользовательс-кие группы, важно, чтобы там присутствовала группа, про-писанная как ChrootGroup в конфигурационном файле SSH-сервера. Из файла master.passwd удаляются все пользова-тели с паролями, пароль root заменяется на «*». После чегосоздаются файлы passwd, pwd.db и spwd.db командой:

Теперь файл master.passwd можно стереть. Кроме того,в конфигурационном файле SSH-сервера указывается груп-па, к членам которой будет применяться chroot (по умолча-нию это группа sftp):

Кроме того, проследите, чтобы параметр AllowedAuthen-tications содержал publickey, а RequiredAuthentications несодержал password. Еще лучше, чтобы он был удален илизакомментирован. Как убедиться в том, что сессия идет вchroot? В файле регистрационного журнала SSH-сервераоб этом делается специальная отметка:

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

Настройка скриптаНастройка скрипта выполняется через задание перемен-ных в конфигурационном файле /etc/periodic.conf. Эти пе-ременные используются скриптом резервного копирования,упомянутым в начале статьи, и скриптом, описываемым вданной статье.

Скрипт использует следующие переменные:

Это соответственно переменные, задающие пользова-теля, группу, режим доступа к файлам и каталогам, созда-ваемым скриптами. Скрипт не устанавливает значения пе-ременных по умолчанию, поэтому все переменные должныбыть заданы в /etc/periodic.conf или /etc/defaults/periodic.conf.

Заголовок и вспомогательные функции

В приведенном выше заголовке нет ничего необычно-го. Переустановка переменной PATH нужна для того, что-бы находить программу SSH2, даже если пользователь ееизменил.

Функция записи информации в регистрационный жур-нал, который ведется программой, имитирует работу про-граммы logger и формирует в журнале записи такого фор-мата:

при этом выводимая в журнал строка передается в пере-менной logline.

> ldd sftp-server2

Ldd: sftp-server2: not a dynamic executable

> ldd sftp-server2:

libm.so.2 => /usr/lib/libm.so.2 (0x280bb000)

libcrypt.so.2 => /usr/lib/libcrypt.so.2 (0x280d7000)

libutil.so.3 => /usr/lib/libutil.so.3 (0x280f0000)

libncurses.so.5 => /usr/lib/libncurses.so.5 (0x280f9000)

libc.so.4 => /usr/lib/libc.so.4 (0x2813b000)

>pwd_mkdb -p -d . master.passwd

ChRootGroups sftp,guest

daily_backup_owner="rmbackup" # Owner of backup filesdaily_backup_group=�wheel� # Group of backup filesdaily_backup_mode="0600" # Mode of backup filesdaily_backup_dirmode="0700" # Mode of intermediate dirs

#!/bin/sh# Safe updating, so � copying current daily backup directory# from remote server to local. Used SSH2 publickey auth# method, so you need a working installation before starting.# This is an open-source software, licenced by BSD license.# Written by CityCat 23.07.2004# $Id: safecopy,v 1.5 2004/08/10 04:26:40 shelton Exp $PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin: ↵↵↵↵↵

/usr/local/sbin

# Logging function# Logged string in variable logline!safe_logger(){ logdate=`date +"%d/%m/%Y %T"` echo "$logdate [$$] safering: $logline" >> $logfile}

07/08/2004 05:00:02 [70241] safering: File _etc.tar.bz2 from host mybox

was succesfully transferred

connection from "192.168.1.1"

Public key /usr/local/share/rmbackup/.ssh2/rmbackup_mybox.pub used.

Public key authentication for user rmbackup accepted.

User rmbackup, coming from mybox, authenticated.

User 'rmbackup' will be chrooted to directory '/usr/local/share/rmbackup'.

Now running on rmbackup's privileges.

Page 17: 025 Системный Администратор 12 2004

15№12(25), декабрь 2004

администрирование

Функция перехода в подкаталог, задаваемый перемен-ной godown. Если каталог отсутствует, он будет создан, иему будут установлены права доступа, заданные в конфи-гурационном файле.

Загрузка значению по умолчанию для скрипта, если онизаданы (обычно вписываются в /etc/defaults/periodic.conf).

ПеременныеЕдинственная переменная, которую имеет смысл настра-ивать в скрипте, вынесена перед строкой предупрежде-ния. Разумеется, все остальные переменные тоже можноменять – это же скрипт. Но все же делать это не рекомен-дуется без понимания механизма его работы.

Итак:! Переменная sysdir указывает корневой каталог систе-

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

! Переменная backupdir указывает на каталог с резерв-ными копиями на удаленном компьютере.

! Переменная ringdir указывает на каталог с резервнымикопиями на мастер-компьютере.

! Переменная maintdir указывает на каталог с регистра-ционным журналом, списком компьютеров, с которыхбудут копироваться данные, и собственно скриптом.

! Переменные hostlist и logfile задают соответственно име-на файлов списка компьютеров и регистрационногожурнала.

! Переменные wsyear, wsmon и wsday хранят текущие год,месяц, день.

! Переменная openssh указывает на то, что SSH, обнару-женный скриптом, является OpenSSH (используется дляадаптации путей и работы с конфигурационными фай-лами).

! Переменная sshconf указывает на расположение конфи-гурационного файла SSH по умолчанию.

! Переменная sshome указывает на пользовательский ка-талог с настройками, ключами и т. д. для SSH (именакаталогов отличаются в SSH2 и OpenSSH).

! Переменная scpname задает имя программы безопас-ного копирования SCP (в SSH2 и OpenSSH они отлича-ются).

Проверка командной строкии обнаружение SSH

Допустимыми параметрами командной строки являют-ся -h или имя файла со списком компьютеров, с которыхпроизводится копирование. Если имя файла не задано,будет использоваться файл cphosts в каталоге $maintdir.

Первым делом ищется программа ssh2 (which ssh2).Если она найдена, то выбирается информация о версии (пе-

# If there is a global system configuration file, suck it in.#if [ -r /etc/defaults/periodic.conf ]; then . /etc/defaults/periodic.conf source_periodic_confsfi

# Variables# There is only maintained variables!# This is a root folder for all subordinated folderssysdir="/usr/local/share/rmbackup"# NO CHANGES BEHIND THIS LINE!! YOU HAVE BEEN WARNED!!backupdir="backup"ringdir="$sysdir/backup"maintdir="$ringdir/maint"hostlist="$maintdir/cphosts"logfile="$maintdir/saferlog"wsyear=`date +"%Y"`wsmon=`date +"%m"`wsday=`date +"%d"`# We assumed SSH2 by SSH Com. presence and locating config# in /usr/local/etc/ssh2openssh=0sshconf="/usr/local/etc/ssh2/ssh2_config"sshome="$HOME/.ssh2"scpname=scp2

# Check commandlineif [ $# -ne 0 ]; then if [ $1 = "-h" ]; then echo "Safering updater. Copying current daily ↵↵↵↵↵

backup dir from remote server." echo " Usage: safecopy [hostlist-location-and-name]." exit else hostlist=$1 fifi# Check on presence SSH in system and detect their versionwssh=`which ssh2'`if [ -z $wssh ]; then wssh=`which ssh'` if [ -z $wssh ]; then logline="No any SSH program was detected, ↵↵↵↵↵

install it first"; safe_logger exit else wsver=`$wssh | awk '{printf "%s %s %s",$1,$2,$3}'` sshome="$HOME/.ssh" scpname=scp wsx=`$wssh | awk '{print $3}'` if [ $wsx = "SSH" ]; then openssh=1 sshconf="/etc/ssh/ssh_config" else logline="Broken SSH1 from SSH ↵↵↵↵↵

Communicationc Inc. probably detected" safe_logger exit fi fi else wsver=`$wssh -V 2>&1 | awk '{printf "%s %s ↵↵↵↵↵

%s %s",$2,$3,$4,$5}'`fi# Log detected versionlogline="Detected version: $wsver"; safe_logger

# Go down function# Set variable godown to downing directory namego_down(){ if [ ! -e $godown ]; then mkdir $godown chown $daily_backup_owner:$daily_backup_group $godown chmod $daily_backup_dirmode $godown fi cd $godown}

Page 18: 025 Системный Администратор 12 2004

16

администрирование

ременная wsver будет содержать «SSH Secure Shell x.x.x.x»,где x.x.x.x – номер версии SSH), и полученная информациявыводится в регистрационный журнал. Если же она не най-дена, производится попытка обнаружить программу ssh(which ssh), и если она найдена, проверяется, что за про-грамма обнаружена. Если это OpenSSH (определяется похарактерному признаку – третье слово при запуске без па-раметров содержит «SSH»), то переменные sshome, scpname,sshconf и openssh устанавливаются в соответствующие зна-чения. Иначе скрипт завершает работу, поскольку работа сSSH1 от SSH Communications не поддерживается (по при-чине его небезопасности).

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

Скрипт проверяет наличие параметра IdentityFile в кон-фигурационном файле сервера (даже если он отмечен зна-ком комментария). Для OpenSSH дополнительно отбрасы-вается путь к IdentityFile, если он там указан. Потом прове-ряется существование файла, описанного как IdentityFile.Если он не существует, скрипт прекращает работу.

Разбор списка компьютеров осуществляется установ-кой переменной IFS в значение «\n». Для этого не нужнописать «IFS=”\n”» – shell не интерпретирует метасимволы.Следует написать «IFS=”», нажать «перевод строки» и зак-рыть кавычку – внутри кавычек окажется символ переводастроки. После считывания файла организовывается стан-дартный цикл по списку переменных-строк:

Разбор строки и получение спискафайлов для копирования

Один из двух наиболее важных моментов. Скрипт копи-рования файлов создает каталоги вида YYYY/MM-YYYY/DD-MM-YYYY, где YYYY – текущий год, MM – текущий месяц,DD – текущий день. Можно было бы, конечно, создаватьпапки типа YYYY/MM/DD, но мне удобнее просматриватьсписок в mc, когда видна полная дата. В переменной wlsпосле выполнения команды будет результат команды «пе-рейти в заданный каталог и получить список файлов в нем».Если предполагается копировать нечто другое, следует за-дать соответствующий путь в переменной fullpath.

Если команда завершилась аварийно, то список будетпуст, и скрипт перейдет к другому узлу из списка или завер-шит работу, если этот список уже кончился. Результат вы-полнения последней команды хранится в переменной status.Если команда выполнена успешно, то выполняется после-довательный переход в каталоги: имя удаленного компью-тера, YYYY, MM-YYYY, DD-MM-YYYY, например: cd myhost;cd 2004; cd 12-2004; cd 15-12-2004. Если такой каталог от-сутствует, он создается с правами, заданными параметра-ми. Мы говорили об этом в разделе «Настройка скрипта».

Пофайловое копирование

# Taking identity file name, drop down comment fieldidentity=`grep IdentityFile $sshconf`idfirst=`echo $identity | awk '{print $1}'`if [ $idfirst = "#" ]; then idfile=`echo $identity | awk '{print $3}'` else idfile=`echo $identity | awk '{print $2}'`fi# For OpenSSH drop down path from pathnameif [ $openssh -eq 1 ]; then idname=${idfile##*/} else idname=$idfilefi# Check on existance identification file. When doesn't �# SSH dodn't setup to work with publickey auth methodif [ ! -e $sshome/$idname ]; then logline="Publickey auth method did not configured ↵↵↵↵↵

yet"; safe_logger exitfi

# Taking hosts listIFS=""hosts=`cat $hostlist`cd $ringdir# Doing safering updatefor host in $hosts do

# Parse host line hostname=`echo $host | awk '{print $1}'` hostadr=`echo $host | awk '{print $2}'` fullpath=$backupdir/$wsyear/$wsmon-$wsyear/ ↵↵↵↵↵

$wsday-$wsmon-$wsyear# Take list of files to backup wls=`$wssh -o "BatchMode yes" -q $hostadr ↵↵↵↵↵

"cd $fullpath 2> null && /bin/ls -1"`

# When list is empty, do nothing# (and don't create directories) status=$? if [ $status -ne 0 ]; then continue else# Go down the ladder godown=$hostname; go_down godown=$wsyear; go_down godown=$wsmon-$wsyear; go_down godown=$wsday-$wsmon-$wsyear; go_down fi

for file in $wls do $scpname -q -Q $hostadr:$fullpath/$file . 2> null status=$?# Check on operation return code if [ $status -ne 0 ]; then logline="Transfer of file $file unsuccesful, ↵↵↵↵↵

return code is $status"; safe_logger else logline="File $file from host $hostname ↵↵↵↵↵

was succesfully transferred"; safe_logger chown $daily_backup_owner:$daily_backup_group $file chmod $daily_backup_mode $file fi done# Return to top cd $ringdir done

Page 19: 025 Системный Администратор 12 2004

17№12(25), декабрь 2004

администрирование

Последнее и самое важное действие скрипта – пооче-редное копирование файлов из списка, полученного на пре-дыдущем шаге. Выполняется команда scp, и результат ееработы заносится в переменную status. В зависимости отзначения переменной status выдается сообщение либо обуспешном завершении копирования (при этом устанавли-ваются права и режим доступа, соответствующие парамет-рам, перечисленным в пункте «Настройка скрипта»), либооб аварийном завершении (и тогда в журнал заносится кодошибки, расшифровку которого можно посмотреть в manssh2).

Возможные ошибкии изменения скриптаЕсли скрипт работает не так, как ожидается, то, скорее все-го, имеет место ошибка в настройке SSH (по крайней мере,почти все ошибки, с которыми я сталкивался после завер-шения его разработки, были такого плана). Это очень про-сто проверить – достаточно с консоли мастер-компьютеранабрать ssh remotebox, где remotebox – имя любого компь-ютера, с которого должны копироваться данные. Если сра-зу же открывается терминал удаленного компьютера – всенормально (при этом motd показываться не должно). Еслиже появляется запрос пароля на разблокирование ключа,запрос пароля на регистрацию на удаленном компьютереили какие-либо сообщения об ошибках – следует устранитьошибки и повторить.

Единственной ошибкой, которую можно совершить пригенерации ключа, является запуск ssh-keygen2 без ключа-P. При этом при генерации ключа будет запрошен пароль.Если при генерации ключа появился запрос пароля, лучшегенерацию прервать и запустить ssh-keygen2 заново с клю-чом -P.

Самой распространенной ошибкой авторизации явля-ется то, что ключ мастер-компьютера не помещен в ката-лог .ssh2 пользователя rmbackup удаленного компьютера,не описан в файле authorization, или в имени ключа допу-щена банальная опечатка. Если ключ для пользователяrmbackup создавался через su rmbackup от пользователяroot, возможно, установлены неверные права на файлыidentification и authorization (при создании файлов владель-цем становится создатель). Второй распространеннойошибкой является задание параметра RequiredAuthenticationpassword в конфигурационном файле sshd.conf на удален-ном компьютере, требующего обязательной аутентифика-ции по паролю.

Если терминальная сессия на удаленном компьютереоткрывается нормально, то следует попробовать вручнуюввести команду (вместо 192.168.1.1 подставить IP или имякомпьютера, с которого должны быть получены файлы):

Если в результате выполнения этой команды получа-ется оглавление каталога /etc (в chroot это файлы group,passwd, pwd.db и spwd.db) – значит, следует проверить ра-боту scp. Иначе следует проверить файл журнала, в кото-рый выводятся сообщения от SSH-сервера на удаленном

компьютере на предмет сообщений об ошибках и устра-нить их.

Если предыдущая команда завершена успешно, следу-ет проверить работу команды scp следующим образом (за-менить 192.168.1.1 на IP-адрес или имя компьютера, с ко-торого должны быть получены файлы. Файл .profile долженсуществовать на удаленном компьютере):

(Внимание! Точка – элемент команды!)Если в текущем каталоге появился файл .profile-tmp,

следует уточнить код ошибки по руководству к ssh2 (manssh2) и устранить ошибки. Если же нет – проверить файлжурнала, в который выводятся сообщения от SSH-серверана удаленном компьютере на предмет сообщений об ошиб-ках, и устранить их. Здесь наиболее частой ошибкой мо-жет быть неверный sftp-server2, который не собран в соот-ветствии с рекомендациями раздела «Дополнительные воп-росы безопасности», а просто переписан и для работы тре-бует наличия динамического загрузчика, libc и пр.

Как можно изменить место, откуда берутся копируемыефайлы на удаленном компьютере? Для этого достаточноизменить формирование переменной fullpath, описанной вразделе «Разбор строки и получение файлов для копиро-вания».

Как можно изменить место и организацию каталогов, вкоторые раскладываются файлы на мастер-компьютере? Дляэтого в функцию go_down передается значение переменнойgodown – каталог будет создан по ее содержимому. Можновообще все складывать в один каталог – для этого нужнозакомментировать строки с «godown=...; go_down».

ЗаключениеДанный скрипт – инструмент системного администратораиз разряда «настроил и забыл». После его настройки он нетребует какого-либо сопровождения, кроме, пожалуй, ре-гулярного резервного копирования каталога с файлами,скопированными с удаленных компьютеров. Ну и, конечно,обеспечения необходимых мер безопасности по отношениюк каталогу, в котором хранятся резервные копии. Разуме-ется, он разрабатывался для решения определенной част-ной задачи, но его нетрудно адаптировать для копирова-ния чего угодно откуда угодно. Ошибки в самом скриптеисключены ввиду его достаточной простоты, как правило,все ошибки связаны с ошибками самого SSH.

Дополнительная информация:1. Daniel J. Barrett, Richard Silverman. SSH, the Secure Shell:

Definitive Guide. O’Reilly & Associates, 2001, 558 pages.ISBN: 0-596-00011-1.

2. http://www.ssh.fi/support/documentation/online/ssh/adminguide/32 – SSH Secure Shell for Servers Version 3.2Administrator’s Guide.

3. http://www.opennet.ru/docs/RUS/ssh_faq – Faq по SSH врусской редакции. Русская редакция: Андрей Лаврен-тьев ([email protected]).

4. man ssh2, man sshd2, man ssh.conf, man sshd.conf, manssh-keygen2.

>su rmbackup>ssh2 -o "BatchMode yes" -q 192.168.1.1 "cd /etc && ↵↵↵↵↵

/bin/ls -1"

scp2 192.168.1.1:.profile ./profile-tmp

Page 20: 025 Системный Администратор 12 2004

18

администрирование

В данной статье речь пойдет о том, как управлять единойучетной записью пользователя посредством MS ActiveDirectory вне зависимости от того, на какой платформе онработает, будь то Windows или UNIX-подобные системы. За-бегая вперед, скажу, что если с Windows-клиентами все ясно,то интеграция с каталогом от Microsoft тем способом, кото-рый будет здесь описан, подходит не для всех UNIX-подоб-ных операционных систем. Так уж сложилось – все они раз-ные, да и Active Directory вовсе не идеальная среда для ин-теграции разнородных систем. Тогда зачем я все это пишу?

А за тем, что очень многие организации изначально ориен-тированы на платформу Windows и в качестве каталога при-меняют Active Directory, а когда в сети начинает появлятьсяUNIX, то встает вопрос об интеграции, и не всегда хорошиекоммерческие решения подходят, либо из-за стоимости, либов силу других причин. Я изначально рассматривал вариант сведением второго каталога для UNIX-клиентов на базеOpenLdap, но хотелось все-таки управлять учетными запи-сями из единой точки, а именно из Active Directory, потомучто этот каталог широко используется у нас в сети.

ЕДИНАЯ УЧЕТНАЯ ЗАПИСЬДЛЯ WINDOWS И UNIXВ ACTIVE DIRECTORY

ИГОРЬ ПОЛЯНСКИЙ

Page 21: 025 Системный Администратор 12 2004

19№12(25), декабрь 2004

администрирование

Вариант Samba + winbind меня не устраивал, посколькупо роду задач samba вообще не нужна, к тому же это лиш-ние службы на каждой машине, использование которых все-таки не решает проблем с централизованным управлени-ем пользовательскими данными, поэтому это решение мнепоказалось неразумным и неизящным.

Более всего привлекал вариант с использованием сер-вера NIS, который входит в продукт, известный как ServicesFor Unix от компании Microsoft и синхронизация записейActive Directory to NIS. Зайдя на microsoft.com в надеждескачать SFU3.5, которая в отличие от предыдущей версииSFU3.0 бесплатна, я набрел на ряд интересных статей, про-читав которые, пошел по другому пути.

Как уже говорилось в начале, не все UNIX-подобные си-стемы могут проходить аутентификацию и запрашиватьданные о пользователе в Active Directory описанным здесьспособом, а только те, которые умеют работать с PAM иpam-модулями. Как вы, наверное, догадались, я буду опи-сывать способ взаимодействия с ldap-сервером, входящимв Active Directory через модули pam_ldap и nss_ldap.

Итак, начнем. В качестве подопытных будут выступатьMS Windows 2000 Server Standart с установленной ActiveDirectory (в дальнейшем AD), Linux Manrdake 10.0, Solaris 9x86, FreeBSD 4.10. Над Windows 2000/XP опыты ставить бес-смысленно – все и так работает. Как минимум понадобит-ся DNS-сервер, который может быть установлен на том жеWindows 2000 Server. Свежеустановленная AD не имеет тра-диционной ldap-схемы для UNIX: userid, grouid, login shell,home directory. Нам нужно её расширить, и для этого я вос-пользуюсь SFU3.5. Вообще-то существует несколько спо-собов это сделать: вручную создав ldif-файл с нужной схе-мой и импортировав его при помощи каких-либо программсторонних разработчиков, например такой, как AD4Unix(www.padl.com/download/MKSADPlugins.msi), или с помощьюSFU от Microsoft. Первый способ я оставляю гуру, вышеоз-наченную программу MKSADPlugins.msi вам установитьвряд ли удастся, если Windows 2000 Server работает с аль-тернативной локалью, отличной от US, что для России уме-стно. В пользу же SFU, на мой взгляд, говорит то, что онасделана в том же КБ, где Windows и AD, плюс в своем со-ставе имеет много утилит от UNIX.

Пройдя добровольно-принудительную процедуру полу-чения .NET Passport, вы сможете бесплатно скачать и ис-пользовать SFU3.5 (www.microsoft.com/windows/sfu). Размерпрограммы примерно 230 Мб. Прежде чем устанавливатьSFU, нужно инсталлировать Active Directory Schema MMCsnap-in следующей командой:

Для расширения схемы AD достаточно установить толь-ко NIS-сервер из состава SFU. Для успешного завершенияустановки необходимо быть либо членом групп DomainAdmins и Schema Admins, либо работать с правами Адми-нистратора. После установки будет предложено перегру-зить машину. NIS-сервер как таковой не понадобится и егоможно остановить и благополучно забыть о нём. В свой-ствах пользователя, группы, компьютера в Active DirectoryUsers and Computers добавится вкладка UNIX Attributes.

Как видите, теперь у каждого пользователя есть атрибу-ты, применяемые в UNIX-системах. Первое поле «NISDomain» будет содержать краткую форму имени нашего до-мена. Этот параметр нужен для службы NIS, и хотя в нашемслучае она не применяется, без нее не активируются другиеполя. С остальными полями, я думаю, затруднений не воз-никнет, может быть, за исключением GID. Прежде чем выб-рать из этого поля группу, её надо создать или в свойствахуже имеющейся задать UNIX-атрибуты. Проблема с группа-ми заключается в том, что нельзя задать одно и то же имядля пользователя и группы, а в мире UNIX такой подход весь-ма распространен. В таком случае можно использовать толь-ко численное представление, правда, я сомневаюсь, что этохороший выход из создавшейся ситуации. Ещё потребуетсясоздать учетную запись, которая будет применяться для вза-имодействия UNIX-машин с ldap-сервером. Это своего родадыра в безопасности, поэтому сей аккаунт не должен при-надлежать кому-либо и доступ к важным ресурсам ему дол-жен быть запрещен. Тем не менее он должен иметь право напоиск объектов в каталоге. На этом этапе вы готовы управ-лять единой учетной записью при помощи Active Directory.

Переходим к настройке клиентских машин. Я использо-вал Linux Mandrake 10.0 Official и всё необходимое ПО ус-танавливал из rpm-пакетов, входивших в состав дистрибу-тива. Понадобится установить pam_ldap и nss_ldap. Послеустановки этих пакетов нужно отредактировать несколькоконфигурационных файлов. Pam_ldap и nss_ldap для на-строек используют один и тот же файл ldap.conf. Также нуж-но будет отредактировать nsswitch.conf и как минимум одинфайл, находящийся в /etc/pam.d, а именно system-auth. Незабудьте сделать копии оригинальных файлов. Итак, файлldap.conf должен содержать следующее:

regsvr32 ñ:\WINNT\system32\schmmgmt.dll

# Áàçîâûå íàñòðîéêè, íåîáõîäèìûå äëÿ ïîäêëþ÷åíèÿ ê AD.# domain, loc è server.domain.loc âû äîëæíû èçìåíèòü# â ñîîòâåòñòâèè ñî ñâîèìè íàñòðîéêàìèbase dc=domain,dc=loc

Page 22: 025 Системный Администратор 12 2004

20

администрирование

Далее на очереди файл nsswitch.conf, тут всё просто –находите строчки:

и меняете их на:

Редактируем файл /etc/pam.d/system-auth:

В этом примере строчки, содержащие модуль pam_ldap.so, были добавлены в соответствии с рекомендациямиMicrosoft. Суть их такова, что сначала система применяет

правила для локального пользователя, если такой учетнойзаписи нет, то информация берется из AD. Но есть одна ма-ленькая проблема, которая может стать большой. Дело в том,что домашний каталог автоматически не создается и по умол-чанию таковым считается /. Вам придется создавать домаш-ние каталоги руками на каждой машине, что не очень удоб-но. Для этого можно использовать модуль pam_mkhomedir.При регистрации в данной системе модуль смотрит, есть лидомашний каталог, если нет, то он его создает и копируеттуда файлы из /etc/skel. Вы можете в соответствии со свои-ми требованиями менять и порядок модулей, и их опции дляразных служб. В таких перестановках надо быть осторож-ным, потому как можно прийти к неожиданным результатамвплоть до невозможности регистрироваться в системе дажепод учетной записью root. Для начала логично почитать что-нибудь о PAM. После этих манипуляций можно попробоватьзарегистрироваться на Linux-машине пользователем, кото-рый не упоминается в файлах passwd, shadow, group, но егоUNIX-атрибуты присутствуют в AD.

Если всё прошло отлично, то при первом входе средипрочих надписей увидим следующее:

Посмотрим, кем нас считает система:

Настраиваем Solaris 9 x86. В Solaris есть свои модулиpam_ldap и nss_ldap, только вот незадача – они не совсемсовместимы с Active Directory, поэтому Microsoft рекомен-дует использовать модули от PADL (www.padl.com), те же,что применяются в Linux. Чтобы скомпилировать эти моду-ли, потребуется установить ряд GNU-утилит, получить ихможно на www.sunfreeware.com. Оглашаю весь список:! autoconf-2.57-sol9-intel-local.gz! automake-1.7.2-sol9-intel-local.gz! gcc-3.2.1-sol9-intel-local.gz! m4-1.4-sol9-intel-local.gz! make-3.80-sol9-intel-local.gz

Плюс к этому берем с сайта www.blastwave.org пакетberkeleydb3-3.11-i386-CSW.pkg.gz.

Перед тем как собирать pam_ldap и nss_ldap, создадимсимволическую ссылку в /usr/local/bin на perl:

На файлы из каталогов /opt/csw/bin, /opt/csw/lib, /opt/csw/include, созданные в процессе инсталляции berkeleydb3-3.11-i386-CSW.pkg.gz, сделаем символические ссылки ваналогичные каталоги, расположенные в /usr. Сделаем ре-зервную копию оригинальных модулей pam_ldap и nss_ldap:

Объявим переменные среды:

cp /usr/lib/security/pam_ldap.so.1 ↵↵↵↵↵/usr/lib/security/pam_ldap.so.1.bak;

cp /usr/lib/nss_ldap.so.1 /usr/lib/nss_ldap.so.1.bak

passwd: files nisplus nisshadow: files nisplus nisgroup: files nisplus nis

passwd: files ldapshadow: files ldapgroup: files ldap

#%PAM-1.0auth required pam_env.soauth sufficient pam_unix.so likeauth nullokauth sufficient /lib/security/pam_ldap.so ↵↵↵↵↵

use_first_passauth required pam_deny.soaccount required pam_unix.soaccount [default=bad success=ok user_unknown=ignore ↵↵↵↵↵

service_err=ignore system_err=ignore] ↵↵↵↵↵lib/security/pam_ldap.so

password required pam_cracklib.so retry=3 ↵↵↵↵↵minlen=2 dcredit=0 ucredit=0 ucredit=0

password sufficient pam_unix.so nullok ↵↵↵↵↵use_authtok md5 shadow

password sufficient /lib/security/pam_ldap.so ↵↵↵↵↵use_authtok

password required pam_deny.sosession required pam_limits.sosession required pam_unix.sosession required /lib/security/pam_mkhomedir.so ↵↵↵↵↵

skel=/etc/skel umask=0022session optional /lib/security/pam_ldap.so

Creating directory '/home/test'.

Creating directory '/home/test/tmp'.

[test@linux-pc test]$ id

uid=10000(test) gid=10000(testgroup) groups=10000(testgroup)

ln -s /usr/bin/perl /usr/local/bin/perl

scope suburi ldap://server.domain.locport 389ldap_version 3# Òîò ñàìûé àêêàóíò, êàê âèäèòå, îí áûë ñîçäàí â êîíòåéíåðå# Users ñ èìåíåì ldap è ïàðîëåì qwertybinddn cn=ldap,cn=Users,dc=domain,dc=locbindpw qwerty# Êîãäà âû áóäåòå ââîäèòü èìÿ ïîëüçîâàòåëÿ è ïàðîëü, áóäóò# ïðèìåíÿòüñÿ ñëåäóþùèå îáúåêòû è àòðèáóòû èç AD:pam_filter objectclass=Userpam_login_attribute sAMAccountNamepam_password ad# Ýòè çàïèñè íóæíû äëÿ óñêîðåíèÿ ïîèñêà. Ìîæåòå èõ âîîáùå# íå âñòàâëÿòü. Îáðàòèòå âíèìàíèå, âñå ïîëüçîâàòåëè â ýòîì# ïðèìåðå õðàíÿòñÿ â «Organization Unit →→→→→ firma»nss_base_passwd ou=firma,dc=domain,dc=loc?subnss_base_shadow ou=firma,dc=domain,dc=loc?subnss_base_group ou=firma,dc=domain,dc=loc?sub# Ýòè çàïèñè îòíîñÿòñÿ ê ìîäóëþ nss_ldap, ïðåîáðàæàþò# îáúåêòû è àòðèáóòû AD ê âèäó, ïðèíÿòîìó â LDAPnss_map_objectclass posixAccount Usernss_map_objectclass shadowAccount Usernss_map_attribute uid sAMAccountNamenss_map_attribute uidNumber msSFU30UidNumbernss_map_attribute gidNumber msSFU30GidNumbernss_map_attribute cn sAMAccountNamenss_map_attribute uniqueMember membernss_map_attribute homeDirectory msSFU30HomeDirectorynss_map_attribute loginShell msSFU30LoginShellnss_map_attribute gecos namenss_map_objectclass posixGroup Group

PATH=/usr/local/bin:$PATHLD_LIBRARY_PATH=/usr/local/libexport LD_LIBRARY_PATH

Page 23: 025 Системный Администратор 12 2004

21№12(25), декабрь 2004

администрирование

Это сработает для оболочек, совместимых по синтак-сису с sh, например, bash, ksh. Если вы пользуетесь другиминтерпретатором, посмотрите документацию к нему.

Соберем модули от PADL, перейдя в соответствующиедиректории, созданные в процессе разархивации файлов,полученных с www.padl.com/download:

Если все прошло удачно, редактируем ldap.conf иnsswitch.conf аналогично Linux, за исключением строчки:

которую заменим на:

Linux воспринимает оба формата, Solaris почему-то толь-ко host. Настройки PAM в Solaris хранятся в файле /etc/pam.conf. На этом этапе, следуя советам Microsoft, я полу-чил неработоспособную систему, поэтому кое-что поменяли добавил (представлены фрагменты с внесенными изме-нениями):

Здесь смысл примерно такой же, как и в случае с Linux.Pam_mkhomedir для Solaris не существует, но его можнособрать самостоятельно. Я следовал инструкциям на http://keutel.de/pam_mkhomedir и получил работоспособный мо-дуль, проделав следующие шаги на машине с Solaris:! Скачал и распаковал исходный код Linux-PAM: http://

www.kernel.org/pub/linux/libs/pam/pre/library/Linux-PAM-0.77.tar.gz, допустим, в /tmp.

! Скачал исходный код: http://keutel.de/pam_mkhomedir/pam_mkhomedir.c тоже в /tmp и скомпилировал следую-щей командой (в одну строчку), находясь в /tmp:

! Получил готовый модуль следующей командой:

К сожалению, FreeBSD 4.x не умеет работать с nss_ldapи значит запрашивать данные о пользователе в AD, плюсне может менять пароль стандартными средствами с помо-щью pam_ldap. Но всё же доступ к машине, как с консоли,так и к службам ssh, ftp и т. д. можно получить, пройдя аутен-тификацию в Active Directory. Для этого установите pam_ldap, отредактируйте два файла – ldap.conf и pam.conf. Вldap.conf достаточно внести следующий фрагмент:

В этом случае пароль из AD будет запрашиваться привходе с консоли, ftp и ssh, если пароль отвергнут, поискбудет продолжен в локальных файлах.

Локально пароль можно вообще не хранить. Для этогопри помощи команды vipw отредактируйте файл паролей.

/usr/local/bin/gcc -D_REENTRANT -g -O2 -Wall -fPIC ↵↵↵↵↵-c -ILinux-PAM-0.77/libpam/include ↵↵↵↵↵-ILinux-PAM-0.77/libpamc/include ↵↵↵↵↵-ILinux-PAM-0.77/modules/pammodutil/include ↵↵↵↵↵-DPAM_DYNAMIC pam_mkhomedir.c -o pam_mkhomedir.o

/usr/ccs/bin/ld -o pam_mkhomedir.so -B dynamic -G ↵↵↵↵↵-lc pam_mkhomedir.o

base dc=domain,dc=locscope suburi ldap://server.domain.locport 389ldap_version 3binddn cn=ldap,cn=Users,dc=domain,dc=locbindpw qwertypam_filter objectclass=Userpam_login_attribute sAMAccountNamepam_password ad

login auth sufficient /usr/local/lib/pam_ldap.sologin auth sufficient pam_skey.sologin auth sufficient pam_opie.so no_fake_prompts#login auth requisite pam_opieaccess.sologin auth requisite pam_cleartext_pass_ok.so#login auth sufficient pam_kerberosIV.so try_first_pass#login auth sufficient pam_krb5.so try_first_passlogin auth required pam_unix.so try_first_passlogin account required pam_unix.sologin password required pam_permit.sologin session required pam_permit.so# Same requirement for ftpd as loginftpd auth sufficient /usr/local/lib/pam_ldap.softpd auth sufficient pam_skey.softpd auth sufficient pam_opie.so no_fake_prompts#ftpd auth requisite pam_opieaccess.softpd auth requisite pam_cleartext_pass_ok.so#ftpd auth sufficient pam_kerberosIV.so try_first_pass#ftpd auth sufficient pam_krb5.so try_first_passftpd auth required pam_unix.so try_first_pass# OpenSSH with PAM support requires similar modules.# The session one is a bit strange, though...sshd auth sufficient /usr/local/lib/pam_ldap.sosshd auth sufficient pam_skey.sosshd auth sufficient pam_opie.so no_fake_prompts#sshd auth requisite pam_opieaccess.so#sshd auth sufficient pam_kerberosIV.so try_first_pass#sshd auth sufficient pam_krb5.so try_first_passsshd auth required pam_unix.so try_first_passsshd account required pam_unix.sosshd password required pam_permit.sosshd session required pam_permit.so

cd pam_ldap-176./configuremakemake installcd nss_ldap-226./configure --enable-schema-mappingmakemake install

uri ldap://server.domain.loc

host server.domain.loc

# login service (explicit because of pam_dial_auth)login auth requisite pam_authtok_get.so.1login auth required pam_dhkeys.so.1login auth sufficient pam_unix_auth.so.1login auth required pam_dial_auth.so.1login auth sufficient pam_ldap.so.1 use_first_pass# Default definitions for Authentication management# Used when service name is not explicitly mentioned# for authencticationother auth requisite pam_authtok_get.so.1other auth required pam_dhkeys.so.1other auth sufficient pam_unix_auth.so.1other auth sufficien pam_ldap.so.1 use_first_pass# Default definition for Session management# Used when service name is not explicitly mentioned# for session managementother session required pam_unix_session.so.1other session sufficient ↵↵↵↵↵

pam_mkhomedir.so skel=/etc/skel/ umask=0022# Default definition for Password management# Used when service name is not explicitly mentioned# for password managementother password required pam_dhkeys.so.1other password requisite pam_authtok_get.so.1other password requisite pam_authtok_check.so.1other password required pam_authtok_store.so.1other password sufficient pam_ldap.so.1 use_authtok

Page 24: 025 Системный Администратор 12 2004

22

администрирование

Сотрите зашифрованный пароль во втором поле и поставь-те там * (звёздочка).

По сведениям, взятым на http://www.padl.com/OSS/nss_ldap.html, FreeBSD 5.1 и выше уже работает с nss_ldap, нопроверить это лично не удалось по причине отсутствия ди-стрибутива.

Осталось прикрутить SSL. Хотя это вовсе не обязатель-но, наверняка вы захотите использовать шифрование подвум причинам. Первая – безопасность, ведь запросы к ldap,в том числе пароли, передаются в открытом виде, вторая –возможность пользователю самому менять пароль в ADпосредством стандартной команды passwd. Необходимопроделать некоторые операции, как на Windows-сервере,так и на клиентских машинах.

На сервере:! Убедиться, что поддерживается шифрование 128 bit, ина-

че вы не сможете удаленно поменять пароль. Windows2000 sp2 и выше это умеет, в противном случае устано-вите Encryption pack.

! Установить сервис сертификатов, входящий в дистри-бутив. Без этого сервер не будет принимать соедине-ния по протоколу ldaps. В процессе инсталляции серви-са сертификатов будет предложено создать корневойсертификат. Заполнив поля (можно не все), вы получи-те файл сертификата, лежащий в директории с:\. Де-лать с ним ничего не придется. В журнале событий (eventviewer) должна появиться запись о возможности приня-тия соединений LDAPS (прим.: у меня это сообщениепоявилось на следующий день, может, потому, что я неперегружал машину, а до этого все попытки коннектана ldaps:636 терпели неудачу). Проверить, что серверработает корректно, можно простым способом. С лю-бой Windows-машины в домене или на самом серверевыполните «Start →→→→→ Search →→→→→ For People».

В свойствах укажите адрес сервера, порт 636, контей-нер для поиска.

В данном примере мы ищем объекты в контейнере Users.Если поиск завершился успехом, значит ваш сервер настро-ен на прием запросов по протоколу LDAPS порт 636.

На клиенте:Самым простым решением для меня оказалось исполь-

зование программы stunnel. После установки stunnel нуж-но поправить два файла stunnel.conf и ldap.conf. Stunnel.confможет выглядеть так:

Из данного примера мы видим – stunnel работает в кли-ентском режиме, слушает запросы на 127.0.0.1 порт 389 ипересылает их на Windows-сервер порт 636 уже в зашиф-рованном виде. В зависимости от операционной системывам придется вручную создать пользователя stunnel и ка-талог /var/tmp/stunnel с возможностью записи для этогопользователя. В файле ldap.conf просто поменяем строчку:

на

Перегружаем машину, регистрируемся, пробуем менятьпароль. Параллельно tcpdump на другом терминале можнонаблюдать наши SSL-соединения.

В результате мы имеем централизованную систему уп-равления пользователями средствами Active Directory, чтозначительно облегчает работу администратора. Интегра-ция таким способом позволяет внедрить UNIX-системы всуществующую структуру Windows-сетей и при этом отка-заться от ведения дополнительных каталогов или хране-ния пользовательских данных на каждой машине.

ri ldap://server.domain.loc

host 127.0.0.1

chroot = /var/tmp/stunnelpid = /stunnel.pidsetuid = stunnel

setgid = stunnel# Some debugging stuffdebug = 7output = /var/log/stunnel.log# Use it for client modeclient = yes# Service-level configuration[ldap]accept = 127.0.0.1:389connect = server.domain.loc:636

Page 25: 025 Системный Администратор 12 2004
Page 26: 025 Системный Администратор 12 2004

24

администрирование

Представьте себе ситуацию: узел СПД в составе маршру-тизатора CISCO и коммутатора Catalyst находится на пер-вом этаже, а ваш FreeBSD-сервер – на четвертом. И приэтом требуется вывести во внешний мир несколько подсе-тей, которые проходят через сервер FreeBSD на Catalyst.Можно, конечно, подключить к серверу несколько сетевыхадаптеров, занять для внутреннего использования несколь-ко портов на Catalyst и пробросить между этажами кило-метр кабеля 5-й категории. На кабеле можно даже сэконо-мить, пропустив по одному кабелю сразу два соединения изадействовав тем самым все имеющиеся пары. Однако всеравно и затрат, и дополнительных работ по прокладке ка-белей получается слишком много. А раз возникает слож-ность, то наверняка кто-то уже нашел способ ее устранить.И в нашем случае панацеей будет технология VLAN – вир-туальные локальные сети.

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

На уровне протоколов это достигается добавлением не-скольких полей в заголовок пакета сетевого уровня. Одноиз добавленных полей содержит идентификатор (номер)сети VLAN, на основе которого и происходит разделениеEthernet-кадров по виртуальным сетям. Кадры, имеющиеодинаковый номер VLAN, рассматриваются как принадле-жащие одной подсети. Регламентируется это стандартомIEEE 802.1Q.

Развитие технологии VLAN привело к тому, что сталовозможным не только назначать отдельные подсети отдель-ным портам, но и через один порт пропускать несколькоVLAN (так называемый multiVLAN). То же относится и к се-тевым адаптерам, чем мы и воспользуемся.

Рассмотрим настройку VLAN для FreeBSD на следую-щем примере: пусть имеется один отрезок кабеля междуCatalyst и FreeBSD. На Catalyst свободен один порт, наFreeBSD – одна сетевая карта, обслуживающая внешниесоединения. Нужно через это соединение организоватьпередачу следующих подсетей:

! подсеть реальных адресов для работы в Интернете(111.222.0.0/28);

! корпоративная частная подсеть для доступа к вышесто-ящим узлам компании (10.0.123.0/24);

! и еще одна сеть для управления оборудованием СПД(10.254.0.0/24).

Прежде всего нужно проверить, поддерживает ли вашасетевая карта работу по VLAN. Некоторые карты обеспе-чивают поддержку данной технологии на аппаратном уров-не, однако драйвер также должен поддерживать VLAN.Страница справочного руководства (см. man vlan) дляFreeBSD 5.2 сообщает, что аппаратное мультиплексирова-ние поддерживается для драйверов bge, em, gx, nge, ti иtxp. (Во FreeBSD 5.3 к этому списку добавился еще и драй-вер re, обеспечивающий работу сетевых адаптеров на чип-сетах RealTek 8139C+/8169/8169S/8110S). Узнать подроб-ную информацию по каждому из драйверов, в том числесписок поддерживаемых драйвером моделей сетевых карт,можно на страницах man (например, man 4 em сообщает,что драйвером em поддерживается Intel PRO/1000 GigabitEthernet adapter). Если ваш адаптер не входит в этот спи-сок, то наверняка он сможет работать с использованиемпрограммной эмуляции мультиплексирования. По крайнеймере, для большинства современных карт это утвержде-ние справедливо. Нужно заметить, что тот же man vlan гла-сит, что сетевой адаптер для полноценной эмуляции дол-жен поддерживать «длинные» кадры (oversized frames). Впротивном случае из-за необходимости размещения допол-нительных полей заголовка, содержащих информацию оVLAN, которой принадлежит пакет, приходится снижать мак-симальный размер передаваемого пакета (MTU) на соот-ветствующем интерфейсе.

Драйвера сетевых адаптеров, поддерживающих длин-ные кадры, перечислены в man vlan, однако данный списокнельзя считать исчерпывающим, поскольку с 2002 года (ког-да писались страницы руководства) ситуация измениласьв лучшую сторону и перечень совместимых сетевых картзначительно расширился. По крайней мере, D-Link DFE-538TX, работающий на драйвере rl, отсутствующем в спис-ке, никаких нареканий с моей стороны не вызвал. (Замеча-

FreeBSD TIPS:НАСТРОЙКА VLAN

СЕРГЕЙ СУПРУНОВ

Page 27: 025 Системный Администратор 12 2004

25№12(25), декабрь 2004

администрирование

ние: во FreeBSD 5.3 поддержка vlan значительно расшире-на, и теперь поддержка длинных кадров драйвером rl офор-млена официально.)

Пожалуй, хватит теории. Перейдем к практике.Для работы VLAN в системе должны быть соответствую-

щие псевдоустройства. В случае с FreeBSD 5.2 (думаю, этосправедливо и для всей 5-й ветки) устройства vlan создают-ся динамически. За это отвечает модуль ядра if_vlan.ko. Есливы предпочитаете иметь монолитное ядро, то потребуетсяпересобрать его со следующей опцией:

Для 3-й и 4-й веток FreeBSD может потребоваться пе-ресобрать ядро с такой строчкой:

Вместо N нужно подставить количество устройств, ко-торое вам понадобится. После сборки и установки новогоядра в системе должны появиться соответствующие интер-фейсы vlan0, vlan1 и т. д., просмотреть которые можно ко-мандой:

Для FreeBSD 5.2 (в недавно вышедшей 5.3 все настра-ивается точно так же) для создания vlan-интерфейсов ис-пользуется «клонирование» (cloning) на этапе загрузки (обэтом – чуть ниже) либо программа ifconfig с опцией create.Второй вариант выглядит следующим образом:

Опция vlan задает номер VLAN, присвоенный этой сети.Параметр vlandev указывает физический интерфейс, исполь-зуемый для организации VLAN. Заметьте, что этот интерфейс(в нашем случае rl0) должен иметь собственный IP-адрес,даже если реально он нигде использоваться не будет:

Обратите внимание, что интерфейсы vlan наследуютMAC-адрес «родительского» интерфейса, но поскольку сетиу нас разные, то ни к каким конфликтам это не приведет.

Если со стороны CISCO все настроено должным обра-зом (собственно говоря, основное требование – номер VLANдолжен совпадать с тем, который назначен интерфейсу состороны FreeBSD), то после этой команды все должно ра-ботать. Например, конфигурация интерфейса для подсетиреальных адресов на CISCO у меня выглядит следующимобразом:

Аналогично описываются остальные интерфейсы. Иден-тификатор VLAN задается в параметре encapsulation dot1Q,в данном случае он равен 111.

На Catalyst соответствующий порт нужно перевести вtrunk-режим и при желании можно указать список разре-шенных номеров VLAN:

С точки зрения остальных служб операционной систе-мы, например ipfw или natd, полученный интерфейс ничемне отличается от физических и может использоваться какобычно. Например, можно подсчитать трафик, проходящийчерез vlan0:

Остался последний штрих – настройка конфигурациидля автоматического создания нужного интерфейса при пе-резагрузке. Для этого в файл /etc/rc.conf добавим следую-щие строчки:

Если «пропадание» сервера на пару минут не критич-но, то рекомендуется его перезагрузить, чтобы лишний разубедиться в правильности всех настроек. Бежать среди ночик неудачно загрузившемуся из-за пропущенного пробеласерверу – не самое приятное занятие.

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

device vlan

pseudo-device vlan N

# ifconfig vlan0

# ifconfig vlan0 create 111.222.0.5 ↵↵↵↵↵netmask 255.255.255.240 vlan 111 vlandev rl0

# ifconfig vlan0

ifconfig: interface vlan0 does not exist

vlan0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500

inet 111.222.0.5 netmask 0xfffffff0 broadcast 111.222.0.15

inet6 fe70::204:5cff:fedf:f81f%vlan0 prefixlen 64 scopeid 0xd

ether 00:05:5d:cf:f9:1e

media: Ethernet autoselect (100baseTX <full-duplex>)

status: active

vlan: 111 parent interface: rl0

# ifconfig rl0rl0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500

options=8<VLAN_MTU>

inet 10.10.10.10 netmask 0xffffff00 broadcast 10.10.10.255

inet6 fe70::204:5cff:fedf:f81f%rl0 prefixlen 64 scopeid 0x1

ether 00:05:5d:cf:f9:1e

media: Ethernet autoselect (100baseTX <full-duplex>)

status: active

interface FastEthernet0/0.111 encapsulation dot1Q 111 ip vrf forwarding Inet ip address 111.222.0.1 255.255.255.240 no ip route-cache

interface FastEthernet0/24 switchport trunk allowed vlan 100,111,999 switchport mode trunk no ip address

# ipfw add 1234 count ip from any to any via vlan0

# Ñîçäàåì íóæíûå èíòåðôåéñû, èñïîëüçóÿ ìåõàíèçì# êëîíèðîâàíèÿ:cloned_interfaces="vlan0 vlan1 vlan2"# È îïèñûâàåì ñîîòâåòñòâóþùèå èíòåðôåéñû VLAN:ifconfig_vlan0="inet 111.222.0.5 ↵↵↵↵↵

netmask 255.255.255.240 vlan 111 vlandev rl0"ifconfig_vlan1="inet 10.254.0.5 ↵↵↵↵↵

netmask 255.255.255.0 vlan 100 vlandev rl0"ifconfig_vlan2="inet 10.0.0.3 ↵↵↵↵↵

netmask 255.255.255.0 vlan 999 vlandev rl0"

ifconfig -a

Page 28: 025 Системный Администратор 12 2004

26

администрирование

БИЛЛИНГ ДЛЯ АТС НА БАЗЕ PostgreSQL

ГЕОРГИЙ ТОЛОКОННИКОВ

В статье рассматривается содержащая около 90 строк кодабиллинговая система для небольших АТС, которая легкоможет быть расширена на АТС большой номерной емкос-ти. В качестве примера рассматривается NEAX2000 IPS.

Стандартный выход АТС соединяется с портом компью-тера, приходящая от АТС информация захватывается скрип-том биллинговой системы, обрабатывается, и направляет-

ся в базу данных телефонных переговоров, поддерживае-мую СУБД PostgreSQL. На основе базы данных ведется под-счет трафика, расчет оплаты и выполняются практическилюбые запросы, интересующие пользователей.

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

Page 29: 025 Системный Администратор 12 2004

27№12(25), декабрь 2004

администрирование

дится к тому, что обозначение внутренних номеров начина-ется со знака *, например, *029. Такая нумерация обычноиспользуется, чтобы можно было звонить «в город» без на-бора «9».

Соединим кабелем COM-порт компьютера с RS232разъемом АТС, находящимся на процессорной плате. Дляопределенности используем нулевой порт – как правило, вкомпьютере два COM-порта: нулевой и первый.

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

Введем следующую команду для прослушивания пор-та, на который поступает информация от АТС (для Linuxпорт будет называться не dev/cuaa0, а, cкорее всего, /dev/ttyS0):

получим при каждом исходящем вызове добавку к содер-жимому файла file:

(с учетом пробелов для каждой записи получаем 128 бай-тов, по байту на каждый символ).

Приведенный пример содержит информацию о том, чтос номера *029, 11 августа с 7 час. 37 мин. 26 сек до 37 мин.56 сек. абонент звонил на номер 100 (служба «время» вМГТС).

При разборке файла с помощью Perl в качестве при-знака конца записи для отдельных вызовов можно принятьвосклицательный знак «!».

Воспользовавшись вызовом sysread(fd, $v, length), гдеfd – дескриптор файла $v – переменная, в которую пишет-ся информация, length – количество считывающихся бай-тов за один вызов, можно установить, что АТС выдает всюзапись по вызову отдельными порциями наборов символов,указанных в примере, разделенными пробелами. В АТСимеется буфер (довольно приличный по размеру), в кото-ром хранятся данные по вызовам, так что при соединениис компьютером все предыдущие вызовы «скачиваются» вкомпьютер.

Код будущей программы состоит из двух блоков:! блок считывания и обработки (считывает из порта ин-

формацию, поступающую из АТС);! блок загрузки записей в базу данных.

Перед рассмотрением приведенного ниже кода скрип-та подчеркнем следующее.

Наша цель – показать, что создать собственную систе-му биллинга совсем несложно. У каждого системного ад-министратора есть свои излюбленные приемы в Perl, кото-рые он при необходимости использует, приспособив под-ходящим образом приведенный скрипт или написав свойсобственный. Поэтому мы для краткости оставили лишь ти-повую обработку ошибок, не стремимся усложнять код дляобеспечения его безопасности, оптимальности или кратко-сти. Отметим только, что приведенный код неплохо рабо-тал у нас на стареньком отдельно стоящем компьютере:

# cat /dev/cuaa0 >> file

^B0!KA050077001*029 08110737260811073756

000050050100 0000 04040

ВведениеБиллинговая система – это комплекс программ, работаю-щий на компьютере, сопряженном с АТС и позволяющийтарифицировать телефонный трафик, выставлять счетаабонентам, получать практически любую информацию позвонкам.

Такие системы обычно дороги. Многие пользуются WinTarif (как правило, взломанной версией…). Можно также по-смотреть сайт www.billonline.ru со всеобъемлющим серти-фицированным Министерством связи решением проблем(за деньги) учета телефонных переговоров.

Наш подход, однако, – демонстрация философии UNIXв действии – позволяет обеспечить простое, бесплатное,открытое решение. Состоит оно из нескольких десятковстрок кода и опирается на типовые утилиты UNIX. Слож-ность кода минимальная, достаточно, например, владенияазами SQL и Perl. Обычно оператор связи, предоставив-ший телефоны, выставляет счет раз в месяц, а тарифика-цию по внутренним номерам офисной АТС либо вообще от-казывается делать, либо требует дополнительной оплаты.Платное программное обеспечение имеет закрытый код ине ясно, что и как оно считает, заменить в нем что-нибудьна более подходящий вариант невозможно. Таким образом,наличие подобного предлагаемого в статье простого реше-ния полезно для работы организации.

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

План действий по автоматизации тарификации АТС сле-дующий:! смотрим, что и в каком формате выводит АТС на порт,

сопрягаемый с компьютером (часто это com-порт);! пишем скрипт, разбирающий должным образом полу-

чаемый поток байтов с АТС;! заводим в СУБД (PostgreSQL) необходимые таблицы;! добавляем к скрипту блоки захвата вывода с АТС и заг-

рузки обработанных скриптом записей в СУБД;! формируем скрипт сопряжения базы данных с веб-сер-

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

Собственно и все. За пару дней это можно сделать изапустить в эксплуатацию. Например, на следующем комп-лексе: Pentium-200 MMX, 256 Мб ОЗУ, FreeBSD версии 4.5и выше с Perl5, PostgreSQL 7 довольно быстро обрабаты-вается до 100 тыс. записей звонков. Это около 100-150 но-меров абонентов, звонящих с интенсивностью выше сред-ней в течение месяца. На Pentium 4 можно легко обрабаты-вать уже миллионы записей.

Все вышеприведенное будет легко работать и под лю-бым другим UNIX.

Тестирование формата вывода АТСи алгоритм программыСначала надо изучить выходные сигналы АТС. Мы рассмат-риваем NEAX2000 IPS с настройками, практически не от-личающимися от стандартных. В нашем случае отличие сво-

Page 30: 025 Системный Администратор 12 2004

28

администрирование

процессы внутри АТС относительно медленные и Perl успе-вает делать все вовремя и без ухищрений.

Отлаженный вариант биллинговой системы с учетомкода для вывода данных с помощью PHP на Apache-сервердостаточно длинный для размещения в тексте, поэтому пре-доставлен автором всем желающим (www.samag.ru/source).

Реализация программыДля реализации программы с помощью системы портовFreeBSD помимо PostgreSQL необходимо для работы ин-терфейса Perl к PostgreSQL установить модули Perl – DBI,DBD-Pg.

Запустив PostgreSQL, создадим таблицу atstarif базыданных ats:

Таким образом, строки в ней будут содержать поля:! Номер, инициировавший соединение.! Дата и время начала разговора.! Длительность звонка в минутах разговора.! Номер, на который шел вызов.

Программа биллинга на Perl может иметь следующийвид (некоторые комментарии даны в самом коде).

Программу можно запустить в фоновом режиме, обыч-ным образом обеспечить ее запуск при перезагрузке ком-пьютера, организовать ее использование по усмотрениюсистемного администратора.

# create table atstarif (nums varchar(15), mydate date, ↵↵↵↵↵mytime time, min int, numd bigint);

#!/usr/bin/perluse POSIX qw(:errno_h);use DBI;use strict;my $user="pgsql";my $dbname="ats";my $dsh;my $dbh;my $p;my $pid;$SIG{ALRM}= 'proga';sub proga {kill 9 => $pid;kill 9 => $p;}# ïðîãðàììà ðàáîòàåò â áåñêîíå÷íîì öèêëå, ïåðèîäè÷åñêè# (ðàç â äâå ìèíóòû) ïîäêëþ÷àÿñü ê ïîðòó, íà êîòîðûé# ÀÒÑ ïîñûëàåò äàííûå î çâîíêàõwhile(1){$dsh="dbi:Pg:dbname=$dbname;port=5432";$dbh=DBI->connect("$dsh", "$user") or die ↵↵↵↵↵

"can't connect: $!\n";$pid=open (ATS, "cu -l/dev/cuaa1 -s9600|");$p=($pid)+1;# ïðîãðàììà ïîäêëþ÷èëàñü ê áàçå äàííûõ è íà÷àëà ñ÷èòûâàòü# äàííûå îò ÀÒÑeval { alarm(60); };my @str = <ATS>;my $sstr;my $ccc;my $ss;my $g;# â ýòîì öèêëå íà÷èíàåòñÿ îáðàáîòêà ïîñòóïàþùèõ ñòðîê îò ÀÒÑforeach $sstr (@str) { if ($sstr=~ /!/) { my @s= split /!/, $sstr;# ïîäñ÷åò âðåìåíè çâîíêà óäîáíî âûäåëèòü â îòäåëüíóþ# ïîäïðîãðàììó

sub duration {my $a=substr($ccc, 6, 10);my $b=substr($ccc, 16, 10);my @aa=split //, $a;my @bb=split //, $b;my $aaa=(($aa[2]*10)+$aa[3])*24*60*60+($aa[4]*10+ ↵↵↵↵↵

$aa[5])*60*60+($aa[6]*10+$aa[7])*60+$aa[8]*10+$aa[9];my $bbb=(($bb[2]*10)+$bb[3])*24*60*60+($bb[4]*10+ ↵↵↵↵↵

$bb[5])*60*60+($bb[6]*10+$bb[7])*60+$bb[8]*10+$bb[9];my $r=$bbb-$aaa;my $cc1=$r%60;my $cc11=($r-$cc1)/60;my $cc2=$cc11%60;my $cc21=($cc11-$cc2)/60;my $cc3=$cc21%24;my $z=" h$cc3 m$cc2 s$cc1 ";}foreach $ss (@s){ $ss =~ s/.*\*/\*/g; $ss =~ s/\b0000 .*//g; $ss =~ s/\b0000600606//g; $ss =~ s/\b000050050//g; $ccc=$ss; my $z=substr($ss, 16, 10);# òåïåðü ïðèìåíèì ïîäïðîãðàììó ïîäñ÷åòà âðåìåíè# ê ïåðåìåííîé $ccc; my $res=&duration; $ss=~ s/$z/$res/g; $ss=~ s/h//g; $ss=~ s/m//g; $ss=~ s/s//g; my @f= split (/\s+/, $ss); if ($f[4]) { $f[4] = 1; } my $z = $f[2]*60 + $f[3] + $f[4]; my @g = split (//, $f[1]); if ($g[4]==0) { $g[4]=""; } my @gg = ($g[2].$g[3], '.', $g[0].$g[1], '.', ↵↵↵↵↵

'04', " ", $g[4].$g[5], ':', $g[6].$g[7]); $f[1]= join ("", @gg); my @ff = ($f[0], $f[1], $z, $f[5]); $ss = join (" ", @ff);if ($ss=~ /\*\d\d\d \d\d\.\d\d\.\d\d \d+:\d+ \d+ \d+/) {# ñòðîêà ñôîðìèðîâàíà äëÿ çàïèñè â áàçó äàííûõ$g= $ss;# òåïåðü ñòðîêó $g ïðèâåäåì ê íåîáõîäèìîìó ôîðìàòó# è çàãðóçèì â áàçó äàííûõchomp($g);my @gg=split / /, $g;my @ggg=split /\./, $gg[1];$gg[1]=join "-", "20$ggg[2]", $ggg[1], $ggg[0];my @dt;$dt[0]=$dbh->quote("$gg[0]");$dt[1]=$dbh->quote("$gg[1]");$dt[2]=$dbh->quote("$gg[2]");$dt[3]=$dbh->quote("$gg[3]");$dt[4]=$dbh->quote("$gg[4]");my $tbl="atstarif ";$dbh->do("insert into $tbl (nums, mydate, mytime, min, numd) values ($dt[0], $dt[1], $dt[2], $dt[3], $dt[4])"); } } }}$dbh->disconnect();close ATS;sleep(60);}

Page 31: 025 Системный Администратор 12 2004
Page 32: 025 Системный Администратор 12 2004

30

администрирование

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

В прошлой статье1 я рассказал об основных возможно-стях пакетного фильтра операционной системы OpenBSDи почему так важно использование фильтров. Недавно нампоступило тревожное сообщение от одной из организацийо том, что их сервер «барахлит», мне пришлось ехать и про-верять, но я и не подозревал, насколько всё серьёзно! Сетьорганизации была спроектирована довольно хорошо, од-нако единственным слабым местом был Linux-сервер, накотором крутились Java-сервлеты и обслуживали денеж-

ные транзакции. Пограничным хостом (firewall) была дав-ненько установленная нами, в то время еще OpenBSD 3.1-stable, с PF в качестве пакетного фильтра. При осмотреLinux-сервера сразу стало понятно, что его атаковали, и нераз, я нашел огромное количество различных exploits насервере и несколько скриптов, которые в тот момент дер-жали открытыми порты с shell, запущенными от прав www-сервера. После проверки сервера различными методами япришел к выводу, что злоумышленникам так и не удалосьни похитить данные, ни проникнуть на сервер. Мне сталоинтересно, как же данные со взломанного сервера (сервердействительно считался взломанным по нашим критериям)так и не ушли в чужие руки.

ПАКЕТНЫЙ ФИЛЬТР OpenBSDЧАСТЬ 2

ДЕНИС НАЗАРОВ

1 Назаров Д. Пакетный фильтр OpenBSD. – Журнал «Системный администратор», №11, ноябрь 2004 г.

Page 33: 025 Системный Администратор 12 2004

31№12(25), декабрь 2004

администрирование

Так как сервер останавливать было нельзя, пришлосьвживую искать все ниточки. Все свелось к одному – на сер-вере с OpenBSD, посмотрев лог-файлы пакетного фильт-ра, сразу стало ясно, что любые попытки добраться к темshell на Linux-сервере оканчивались провалом, ибо фильт-рация была настолько четкой, что помимо входящих соеди-нений контролировались и все исходящие. Дальнейшее ис-следование показало все места, откуда были произведеныатаки, и подтвердило их безуспешность. Сейчас в той орга-низации стоит новый мощный сервер под управлением SunSolaris 10 и теперь уже OpenBSD 3.6-stable. К чему вся этаистория? Показать на конкретном примере, как важно ис-пользование пакетных фильтров и как они могут защититьзаведомо опасные приложения.

Итак, приступим к продолжению нашей статьи, я рас-скажу вам о следующих вещах:! Распределение по очередям (Queuing).! Роутинг (маршрутизация).

Распределение по очередям (Queuing)Любые пакеты могут быть разделены по очередям для кон-троля полосы пропускания. Зачем это надо? Распределятьнагрузку на канал равномерно для всей сети, например, илиже, наоборот, урезать трафик для определенного сервисаили IP-адреса. Для определения «очереди» (queue) нужнывсего лишь две декларации, и в дальнейшем все пакетыможно будет распределять по очередям, используя «имяочереди». Согласно компоненту фильтрации пакетногофильтра (PF), для правила pass данный пакет будет поме-щен в очередь, на которую ссылалось последнее(!) прави-ло. Немножко запутанно?

Поясню на примере:

Здесь будет применено последнее правило, т.е пакет бу-дет присвоен очереди с именем «www-2».

Очередями управляют «планировщики». На данный мо-мент PF поддерживает 3 типа «планировщиков»:! CBQ (Class Based Queueing) – очереди, прикрепленные

к интерфейсу, создают «дерево», в котором каждая изэтих очередей может иметь своих «потомков». Очере-ди имеют приоритет и полосу пропускания. Приоритетопределяет, через какую очередь пакет пройдет первым,а полоса пропускания уже непосредственно влияет наскорость прохождения. CBQ выполняет двухсторонееразделение полосы пропускания вашего канала, исполь-зуя иерархически-структурированные классы. Каждыйкласс имеет свою собственную «очередь» и присвоен-ную ей способность пропускания. Класс-потомок можетзаимствовать у родительского класса только(!) ту про-пускную способность, которая в данный момент доступ-на для него.

! PRIQ (Priority Queueing) – очереди просто присоедине-ны к интерфейсу и не могут иметь очередей-потомков.Каждая такая очередь имеет свой уникальный «приори-тет», который может принимать значения от 0 до 15.

Пакеты в очереди с наибольшим приоритетом будут об-работаны первыми.

! HFSC (Hierarchical Fair Service Curve) – описание оченьсхоже с CBQ за исключением некоторых дополнений.HFSC есть не что иное как «исправленный» механизм,базирующийся на модели QoS. Его уникальность состо-ит в возможности разъединять связь между задержкойпакета и очередью. То есть HFSC обрабатывает очере-ди и пакеты отдельно друг от друга, однако после про-цесса обработки пакет и очередь опять логически свя-зываются. В некоторых ситуациях это позволяет добить-ся максимальной производительности от трафик-шей-пера. Очень часто это используется для сервисов, ра-ботающих в режиме реального времени.

Активизировать возможность распределения по очере-дям нужно в конфигурационном файле вашего фильтра (поумолчанию /etc/pf.conf) при помощи директивы «altq on»,которая имеет свои дополнительные параметры:! <interface> – имя интерфейса, для которого мы включа-

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

! <scheduler> – планировщик, в данный момент PF под-держивает cbq, priq, hfsc.

! bandwidth <value> – максимальный битрейт для всех оче-редей на данном интерфейсе. Значение может быть оп-ределено как процент от общей пропускной способнос-ти интерфейса, так и числовой величиной. Для этогомогут использоваться слова b, Kb, Mb, Gb. Что соответ-ственно – биты, килобиты, мегабиты, гигабиты. Еслизначение bandwidth не задано, то будет использованамаксимальная скорость.

! qlimit <value> – количество пакетов, которое может об-служивать очередь, по умолчанию 50, это значение от-лично подходит для 100-мегабтиных сетей.

! queue <list> – определяет список очередей, которые бу-дут созданы для данного интерфейса.

В этом примере интерфейс dc0 будет распределять вочереди 5Mbit/s, используя CBQ.

После включения altq мы можем создавать очереди-по-томки. Для них используются те же дополнительные пара-метры, что и для директивы altq, за исключением <scheduler>и queue, т.к они уже определены. Имя родительской очере-ди должно совпадать с определением в altq.

Например:

Для <scheduler> есть список параметров, которые по-могают контролировать работу очереди.! default – попадая в эту очередь, пакет не проверяется

дальше, а тут же обрабатывается.! red – Random Early Detection – RED отбрасывает паке-

ты, которые, предположительно могут перегрузить оче-редь.

pass in on $ext_if inet proto tcp from any to ↵↵↵↵↵any port 80 keep state queue www-1

pass in on $ext_if inet proto tcp from any to ↵↵↵↵↵any port 80 keep state queue www-2

altq on dc0 cbq bandwidth 5Mb queue { std, http, mail, ssh }

queue std bandwidth 10% cbq(default)

Page 34: 025 Системный Администратор 12 2004

32

администрирование

! ecn – Explicit Congestion Notification – практически то жесамое, что и RED. Отличается лишь алгоритмом обра-ботки очередей, в итоге результат тот же, что и при ис-пользовании RED. RED использует более оптимизиро-ванный алгоритм, и за его счет обработка очередей про-исходит гораздо быстрее.

Для CBQ предусмотрены дополнительные параметры.! borrow – очередь-потомок может «заимствовать» сво-

бодную пропускную способность у родительской очере-ди в случае необходимости.

Теперь параметры для HFSC.! realtime <sc> – минимальная доступная пропускная спо-

собность для очереди.! upperlimit <sc> – максимальная доступная очереди про-

пускная способность.! <sc> – список так называемых service curve (для realtime

задач), которые имеют формат (m1, d, m2), работаютони по принципу «для первых d мили-секунд выдаватьпропускную способность m1, после этого m2».

Синтаксис определения очередей CBQ и HFSC одина-ков, разница лишь в дополнительных параметрах (см. вы-ше). Однако стоит помнить, что скорость пропускания дляочередей-потомков не может быть больше той, что опреде-лена для родительской очереди.

Дополнительный параметр для определения очередей –priority <level> – указывает приоритет очереди. Для CBQ иHFSC значения могут быть от 0 до 7, для PRIQ – от 0 до 15.Значение по умолчанию для всех очередей 1.

Присвоение пакетов очередям происходит при помощиключевого слова queue в правилах фильтрации(!). В нор-мальном режиме указать можно только одну очередь, од-нако, если же указана вторая, то пакеты будут обрабаты-ваться на основе TOS (Type Of Service).

Что ж, теперь давайте посмотрим, как все это выглядитна практике, ибо в теории мало что понятно.

Включаем очереди:

Определяем родительские очереди и очереди-потом-ки.

И назначаем правила:

Итак, очередь std будет забирать 10% от нашего 5Mbit/sканала.

Очередь http будет забирать 60% и иметь двух потом-ков employees и developers с механизмом определенияпреждевременной нагрузки RED и возможностью «заим-ствования» полосы пропускания у родителя. У очереди httpприоритет равен 2, что в данной конфигурации являетсянаивысшим приоритетом (т.к значения больше, чем «2» неопределены). Значит, данная очередь будет обрабатыватьпакеты первой. Для очередей-потомков установлены ско-рости в процентном отношении соответственно 75% и 15%.Важно понимать, что вычисляться эти проценты будут изтого куска общей пропускной способности канала, которыйотдан родительской очереди.

Очередь mail определена как 10% от общей полосы про-пускания и имеет низший приоритет (0), чем другие.

Очередь ssh делится на ssh_interactive и ssh_bulk, име-ющие приоритеты 7 и 0. Как только появляется пакет с пор-том назначения 22 и его помещают в очередь ssh_bulk. Пос-ле того как соединение считается установленным, пакет пе-реходит в очередь ssh_interactive и имеет наивысшийприоритет для родительской очереди. А зачем так сложно?

Стоит помнить, что «контроль состояний» (stateful in-spection) применяется не только для фильтрации, но и дляконтроля полосы пропускания, а это означает, что даже приогромных правилах фильтров и различных ограничений ско-рости ваш сервер не будет иметь проблем с загрузкой про-цессора.

Роутинг (маршрутизация)Тут все просто и мощно. Управлять пакетом нам позволяютте же правила фильтрации, однако с добавлением однойиз нижеперечисленных опций. Помните – когда создается«состояние» (state), все пакеты для данного правила филь-трации и роутинга попадают под него.! fastroute – обычный режим, система обрабатывает па-

кет обычным образом.! route-to – система направляет пакет на нужный интер-

фейс с возможностью указания IP для «следующегохоста». Надо помнить, что помимо route-to нужно создатьправила, позволяющие направлять пакет с одного ин-терфейса на другой в правилах фильтрации, иначе всеваши пакеты будут зарезаны фильтром.

! reply-to – на сей раз система отвечает пакетом с ука-занным IP-адресом и интерфейсом.

! dup-to – создает дубликат пакета и отправляет его с по-мощью route-to. Настоящий пакет обрабатывается обыч-ным способом. Dup-to полезно использовать для обна-ружения конфликтов в сети, когда рабочий сервер тро-гать нельзя, а трафик, проходящий через него, нужноанализировать.

Комбинируя правила фильтрации и опции роутинга,можно добиться очень сложных схем маршрутизации, нодля таких целей придумали Cisco routers. А это уже совсемдругая история.

altq on dc0 cbq bandwidth 5Mb queue { std, http, mail, ssh }

queue std bandwidth 10% cbq(default)queue http bandwidth 60% priority 2 cbq(borrow red) ↵↵↵↵↵

{ employees, developers }queue developers bandwidth 75% cbq(borrow)queue employees bandwidth 15%queue mail bandwidth 10% priority 0 cbq(borrow ecn)queue ssh bandwidth 20% cbq(borrow) ↵↵↵↵↵

{ ssh_interactive, ssh_bulk }queue ssh_interactive priority 7queue ssh_bulk priority 0

block return out on dc0 inet all queue stdpass out on dc0 inet proto tcp from $developerhosts to ↵↵↵↵↵

any port 80 keep state queue developerspass out on dc0 inet proto tcp from $employeehosts to ↵↵↵↵↵

any port 80 keep state queue employeespass out on dc0 inet proto tcp from any to ↵↵↵↵↵

any port 22 keep state queue(ssh_bulk, ssh_interactive)pass out on dc0 inet proto tcp from any to ↵↵↵↵↵

any port 25 keep state queue mail

Page 35: 025 Системный Администратор 12 2004

33№12(25), декабрь 2004

bugtraq

Повышение привилегийв Symantec Windows LiveUpdateПрограмма: Norton AntiVirus 2001, Norton AntiVirus 2002,Norton Internet Security 2001, Norton Internet Security 2002,Norton Internet Security 2003, Norton Internet Security 2003Professional, Norton Internet Security 2004, Norton InternetSecurity 2004 Professional, Norton SystemWorks 2001, NortonSystemWorks 2002, Norton SystemWorks 2003, NortonSystemWorks 2004, Symantec AntiVirus for Handhelds 3.x,Symantec Norton AntiVirus 2003, Symantec Norton AntiVirus2004, Symantec Windows LiveUpdate 1.x, Symantec WindowsLiveUpdate 2.x.Опасность: Средняя.Описание: Обнаружена уязвимость в Symantec WindowsLiveUpdate. Локальный атакующий может повысить своипривилегии на системе.

Уязвимость существует из-за того, что Symantec AutomaticLiveUpdate позволяет управлять некоторыми интернет-оп-циями с системными привилегиями. Локальный атакующийможет использовать эту уязвимость во время сессииLiveUpdate посредством графического интерфейса при за-пущенной задаче «NetDetect».URL производителя: www.symantec.com.Решение: Установите обновления с сайта производителя.

Переполнение буфера в WINSПрограмма: Microsoft Windows 2000 Advanced Server,Microsoft Windows 2000 Datacenter Server, Microsoft Windows2000 Server, Microsoft Windows NT 4.0 Server, MicrosoftWindows NT 4.0 Server, Terminal Server Edition, MicrosoftWindows Server 2003 Datacenter Edition, Microsoft WindowsServer 2003 Enterprise Edition, Microsoft Windows Server 2003Standard Edition, Microsoft Windows Server 2003 Web Edition.Опасность: Высокая.Описание: Обнаружено переполнение буфера в службеWINS. Удаленный атакующий может выполнить произволь-ный код на уязвимой системе.

Уязвимость существует из-за некорректной проверки дли-ны буфера при обработке параметра Name в определенныхпакетах. Удаленный атакующий может с помощью специ-ально сформированного пакета вызвать переполнение бу-фера и выполнить произвольный код на уязвимой системе.URL производителя: www.microsoft.com.Решение: Установите обновления с сайта производителя.

Переполнение буферав Microsoft Windows NT DHCPПрограмма: Microsoft Windows NT.Опасность: Средняя.Описание: Обнаружено несколько уязвимостей в DHCP-службе в Microsoft Windows NT. Удаленный атакующий мо-жет вызвать отказ в обслуживании и скомпрометироватьуязвимую систему.1. Уязвимость существует из-за некорректной проверки

длины буфера при логировании некоторых значений оп-ределенных пакетов. Удаленный атакующий может спе-циальным образом сформировать DHCP-пакет и выз-вать отказ в обслуживании.

2. Уязвимость существует из-за некорректной проверки бу-фера при обработке DHCP-сообщений. Удаленный ата-кующий может послать специально сформированноеDHCP-сообщение, вызвать переполнение буфера и вы-полнить произвольный код на уязвимой системе.

URL производителя: www.microsoft.com.Решение: Установите обновления:1. Microsoft Windows NT Server 4.0 (requires Service Pack

6a): http://www.microsoft.com/downloa...F82D-F2A2-49AA-BF33-897498898EAD.

2. Microsoft Windows NT Server 4.0 Terminal Server Edition(requires Service Pack 6): http://www.microsoft.com/downloa...259F-3004-462C-B2A8-37F65EB78A2D.

Выполнение произвольных FTP-командв Microsoft Internet ExplorerПрограмма: Microsoft Internet Explorer 6.Опасность: Низкая.Описание: Обнаружена уязвимость в Microsoft InternetExplorer при обработке FTP-ссылок. Удаленный атакующийможет выполнить произвольную FTP-команду на уязвимойсистеме.

Удаленный атакующий может создать специально сфор-мированный FTP URL, который выполнит произвольнуюFTP-команду на определенном FTP-сервере. Командавставляется в URL и разделяется символами «%0a». При-мер:

URL производителя: www.microsoft.com.Решение: Решения не существует на данный момент.

ftp://ftpuser:ftppass@server/directory%0asomecommand%0a

Повышение привилегий в ядре LinuxПрограмма: Linux kernel версии до 2.4.23.Опасность: Низкая.Описание: Уязвимость обнаружена в ядре Linux на плат-формах AMD64 и Intel EM64T. Локальный атакующий мо-жет повысить свои привилегии на системе.

Уязвимость существует при установке TSS-лимитов. Ло-кальный атакующий может вызвать отказ в обслуживанииили выполнить произвольный код на уязвимой системе.URL производителя: www.kernel.org.Решение: Установите обновление от производителя.

Составил Александр Антипов

Выполнение произвольного кодав Cyrus IMAP ServerПрограмма: Cyrus IMAP Server 2.2.9 и более ранние версии.Опасность: Средняя.Описание: Обнаружена уязвимость в Cyrus IMAP Server.Удаленный атакующий может выполнить произвольный кодна уязвимой системе. Уязвимость обнаружена в функцииmysasl_canon_user(). Удаленный атакующий может вызватьпереполнение буфера и выполнит произвольный код насистеме с привилегиями IMAP-процесса.URL производителя: asg.web.cmu.edu/cyrus.Решение: Установите обновление: ftp://ftp.andrew.cmu.edu/pub/cyrus-mail.

Page 36: 025 Системный Администратор 12 2004

34

администрирование

В этой статье я рассмотрю один из вариантов запуска на-стоящего UNIX на современных компьютерах.

Я думаю, любой юниксоид хотя бы один раз читал исто-рию возникновения UNIX, как он развивался и какие мета-морфозы пережил, чтобы дойти до нас в виде множествасвоих «детей». Глядя на генеалогическое древо UNIX, дивудаешься, какое большое количество ответвлений и версийсистемы было выпущено в прошлом. Некоторые уже давноумерли, иные просто в спячке, но большинство из них вы-росли и дожили до наших дней. Ну как тут не загоретьсяжеланием посмотреть на тот самый настоящий, легендар-ный AT&T UNIX, с которого все и началось? Конечно, в нашидни достаточно затруднительно найти PDP11 и родной ди-стрибутив. Так что единственной возможностью погрузитьсяво времена использования настоящего UNIX на PDP11 нампомогут эмуляторы. Точнее, один из них – simh (SimulatorHistory). Начало данному проекту было положено в 1993году. Главный разработчик проекта – Robert M Supnik. Внастоящее время simh можно запустить почти на всех со-временных ОС, а именно:! OpenVMS/VAX! OpenVMS/Alpha! Windows 9x/2k/XP! MacOS X! Linux

Классический pdp 11/45 был выпущен в 1970 году. Изpdp-серии это был единственный 16-битный компьютер.Хотя были и 24- и 18-битные машины. При рекордно низкойцене (~ 10800$) pdp 11 получил широчайшее распростра-нение. Всего было продано около 600000 (!) экземпляров.Некоторые из них работают и по сей день.

Все свои эксперименты я проводил на P3-550 МГц/320 Мб RAM под управлением FreeBSD 5.3.

Для начала нашего путешествия во времени нам нужендистрибутив, который можно взять с http://simh.trailing-edge.com/sources/simhv33-0.zip.

Также понадобится дамп диска с установленным UNIX.Его мы берем с http://simh.trailing-edge.com/kits/uv7swve.zip.

Распакуем и установим программу:

Симулятор помещает все свои исполняемые файлы вкаталог BIN. Но так как по умолчанию он не существует,создаем его:

Если процесс компиляции прошел гладко, приступаемнепосредственно к запуску:

На экране появится приглашение программы.

Начинается загрузка:

Указываем, что именно запускать:

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

Далее нам показывают объем доступной памяти, онравен целым 177 856 байтам! После чего мы попадаем вshell. В принципе можно начинать работу с настоящим UNIX7-ой версии. По умолчанию мы попадаем в систему с пра-вами root. В документации к эмулятору в качестве примераработы были приведены следующие действия:

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

Идем дальше.

НАСТОЯЩИЙ UNIXВ НАШИ ДНИ

АЛЕКСАНДР БАЙРАК

# mkdir unixemul# cd unixemul# unzip ../simhv33-0.zip# unzip ../uv7swve.zip# mkdir BIN# gmake

# mkdir BIN# gmake

# BIN/pdp11

// Óêàçûâàåì, êàêîé òèï ïðîöåññîðà ìû áóäåì ýìóëèðîâàòü:sim> set cpu 18// u18 ñîîòâåòñòâóåò ïðîöåññîðó, óñòàíîâëåííîìó// íà êëàññè÷åñêîé pdp 11/45.// Óêàçûâàåì, ÷òî áóäåì èñïîëüçîâàòü êîíñîëüíûé òåðìèíàë// DL11. Âûâîä èíôîðìàöèè áóäåò ïðîèçâîäèòüñÿ â ðåæèìå// 7 áèò íà ñèìâîë.sim> set tto 7b// Óêàçûâàåì, ÷òî ââîä áóäåò òàêæå èñêëþ÷èòåëüíî 7-áèòíûé.sim> set tti 7b// Ïðèñîåäèíÿåì äàìï äèñêà ñ UNIX ê rl.  êà÷åñòâå rl// âûñòóïàåò êîíòðîëëåð äèñêà RLV12/RL01.sim> attach rl unix_v7_rl.dsk// Óêàçûâàåì, îòêóäà ïðîèçâîäèòü çàãðóçêó:sim> boot rl

: rl(0,0)rl2unix

@boot

New Boot, known devices are hp ht rk rl rp tm vt

// Ñîçäàäèì êàòàëîã dmr# mkdir /usr/dmr// Ñäåëàåì âëàäåëüöåì êàòàëîãà dmr ïîëüçîâàòåëÿ dmr# chown dmr /usr/dmr// Èçìåíèì ãðóïïó âëàäåíèÿ êàòàëîãà íà òðåòüþ# chgrp 3 /usr/dmr// Ñîçäàäèì êàòàëîã äëÿ âðåìåííûõ ôàéëîâ# mkdir /tmp// Ïîñòàâèì äëÿ íåãî ïîëíûé äîñòóï äëÿ âñåõ# chmod 777 /tmp// Íàæèìàåì <Ctrl+D># ^D

Restricted rights: Use, duplication, or disclosure is subject to restrictions

stated in your contract with Western Electric Company, Inc.

Thu Sep 22 05:51:05 EDT 1988

! Tru64! Solaris! HP-UX! *BSD! OS/2

Page 37: 025 Системный Администратор 12 2004

35№12(25), декабрь 2004

администрирование

Видим результат:

Кстати, вы еще не догадались, кому принадлежит имяпользователя dmr? Человеку – живой легенде современ-ности – Деннису Ритчи, отцу и основоположнику Юникса!

Согласитесь, что очень неудобно при каждом запускеОС каждый раз вводить все команды инициализации. Тутнам на помощь приходят команды save и restore. Для «со-хранения» ввода команд, необходимых для запуска ОС, намнужно набрать команду:

В качестве filename введите имя файла, в который выхотите сохранить текущий образ эмулятора.

Для «восстановления» состояния набираем:

После чего будут актуальны ранее введенные и сохра-ненные настройки.

Также следует отметить одну очень досадную недора-ботку по части удобства использования. В оболочке эмуля-тора нет возможности редактировать вводимые команды.

Про возможность автодополнения команд я вообщемолчу. Хотя должен заметить, можно использовать зара-нее определенные алиасы. Например, для команды attachсинонимом будет команда at. Более подробно про алиасыможно прочитать в документации.

Simh поддерживает работу через сеть. Например, у васнет возможности работать с ОС, запущенной через эмуля-тор, находясь непосредственно перед монитором компью-тера, на котором включен simh. Или вы хотите дать воз-можность своим знакомым или друзьям поэксперименти-ровать на запущенной через эмулятор ОС.

Воспользуемся опцией, определяющей консоль:

Назначаем доступ к консоли через порт 12345.На что эмулятор ответит:

Проверить, действительно ли нас ожидает соединение

// Ââîäèì ëîãèí dmr:login: dmr// Ñ ïîìîùüþ ðåäàêòîðà ed íà÷èíàåì ðåäàêòèðîâàòü ôàéë hello.c:$ ed hello.c?hello.camain(){printf(«Hello World!\n»);}.w40q// Ñêîìïèëèðóåì íàïèñàííûé íàìè ôàéë:$ cc hello.c// Çàïóñòèì:$ a.out

Hello World!

на указанном порту, мы можем с помощью команд netstat -na или sockstat -4.

Работать по сети мы сможем после ввода на локальноймашине параметров, указывающих, откуда нам запускатьОС. В нашем случае это boot rl. После вывода которой мывидим на экране:

После чего мы можем получить доступ к эмулятору че-рез telnet. Пример сессии:

Я не буду описывать здесь все свои эксперименты ко-торые проводил в UNIX, чтобы не лишать читателя удоволь-ствия самому заняться исследованием этой ОС. А мореразличных открытий и удивительных находок я вам обещаю.

Для корректного завершения работы с UNIX надо двараза произвести синхронизацию диска с помощью коман-ды sync. После чего нажать <Ctrl+E>, и вы снова попадетев оболочку эмулятора. Выход из которой осуществляется спомощью команд exit, quit, bye, на выбор.

В конце хотел бы добавить, что рассмотренный эмуля-тор кроме PDP11 поддерживает еще достаточно большоеколичество различных компьютеров:! Data General Nova, Eclipse! Digital Equipment Corporation PDP-1, PDP-4, PDP-7, PDP-8,

PDP-9, PDP-10, PDP-11, PDP-15, VAX! GRI Corporation GRI-909! IBM 1401, 1620, 1130, System 3! Interdata (Perkin-Elmer) 16b and 32b systems! Hewlett-Packard 2116, 2100, 21MX! Honeywell H316/H516! MITS Altair 8800, with both 8080 and Z80! Royal-Mcbee LGP-30, LGP-21! Scientific Data Systems SDS 940

Соответственно, если мы найдем ОС для данных компь-ютеров и приложим немного смекалки и настойчивости, по-лучим в собственное распоряжение целый полигон для изу-чения истории компьютеров и ОС. Особый интерес (по край-ней мере для меня) представляет эмуляция VAX. Особеннопри учете того, что на VAX можно запустить OpenBSD,NetBSD, и другие менее известные в настоящее время ОС.Но этому вопросу я намерен посвятить отдельную статью.

Я был бы очень рад всем вашим отзывам c описаниемэкспериментов, поставленных с помощью этого эмулятора.

Ссылки:1. http://simh.trailing-edge.com/software.html – небольшая

коллекция программ и ОС, подходящих для использо-вания под эмулятором simh.

2. http://simh.trailing-edge.com/photos.html – фотогалереяразличных старых компьютеров.

3. http://www.cs.bell-labs.com/who/dmr – домашняя странич-ка Денниса Ритчи.

sim> save filename

sim> restore filename

sim> set console telnet=12345

Listening on port 12345.

Waiting for console Telnet connection.

[01mer@darkthrone]:~> telnet marduk 12345

Trying 192.168.1.22

Connected to marduk

Escape charset is ‘^]’

Connected to PDP11 simulator

@

Page 38: 025 Системный Администратор 12 2004

36

администрирование

Любой системный администратор, если он в меру ленив,рано или поздно берется за автоматизацию своей работы.Сначала вместо длинных команд со множеством ключей по-являются псевдонимы (aliases), потом группы команд объе-диняются в пакетные файлы командной оболочки, затемна арену выходят сценарии на более функциональных язы-ках типа Perl… И все для того, чтобы сократить количество«кликов» и по возможности переложить часть работы напользователей, которые эти операции и должны бы делать«по идее», но «по факту» научить их находить нужный файлв дереве каталогов, упаковывать его и отправлять по на-значению оказывается на порядок сложнее, чем делать этосамому.

Об использовании Python для выполнения тех или иныхопераций на UNIX-серверах написано достаточно много. Вданной же статье я хочу показать применение этого языкадля решения «бытовых» задач в среде Windows. В качествепримера (которым возможности Python никоим образом неограничиваются) разработаем приложение, автоматизирую-щее отправку данных и получение обновлений по FTP, ис-пользуя заранее настроенные пути и имена файлов.

Попытаемся сделать наше приложение максимальноуниверсальным, однако будем иметь в виду конкретнуюцель – нужно организовать обмен данными с удаленной кас-сой (ежедневно сбрасывать на сервер файлы реестров ивремя от времени получать с сервера обновленную базу

абонентов). Все задачи условно разделим на пользователь-ские (например, инициирование отправки) и администра-торские (например, первичная настройка). Первые из нихтребуется разработать максимально удобно, предоставивпростейший интерфейс и лишив пользователя возможнос-ти ошибаться. Задачи второй категории по традиции ре-шим достаточно упрощенно – главное, чтобы все работалопри минимуме телодвижений.

Первым делом скачаем с http://python.org дистрибутивPython для Windows. Его инсталляция никаких вопросоввызвать не должна. На момент написания статьи у менябыла установлена версия Python 2.3.4. Входящая в составпакета среда разработки IDLE (рис. 1) предоставляет неко-торые удобства, но для меня как-то уже устоялся стиль раз-работки, когда код вбивается в обычный текстовый файл,и затем исполняется командой типа:

Можно, конечно, в командной строке набрать простоtest.py – в процессе инсталляции в Windows расширение«.py» ассоциируется с интерпретатором python.exe, и по-добная команда тоже выполнит код. Однако на стадии от-ладки это не совсем удобно – для потоков stdout и stderr вэтом случае создается новое консольное окно, которое зак-рывается сразу же после завершения (в том числе и ава-

АВТОМАТИЗИРУЕМ FTP С ПОМОЩЬЮ PYTHON

СЕРГЕЙ СУПРУНОВ

C:\myworks\python\test>python test.py

Page 39: 025 Системный Администратор 12 2004

37№12(25), декабрь 2004

администрирование

рийного) работы сценария, не позволяя ознакомиться с со-общениями об ошибке.

Знакомство с PythonПодробно останавливаться на основах языка я не буду. Дан-ный раздел имеет целью коротко пояснить, что и как, длятех, кто ранее с Python не сталкивался, но статью прочи-тать непременно хочет. И сразу, как говорится, – с места вкарьер:

Результат работы этого сценария будет следующим:

(0) – первая строка указывает интерпретатору, в какойкодировке следует рассматривать приведенный ниже текст.Для ASCII-текста она не требуется, но поскольку мы исполь-зуем кириллицу, то без нее интерпретатор будет каждыйраз выдавать предупреждение «DeprecationWarining: Non-ASCII character…».

(1, b) – комментарии, как и принято в UNIX, предваря-ются символом «#». Для многострочных комментариев ча-сто используют обрамление текста с помощью утроенныхкавычек: «’’’ multiline comment ’’’». Этот же прием можно ис-пользовать для временного исключения участков кода настадии отладки.

(2) – третья строка импортирует модуль, в данном слу-чае «os», который является стандартным для Python и со-держит функции для работы с конкретной операционнойсистемой. В нашем примере из этого модуля мы использу-ем функцию getcwd(), возвращающую текущий каталог.

(3) – с этой строки начинается определение функции«hello». В скобках указывается список параметров, причемдаже если параметров нет, скобки обязательно должныбыть. Двоеточие начинает блок кода, содержащий телофункции. В отличие от таких языков, как C или Perl, в Pythonблок операторов (определения функций, циклы, ветвления)не обрамляется операторными скобками, а выделяется от-

ступом. Отступ может быть выполнен любым количествомсимволов «пробел», но все операторы блока должны иметьодинаковый отступ. Первая же строка, выполненная безотступа, рассматривается как окончание блока операторов.

Здесь хочется сделать отступление и немного пофило-софствовать о стиле программирования. Тот же Perl позво-ляет кодировать как угодно – хоть в одну строку. С однойстороны, каждый программист со временем вырабатываеттот стиль, который ему более удобен. При переходе на Perlс других языков можно перенести и устоявшийся стиль на-писания кода. Но с другой стороны тут есть и вероятность,что кто-то другой будет очень долго воспроизводить «не-ASCII»-звуки, пытаясь разобраться в исходниках програм-мы, написанной как-нибудь экзотически. Язык Python в этомсмысле более требователен к разработчику, унифицируятем самым стиль кодирования и упрощая работу тем, комупридется работать с этим кодом в будущем. Однако про-должим…

(4, 5) – оператор «print» выводит на экран значение стро-ковой переменной или непосредственно строку, заключен-ную в кавычки или апострофы. Вставка в строку перемен-ных выполняется в стиле оператора printf языка Си, за темисключением, что список интегрируемых переменных за-дается после символа «%» как кортеж (то есть через запя-тую и в круглых скобках). Если переменная одна, как в на-шем случае, скобки можно опустить.

(6) – пустые строки, естественно, допускаются.(7, a) – оператор ветвления пояснять, думаю, не нужно.

Как и обычно, задаются условие и блок операторов (выде-ляется отступом), которые будут выполнены, если условиеистинно. В противном случае, если задан далее оператор«else», будет выполнен его блок операторов. Если командав блоке одна, допускается указывать ее непосредственнопосле двоеточия в этой же строке (хотя это и противоречитофициальному стилю программирования). Оператор «pass»ничего не делает, и строго говоря, строка «a» в нашем слу-чае совершенно не нужна.

Чуть подробнее следует остановиться на самом усло-вии, указанном в строке (7): __name__ == ‘__main__’. Встро-енная переменная __name__ возвращает имя программы,если вызывается как модуль из другого сценария (об этом– чуть ниже) либо строку «__main__», если файл запуска-ется непосредственно. То есть код строк «8-9» будет вы-полнен только тогда, когда файл first.py запускается из ко-мандной строки. Зачем это сделано, будет объяснено да-лее.

(8) – здесь мы просто вызываем описанную ранее фун-кцию «hello», передав ей текстовую строку в качестве аргу-мента.

(9) – функция raw_input считывает со стандартного по-тока ввода stdin строку, завершающуюся символом пере-вода строки. В данном случае этот оператор используетсяисключительно для задержки вывода, чтобы консольноеокно не закрывалось сразу.

Теперь рассмотрим еще одну концепцию Python – по-вторное использование кода. Конечно, это позволяет де-лать любой язык программирования, но в Python повтор-ное использование положено в основу синтаксиса, и всеполучается очень легко и естественно.

(0) # -*- coding: cp866 -*-(1) #----------------------------- first.py(2) import os(3) def hello(message):(4) print message(5) print 'Âû íàõîäèòåñü â %s.' % os.getcwd()(6)(7) if __name__ == '__main__':(8) hello('Hello from Python.')(9) raw_input('Íàæìèòå Enter...')(a) else: pass(b) #----------------------------end of first.py

C:\myworks\python\test>python test.py

Hello from Python.

Вы находитесь в C:\myworks\python\test.

Нажмите Enter...

Ðèñóíîê 1

Page 40: 025 Системный Администратор 12 2004

38

администрирование

Для примера напишем еще один сценарий:

Запустив его, мы получим такой вывод:

То есть мы подключили нашу первую программу как мо-дуль и получили возможность использовать определенныев ней функции. Код вне функций (в нашем случае это стро-ки «0, 1, 6-b») выполняется в момент импорта. Именно длятого, чтобы избежать какой-либо активности нашего пер-вого сценария во время его импортирования, мы и ввелипроверку имени __name__, чтобы определить, подключа-ется наш сценарий к другому или запускается автономно.

Говоря об импорте, следует указать еще на один син-таксис подключения: «from first import hello». Эта командаимпортирует из first.py только функцию hello. Через запя-тую можно перечислить и несколько импортируемых функ-ций. Команда «from first import * » импортирует в текущийсценарий все функции, найденные в first.py. Отличие этогосинтаксиса от использованного в second.py заключается втом, что имена функций включаются в пространство именимпортирующего сценария, и поэтому подгруженные фун-кции должны вызываться без указания модуля:

Ну и для полноты картины – несколько слов о библиоте-ке графических объектов Tkinter. Основанная на Tk/Tcl, онапозволяет достаточно просто наделять сценарии графичес-ким интерфейсом:

В строке «1» импортируем все из модуля Tkinter. Далеепоследовательность действий такова: объявляем окноwindow верхнего уровня (3); задаем ему текст заголовка (4);описываем и упаковываем текстовую метку (5-7); анало-гично поступаем с кнопкой (8-a) и, наконец, в строке «b»запускаем на выполнение цикл окна.

Синтаксис описания различных элементов во многомодинаков – первым параметром задается родительскийэлемент (в данном случае окно верхнего уровня), к кото-рому прикрепляется данный элемент. Далее перечисля-ются другие параметры: «text» для задания отображаемо-го текста, «command» определяет обработчик обратноговызова, который будет исполнен при выборе данного эле-мента (в данном примере при нажатии на кнопку главноеокно будет закрыто). Параметры можно задавать и с помо-

щью метода «config» графического объекта, как показа-но в строке «6».

Любой объект должен быть размещен одним из менед-жеров размещения (в данном примере используем наибо-лее простой из них – pack). То есть для каждого объектатребуется вызвать метод pack(), который поместит его вконкретном месте окна. С помощью дополнительных пара-метров можно управлять упаковкой, например, указывать,к какой стороне окна требуется прикрепить элемент (пара-метр side), следует ли растягивать элемент при измененииразмеров окна (expand), должен ли элемент заполнять всеотведенное ему пространство в указанном направлении (fill).Самый лучший способ познакомиться с особенностями упа-ковки – на практике попробовать различные варианты.

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

Обратите внимание на символ «u» перед текстовымистроками. Этот хитрый оператор заставляет Python преоб-разовывать следующую далее текстовую строку в кодиров-ку Unicode. Базовая кодировка должна быть задана так, какпоказано в строке «0». В версиях Python до 2.3 этот синтак-сис не действует, и там требуется явно задавать функциюпреобразования unicode().

Еще одно замечание – внутри скобок допускается пе-ренос строки и произвольный отступ перенесенной части,как это продемонстрировано в строках «8-9».

В результате с помощью этих нескольких строк мы по-лучим полнофункциональное окно, изображенное на рис. 2.Для первого знакомства, думаю, этого достаточно. Еще не-которые нюансы мы рассмотрим в дальнейшем.

Модуль для архивирования myzipПоскольку передавать по сети файлы в запакованном виденамного приятнее, особенно когда речь идет о коммутиру-емой линии, то заготовим несколько функций для работы сzip-файлами. Чтобы иметь возможность использовать этифункции и в других приложениях, поместим их в отдель-ный файл:

(0) import first(1) first.hello('Hi')

C:\myworks\python\test>python test.py

Hi.

Вы находитесь в C:\myworks\python\test.

(0) from first import hello(1) hello('Hi')

(0) # -*- coding: cp866 -*-(1) from Tkinter import *(2)(3) window = Tk()(4) window.title(u'Ïðîñòîå ãðàôè÷åñêîå îêíî')(5) label = Label(window, text = u' ↵↵↵↵↵

Ïðîñòàÿ òåêñòîâàÿ ìåòêà')(6) label.config(fg = 'blue', ↵↵↵↵↵

font = ('Georgia', 14, 'italic'))(7) label.pack()(8) button = Button(window, text = u'Çàêðûòü', ↵↵↵↵↵

command = window.quit)(a) button.pack(expand=YES, fill=X)(b) window.mainloop()

Ðèñóíîê 2

# -*- coding: cp866 -*-#--------------------------------------------------------## myzip.py: ìîäóëü ðàáîòû ñ zip-àðõèâàìè##--------------------------------------------------------# Ìîäóëü äëÿ ðàáîòû ñ zip-àðõèâàìèfrom zipfile import *# Èìïîðòèðóåòñÿ ôóíêöèÿ glob äëÿ îáõîäà êàòàëîãîâfrom glob import glob# Åñëè íå íîëü � âûâîäèòü ñîîáùåíèÿ íà ýêðàí

Page 41: 025 Системный Администратор 12 2004

39№12(25), декабрь 2004

администрирование

В основе данного сценария лежит стандартный модульzipfile. Он предоставляет довольно развитые средства дляработы с архивами, но его непосредственное использова-ние потребует каждый раз писать один и тот же код обвяз-ки. Поэтому мы и создаем собственный модуль, в которомопишем нужные нам функции на более высоком уровне.

Класс ZipFile модуля zipfile позволяет работать с архи-вом, почти как с обычным файлом – читать из него, записы-вать и т. д. Фигурирующий здесь параметр ZIP_DEFLATEDопределяет метод компрессии.

В дальнейшем нам понадобятся отсюда: функция read-allzip, которая будет извлекать в текущую папку все файлыиз скачанного архива, и writepattzip, которая будет упако-вывать в архив все файлы из текущего каталога. Функциисоответствуют шаблону.

Из интересного отметим здесь, что шаблоны передают-ся в виде кортежа, то есть этот параметр должен выгля-деть примерно так: «(‘*.db’, ‘*.px’)». Также обратите внима-ние на синтаксис цикла «for»: он перебирает все значенияиз списка, заданного после ключевого слова «in».

Модуль работы с FTP myftpАналогично в отдельный файл вынесем и функции работыпо протоколу FTP. Здесь нам требуется две функции – от-правка одного файла по заданному пути и чтение одногофайла. Возможность загрузки или отправки сразу несколь-ких файлов реализовывать не будем: поскольку в основенашего приложения будет лежать работа с архивами, тоцелесообразно упаковывать все передаваемое или прини-маемое в один файл. Код модуля представлен ниже:

# -*- coding: cp866 -*-#--------------------------------------------------------## myftp.py: ìîäóëü ðàáîòû ñ FTP##--------------------------------------------------------# Èìïîðò íóæíûõ ôóíêöèéimport osfrom ftplib import FTPfrom myzip import *VERBOSE = 1# Ñêà÷èâàíèå ôàéëà ïî FTP:# ïåðåäàþòñÿ ñëåäóþùèå ïàðàìåòðû:# fromdir � ïàïêà-èñòî÷íèê íà FTP-ñåðâåðå# file � èìÿ ñêà÷èâàåìîãî ôàéëà# (fromsite, ftpuser, ftppassword) � FTP-ñåðâåð# è ëîãèí/ïàðîëü äëÿ âõîäà# todir - ëîêàëüíàÿ ïàïêà äëÿ ñîõðàíåíèÿ ñêà÷àííîãî ôàéëà#def getftp(fromdir, file, (fromsite, ftpuser, ↵↵↵↵↵

ftppassword), todir):olddir = os.getcwd() # çàïîìèíàåòñÿ òåêóùèé êàòàëîãos.chdir(todir) # ïåðåõîä â ïàïêó íàçíà÷åíèÿif VERBOSE:

print 'myftp: Óñòàíàâëèâàåòñÿ ñîåäèíåíèå ñ ↵↵↵↵↵%s...' % fromsite

try:localfile = open(file, 'wb')connection = FTP(fromsite)connection.login(ftpuser, ftppassword)connection.cwd(fromdir)

except:print 'myftp: ÎØÈÁÊÀ ÑÎÅÄÈÍÅÍÈß Ñ %s!' % fromsitereturn(-1)

if VERBOSE: print 'myftp: Ñîåäèíåíèå ñ %s óñòàíîâëåíî.' ↵↵↵↵↵

% fromsiteif VERBOSE:

print 'myftp: Âûïîëíÿåòñÿ çàãðóçêà %s...' % filetry:

connection.retrbinary('RETR ' + ↵↵↵↵↵file, localfile.write, 1024)

connection.quit()localfile.close()

except:print 'myftp: ÎØÈÁÊÀ ÏÎËÓ×ÅÍÈß ÔÀÉËÀ %s' % filereturn(-2)

if VERBOSE: print 'myftp: Çàãðóçêà ôàéëà %s çàâåðøåíà.' % file

# èñïîëüçóåì try, ïîñêîëüêó ñêà÷àííûé ôàéë ìîæåò# îêàçàòüñÿ íå zip-àðõèâîì. Õîòÿ ýòî ìîæíî áûëî# áû ïðîâåðèòü è ÿâíî:try:

readallzip(file)except:

print 'myftp: %s íå ÿâëÿåòñÿ àðõèâîì, ïîìåùåí ↵↵↵↵↵êàê åñòü.' % file

os.chdir(olddir) # âîçâðàùàåìñÿ â ïðåæíèé êàòàëîã# Çàãðóçêà ôàéëà ïî FTP íà ñåðâåð:# ïåðåäàþòñÿ ñëåäóþùèå ïàðàìåòðû:# fromdir � ëîêàëüíàÿ ïàïêà-èñòî÷íèê# file � èìÿ îòïðàâëÿåìîãî zip-ôàéëà# pattern � ñïèñîê øàáëîíîâ äëÿ îòïðàâêè# (fromsite, ftpuser, ftppassword) � FTP-ñåðâåð# è ëîãèí/ïàðîëü äëÿ âõîäà# todir � ïàïêà íà FTP-ñåðâåðå äëÿ çàãðóçêè ôàéëà

VERBOSE = 1# Î÷èñòêà àðõèâà îò èìåþùèõñÿ â íåì ôàéëîâ:# àðõèâ îòêðûâàåòñÿ íà çàïèñü è ñðàçó çàêðûâàåòñÿdef clearzip(zipname):

if VERBOSE: print 'myzip: Î÷èñòêà àðõèâà %s.' % zipname

zip = ZipFile(zipname, 'w', ZIP_DEFLATED)zip.close

# Ôóíêöèÿ çàïèñè ôàéëà â àðõèâ:# óêàçàííûé ôàéë äîáàâëÿåòñÿ ê ñóùåñòâóþùèìdef writezip(zipname, filename):

if VERBOSE: print 'myzip: Óïàêîâûâàåòñÿ %s â %s.' ↵↵↵↵↵

% (filename, zipname)zip = ZipFile(zipname, 'a', ZIP_DEFLATED)zip.write(filename)zip.close

# Çàïèñü â àðõèâ âñåõ ôàéëîâ èç êàòàëîãà, óäîâëåòâîðÿþùèõ# øàáëîíódef writepattzip(zipname, patterns):

if VERBOSE: print 'myzip: Ñîçäàåòñÿ àðõèâ %s...' % zipname

clearzip(zipname)for pattern in patterns:

filelist = glob(pattern)for filename in filelist:

writezip(zipname, filename)if VERBOSE:

print 'myzip: Àðõèâ ñîçäàí.'# Èçâëå÷åíèå ôàéëà èç àðõèâàdef readzip(zipname, filename):

if VERBOSE: print 'myzip: Èçâëåêàåòñÿ %s èç %s.' ↵↵↵↵↵

% (filename, zipname)zip = ZipFile(zipname, 'r', ZIP_DEFLATED)open(filename, 'wb').write(zip.read(filename))zip.close

# Èçâëå÷åíèå âñåõ ôàéëîâ èç àðõèâàdef readallzip(zipname):

if VERBOSE: print 'myzip: ×èòàåòñÿ àðõèâ %s...' % zipname

zip = ZipFile(zipname, 'r', ZIP_DEFLATED)for filename in zip.namelist():

readzip(zipname, filename)zip.closeif VERBOSE:

print 'myzip: Àðõèâ ïðî÷òåí.'

# Åñëè çàïóñêàåòñÿ èç êîìàíäíîé ñòðîêè, òî ìîæíî# ÷òî-òî ñäåëàòüif __name__ == '__main__': print 'Òîëüêî êàê ìîäóëü.'

Page 42: 025 Системный Администратор 12 2004

40

администрирование

Здесь следует обратить внимание на то, что файлы сле-дует открывать в бинарном режиме (используем парамет-ры «rb» и «wb»), чтобы они не пострадали в результате ин-терпретации Python символов конца строки.

Всю черную работу в этом сценарии выполняет стан-дартный модуль ftplib, а конкретно – его класс FTP, кото-рый отвечает за методы установления соединения, обес-печивает работу протокола FTP и т. д.

Потенциально опасные операции, которые могут выз-вать ошибку (например, FTP-сервер может быть недосту-пен), заключены в оператор «try – except». Он в свою оче-редь перехватывает ошибку и не позволяет нашему прило-жению «обрушиться» со страшными для пользователя ру-гательствами.

Файл конфигурации config.pyКонечно, нужные нам переменные, такие как URL FTP-сер-вера, имя и пароль пользователя, и прочее, можно задатьнепосредственно в главном модуле нашего приложения, нонесколько удобнее представляется вынос этих описаний вотдельный файл. Чтобы не связываться с разбором кон-фигурационного файла и не изобретать ему какой-то фор-мат, будем использовать в его качестве обычный сценарийPython, в котором определяются соответствующие перемен-ные. Затем, будучи импортирован в главный сценарий, онпредоставит свои переменные другим функциям. В концеконцов это уже относится к «административным» функци-ям, а мы условились не тратить много усилий на красоту вданном случае.

Наиболее важными здесь являются список FTP-серве-ров и список операций. Код в начале сценария, помечен-ный как «предвычисляемый», нужен для динамическогоопределения значения некоторых переменных, подставля-емых в списки. В нашем примере в нем вычисляется значе-ние переменной srcdir, которая задает папку-источник дан-ных, используемую в операции 1 («Отправить реестры»). Вкачестве источника должна использоваться папка с име-нем вида Pay_NN, где NN – двузначное число, с наиболь-шим значением NN. Для того чтобы определить эту папкуна данный момент, и нужен этот «предвычисляемый» код.

Список FTP-серверов задается как список кортежей,каждый из которых содержит адрес сервера, имя и парольпользователя для доступа на этот сервер. В дальнейшемобращение к данным по тому или иному серверу выполня-ется по порядковому номеру записи (начиная с нуля). На-пример, имя пользователя, которое должно использовать-ся для доступа на ftp.freebsd.org, можно будет получить так:«ftpservers[1][1]».

Аналогично задается список операций. Назначения по-лей приведены в комментарии. Номер операции здесь ука-зываем явно – так будет удобнее в дальнейшем. Второеполе задает саму операцию – получение данных (get) илиотправка (put).

Конечно, формат нашего конфигурационного файласпособен напугать кого угодно, однако пользователям непридется с ним работать, а администратор как-нибудь раз-берется.

Главный сценарий manager.pyТеперь попытаемся объединить все это в законченное при-ложение:

#def putftp(fromdir, zipfile, pattern, (tosite, ↵↵↵↵↵

ftpuser, ftppassword), todir):olddir = os.getcwd()os.chdir(fromdir)if VERBOSE:

print 'myftp: Ïîäãîòîâêà ôàéëîâ ê îòïðàâêå...'writepattzip(zipfile, pattern)if VERBOSE:

print 'myftp: Ôàéëû óïàêîâàíû â %s.' % zipfileprint 'myftp: Óñòàíàâëèâàåòñÿ ñîåäèíåíèå ↵↵↵↵↵

ñ %s...' % tositetry:

localfile = open(zipfile, 'rb')connection = FTP(tosite)connection.login(ftpuser, ftppassword)connection.cwd(todir)

except:print 'myftp: ÎØÈÁÊÀ ÑÎÅÄÈÍÅÍÈß Ñ %s' % tositereturn(-2)

if VERBOSE: print 'myftp: Ñîåäèíåíèå ñ %s óñòàíîâëåíî' % tosite

print 'myftp: Âûïîëíÿåòñÿ îòïðàâêà ôàéëà ↵↵↵↵↵%s...' % zipfile

try:connection.storbinary('STOR ' + zipfile, ↵↵↵↵↵

localfile, 1024)connection.quit()localfile.close()

except:print 'myftp: ÎØÈÁÊÀ ÎÒÏÐÀÂÊÈ ÔÀÉËÀ %s!' % zipfilereturn(-2)

if VERBOSE: print 'myftp: Ôàéë %s îòïðàâëåí.' % zipfile

os.chdir(olddir)

# -*- coding: cp866 -*-#------------------------------------------------------# ïðåäâû÷èñëÿåìûé êîä:import os

from glob import globolddir = os.getcwd()root = 'data/'os.chdir(root)list = glob('Pay_*')list.sort()srcdir = root + list[-1] # ïîñëåäíèé ýëåìåíò ñïèñêàos.chdir(olddir)# print 'config: Òåêóùèé êàòàëîã îòïðàâêè � %s' % srcdir#-----------------------------------------------------# Ñïèñîê FTP-ñåðâåðîâ. Ôîðìàò çàïèñè:# (FTP-ñåðâåð, ëîãèí, ïàðîëü)ftpservers = [('ftp.my.server.ru', 'user', 'password'),('ftp.freebsd.org', 'ftp', '[email protected]'),]#-----------------------------------------------------# Ñïèñîê îïåðàöèé. ôîðìàò çàïèñè:# (íîìåð, òèï îïåðàöèè, íàçâàíèå îïåðàöèè, íîìåð FTP-ñåðâåðà,# ïàïêà-èñòî÷íèê, èìÿ àðõèâà, øàáëîí, ïàïêà íàçíà÷åíèÿ)operations = [(0, 'get', u'Îáíîâèòü äàííûå', 0, 'downdata', ↵↵↵↵↵

'basa.zip', ('*',), 'data'),(1, 'put', u'Îòïðàâèòü ðååñòðû', 0, srcdir, ↵↵↵↵↵

'reestr.zip', ('*.db', '*.px',), 'updata'),(2, 'get', u'Îáíîâèòü ïðîãðàììó', 0, 'ftpman', ↵↵↵↵↵

'ftpman.zip', ('*',), 'bin'),(3, 'get', u'Ïîëó÷èòü README.TXT', 1, ↵↵↵↵↵

'pub/FreeBSD', 'README.TXT', ('*',), '.'),]

# -*- coding: cp866 -*-from Tkinter import *from myftp import getftp, putftp

Page 43: 025 Системный Администратор 12 2004

41№12(25), декабрь 2004

администрирование

VERBOSE = 1if VERBOSE: print '================> manager.py çàïóùåí.'# Ñëóæåáíî-äåêîðàòèâíàÿ ôóíêöèÿ. Íóæíà, ÷òîáû ìåíÿòü òåêñò# ìåòêè â çàâèñèìîñòè îò ñîñòîÿíèÿdef chStat(messvar, color, btn, btnrelief):

# èçìåíÿåì ãðàíèöó êíîïêè òàê, ÷òîáû â ìîìåíò# âûïîëíåíèÿ îïåðàöèè îíà âûãëÿäåëà âäàâëåííîé �# èñêëþ÷èòåëüíî «äåêîðàòèâíûé» ýôôåêòbtn.config(relief = btnrelief)# ìåíÿåì òåêñò ìåòêèstatus.config(text = messvar)# ìåíÿåì öâåò ìåòêèstatus.config(fg = color)# ïåðåðèñîâûâàåì ìåòêóstatus.update()

# Ôóíêöèÿ ïîëó÷åíèÿ äàííûõ. Íàçíà÷àåòñÿ êàê îáðàáîò÷èê# êíîïêàì îïåðàöèé òèïà 'get'def get(nr):

if VERBOSE: print '================> âûïîëíÿåòñÿ ↵↵↵↵↵çàãðóçêà...'

# âûáèðàåì íóæíûé êîðòåæop = config.operations[nr]# âû÷èñëÿåì èìÿ êíîïêè ïî íîìåðóexec 'obj = btn%d' % op[0]# âûáèðàåì äàííûå ïî FTP-ñåðâåðóftpsite = config.ftpservers[op[3]]msg = u'Ïîäîæäèòå: âûïîëíÿåòñÿ çàãðóçêà...'chStat(msg, '#AA0000', obj, 'sunken')err = getftp(op[4], op[5], ftpsite, op[7])if err:

msg = u'ÎØÈÁÊÀ ÏÎËÓ×ÅÍÈß ÄÀÍÍÛÕ!.'chStat(msg, '#FF0000', obj, 'raised')

else:msg = u'Äàííûå ïîëó÷åíû.'chStat(msg, '#007700', obj, 'raised')

if VERBOSE: print '================> çàãðóçêà çàâåðøåíà.'# Ôóíêöèÿ îòïðàâêè äàííûõ. Íàçíà÷àåòñÿ êàê îáðàáîò÷èê# êíîïêàì îïåðàöèé òèïà 'put'def put(nr):

if VERBOSE: print '================> âûïîëíÿåòñÿ ↵↵↵↵↵îòïðàâêà...'

op = config.operations[nr]exec 'obj = btn%d' % op[0]ftpsite = config.ftpservers[op[3]]msg = u'Ïîäîæäèòå: âûïîëíÿåòñÿ îòïðàâêà...'chStat(msg, '#AA0000', obj, 'sunken')err = putftp(op[4], op[5], op[6], ftpsite, op[7])if err:

msg = u'ÎØÈÁÊÀ ÎÒÏÐÀÂÊÈ ÄÀÍÍÛÕ!'chStat(msg, '#FF0000', obj, 'raised')

else:msg = u'Äàííûå îòïðàâëåíû.'chStat(msg, '#007700', obj, 'raised')

if VERBOSE: print '================> îòïðàâêà âûïîëíåíà.'# Ñîçäàåì ãëàâíîå îêíîtk = Tk()tk.title(u'Öåíòð óïðàâëåíèÿ îáìåíîì')# Íåêîòîðûå äåêîðàòèâíûå ýëåìåíòû...topf = Frame(tk)topf.pack(expand=NO, fill=X)lbl = Label(topf, text = u' � Àâòîìàòèçàöèÿ îáìåíà ↵↵↵↵↵

äàííûìè ïî FTP - ')lbl.config(font = ('Georgia', 9, 'italic bold'))lbl.config(bg = '#AAAAFF')lbl.pack(side=TOP, expand=YES, fill=X)# Ñîçäàåì ñòàòóñ-ìåòêó, â êîòîðóþ áóäåò âûâîäèòüñÿ# èíôîðìàöèÿ î ñîñòîÿíèèmidf = Frame(tk)midf.pack(expand=YES, fill=BOTH)status = Label(midf, text = u'Ïîäðîáíûé âûâîä ñì. ↵↵↵↵↵

â îêíå êîíñîëè')status.config(bg='#FFFFFF', bd=2, relief=SUNKEN, height=3)status.pack(expand=YES, fill=BOTH)# Ôðåéì äëÿ ðàçìåùåíèÿ êíîïîê îïåðàöèé. Íóæåí äëÿ óïðàâëåíèÿ# ðàñòÿãèâàíèåì ïðè èçìåíåíèè ðàçìåðîâ îêíà � âåñü ôðåéì# áóäåò «ïðèâÿçàí» ê íèæíåé êðîìêå îêíàcomf = Frame(tk)comf.pack(fill=X)# Èìïîðòèðóåì êîíôèãóðàöèîííûé ôàéë.

В результате исполнения этого сценария на экране ото-бразится графическое окно наподобие изображенного нарис. 3. Одновременно с этим будет открыто консольное окно,куда будет направляться вывод операторов print (рис. 4).Отдавая сценарий на выполнение интерпретатору pythonw,а не python, можно избежать появления консольного окна.Но в данном случае оно нам нужно для получения дополни-тельной информации.

Таким образом, потратив немного усилий, нам удалосьсущественно упростить для пользователя работу с FTP. Опи-сав в файле config.py все операции, которые должны будутвыполняться пользователями, мы получим удобное графи-ческое окно. Каждая операция будет запускаться по одномущелчку мышки. В случае необходимости можно внести кор-рективы в список операций, на это уйдут считанные минуты.

Безусловно, полученное приложение не является иде-альным. Зато его можно назвать оптимальным в плане со-отношения затрат на разработку, полученной функциональ-ности и удобства использования. К тому же исходный код внесколько строчек всегда рядом, и внести любое измене-ние не составит особого труда.

# Èìåííî â ýòîò ìîìåíò áóäóò âûïîëíåíû «ïðåäâû÷èñëåíèÿ»import config# Ïåðåáèðàÿ âñå êîðòåæè â ñïèñêå îïåðàöèé, äèíàìè÷åñêè# ñîçäàåì äëÿ êàæäîé èç íèõ êíîïêófor op in config.operations:

cmd = "btn%d = Button(comf, text = '%s', " % (op[0], op[2])cmd = cmd + "command = (lambda: %s(%d))) " % (op[1], op[0])exec cmdexec 'btn%d.pack(fill=X)' % op[0]

# Êíîïêà «Çàêðûòü» è åùå íåìíîãî äåêîðàöèécloseBtn = Button(comf, text = u'Çàêðûòü', command = tk.quit)closeBtn.pack(side=RIGHT)copyLbl = Label(comf, text = u'Coded by Amsand, 2004')copyLbl.config(font = ('Georgia', 8, 'italic'))copyLbl.pack(side=LEFT)# Âûâîäèì íà ýêðàí ïîëó÷åííîå îêíî è ïåðåäàåì åìó óïðàâëåíèåmainloop()# Êîãäà îêíî áóäåò çàêðûòî, óïðàâëåíèå âíîâü âåðíåòñÿ# ñöåíàðèþif VERBOSE: print '================> manager.py îñòàíîâëåí.'

Ðèñóíîê 3

Ðèñóíîê 4

Page 44: 025 Системный Администратор 12 2004

42

безопасность

Инциденты с безопасностью были и, видимо, будут всегда.Не последнюю роль в этом играет изначально ошибочныйдизайн многих сетевых протоколов. Большинство из них пе-редают и принимают данные либо в открытом виде, либо сминимальным шифрованием. Криптография не стоит на ме-сте, и постепенно некоторые протоколы обзаводятся функ-циями, реализующими стойкое шифрование, но, к сожале-нию, процесс этот идет не слишком быстро. Для подавляю-щего большинства разработчиков программного обеспече-ния вопросы безопасности создаваемого продукта стоятдалеко не на первом месте. Обычно все делается по прин-ципу «лишь бы приложение хоть как-то заработало», а по-том мы уже исправим все недочеты. Обычно это «потом»растягивается на годы. И чаще всего для внедрения в ужеработающий программный комплекс механизмов безопас-ности необходимо достаточно сильно менять не только код,но и многие идеи, лежащие в основе всего дизайна. Не каж-дый производитель программного обеспечения с радостьюпойдет на дополнительные трудозатраты.

Благодаря инициативе компании Netscape стандартомде факто для задач шифрования веб-коммуникаций сталSSL (Security Socket Layer). Первоначально он применялсядля защиты данных, передаваемых с помощью HTTP. Годыактивного использования в сфере веб-коммерции доказа-ли стабильность и надежность этого решения. Таким обра-зом, возникла защищенная версия протокола HTTP, в даль-нейшем получившая название HTTPS. Вслед за этим по-явились протоколы IMAPS, POP3S, SMTPS, NNTPS, LDAPS.Они призваны со временем заменить своих небезопасныхпредков.

По идее, использование SSL вместо стандартного APIдля работы с сетевыми сокетами должно быть довольно про-стым и прозрачным для приложения. На первый взгляд, нуж-но всего лишь заменить в исходном коде защищаемого при-ложения вызовы стандартных функций на их SSL-аналогии произвести перекомпиляцию. Но не тут то было, при ра-боте в многопоточной и многопользовательской среде при-ходится добавлять в свое приложение довольно много кодаподдержки SSL. На данный момент в сети существует не-сколько библиотек, реализующих функции SSL. Самой по-пулярной из них является OpenSSL, распространяемая пооткрытой лицензии.

Как я говорил ранее, переделка обычной программы вSSL-версию – уже нетривиальный процесс, но на этом труд-ности не заканчиваются. К сожалению, настройка и уста-новка на сервере программного обеспечения, реализующе-го защищенные версии протоколов, упомянутых выше, ча-сто тоже довольно непроста. Кроме этого, иногда встреча-ются ситуации, когда производитель того или иного сер-верного или клиентского обеспечения, работающего с не-безопасными протоколами, канул в Лету, не успев создатьзащищенных версий своих программ и оборудования. Заправо пользования этими разработками когда-то были зап-лачены лицензионные отчисления и, соответственно, отка-заться от работы с ними экономически невыгодно. Иногдаэто сделать вообще невозможно по причине того, что ниодно из решений, предлагаемых сторонними поставщика-ми, не реализует нужные функции. Но чаще всего склады-вается ситуация, когда безопасные приложения от новогопоставщика не удается встроить в устаревшее оборудова-ние и программные среды, до сих пор используемые вомногих производственных процессах и служащие нам ве-рой и правдой.

Таким образом, мы незаметно подошли к предмету на-шей сегодняшней беседы. Говорить мы будем о программеStunnel, которая позволяет защитить небезопасные серви-сы. Механика действия довольно проста. Stunnel позволя-ет шифровать любое TCP-соединение с помощью SSL. Приэтом ни отправитель, ни получатель не подозревают о том,что трафик в процессе передачи по сети шифруется с по-мощью внешней программы.

Программа работает на следующих операционных сис-темах:! FreeBSD! NetBSD! OpenBSD! GNU/Linux! AmigaOS! BeOS! IBM AIX! Mac OS X! OpenVMS

Итак, рассмотрим пример превращения небезопасных

ЗАЩИТА СЕТЕВЫХ СЕРВИСОВС ПОМОЩЬЮ STUNNELЗАЩИТА СЕТЕВЫХ СЕРВИСОВС ПОМОЩЬЮ STUNNEL

АНДРЕЙ БЕШКОВ

! HP NonStop™ Kernel! HP-UX! Plan 9! QNX! SCO OpenServer! SGI IRIX! Solaris! Tru64, он же Digital Unix, он же DEC OSF/1! Windows 95/98/ME/NT/2000/XP

Page 45: 025 Системный Администратор 12 2004

43№12(25), декабрь 2004

безопасность

сервисов pop3, imap, smtp в их безопасные аналоги IMAPS,POP3S, SMTPS. Представим, что у нас есть сервер, функ-ционирующий под управлением FreeBSD 4.10. Он назы-вается freebsd410.unreal.net и доступен нашему клиентупо адресу 10.10.21.134. Кроме всего прочего, на нем ра-ботают программы dkimap, postfix, cucipop, которые и ре-ализуют ту самую «святую троицу» протоколов. Все онипринимают входящие соединения на любом сетевом ин-терфейсе. Postfix работает как резидентный демон, а ос-тальные демоны запускаются с помощью inetd, как толь-ко кто-нибудь попытается присоединиться к нужным пор-там. Соответственно, в /etc/inetdd.conf присутствуют сле-дующие строки:

Таким образом, картина, показываемая командой:

выглядит следующим образом:

Демоны ждут входящих соединений на портах 25, 110,143. Что означают эти номера, можно узнать, пролиставфайл /etc/services. Кстати, стоит убедиться, что в этом жефайле есть записи, описывающие наши будущие защищен-ные сервисы:

Объяснить, как все происходит, довольно просто. На схе-ме изображена типичная картина сетевого взаимодействияклиента и почтового сервера (см. рис. 1).

При отправке сообщений почтовый клиент, умеющий ра-ботать с SSL, шифрует пакеты и передает их демону stunnel.Тот в свою очередь расшифровывает их и отдает демонамimap, pop3, smtp. А почтовые демоны в ответ на запросыотдают данные в открытом виде stunnel, который шифруетих и передает клиенту. При этом ни клиент, ни демоны недогадываются о том, что общаются друг с другом черезпосредника.

Итак, приступаем к установке stunnel на сервер.Предварительно в систему должен быть проинсталли-

рован OpenSSL, так как для правильного функционирова-ния stunnel требуются криптоалгоритмы, реализуемые имен-но этой библиотекой. Для FreeBSD проводить инсталляциюудобнее всего из портов.

По окончании сборки будет автоматически создан поль-зователь stunnel, входящий в одноименную группу. Затемпроизойдет установка, и нам будет доступен stunnel версии4.04. Сразу же после этого система начнет создавать сек-ретный ключ и сертификат. Вы можете воспользоваться этимспособом и начать отвечать на задаваемые вопросы или про-сто нажимать Enter и впоследствии самостоятельно создатьнужные файлы. Я предпочитаю второй способ. Создаем ди-ректорию, где у нас будут храниться сертификаты и ключи.

Самостоятельно создаем ключи и сертификаты со сро-ком действия 1 год. В связи с тем, что stunnel не умеет ра-ботать с ключами, защищенными паролями, используем оп-цию -nodes.

pop3 stream tcp nowait root ↵↵↵↵↵/usr/local/libexec/cucipop cucipop -Y

imap stream tcp nowait root ↵↵↵↵↵/usr/local/libexec/dkimap4 dkimap

tcp4 0 0 *.25 *.* LISTEN

tcp4 0 0 *.143 *.* LISTEN

tcp4 0 0 *.110 *.* LISTEN

# netstat -na | grep LISTEN

imaps 993/tcp # imap4 protocol over TLS/SSLimaps 993/udppop3s 95/tcp spop3 # pop3 protocol over TLS/SSLpop3s 995/udp spop3smtps 465/tcp # smtp protocol over TLS/SSL (was ssmtp)smtps 465/udp

Ðèñóíîê 1

# cd /usr/ports/security/stunnel# make all install

# mkdir /usr/local/etc/stunnel/certs# cd /usr/local/etc/stunnel/certs

Page 46: 025 Системный Администратор 12 2004

44

безопасность

Обратите внимание, что для заполнения поля CommonName или CN было использовано DNS-имя сервера. Этообязательно нужно делать, иначе почтовый клиент будетпостоянно возмущаться несовпадением фактическогоимени сервера и того, что записано в недрах сертифика-та. Также необходимо убедиться, что на клиентском компь-ютере правильно работает разрешение имени freebsd410.unreal.net.

Покончив с предыдущим пунктом, устанавливаем пра-вильные права доступа к файлам.

Создаем директорию, куда демон перейдет в chroot:

При запуске без параметров stunnel будет использоватьфайл конфигурации /usr/local/etc/stunnel/stunnel.conf. Запи-сываем в него следующие строки:

В описании сервисов стоит обратить особое вниманиена ключевые слова accept и connect. Первое описывает ад-рес и порт, через который к нам и от нас будут идти зашиф-рованные данные, а второе, соответственно, адрес и портдля обмена расшифрованными данными с демонами. Опи-сание обоих переменных может быть в нескольких форма-тах.

Адрес:порт – данные принимаются и отправляются толь-ко на интерфейсе и порте с указанным адресом. В случаеесли адрес не указан, по необходимости будут задейство-ваны соответствующие порты на всех доступных интерфей-сах. В моем конфигурационном файле для наглядностипродемонстрированы оба вида настроек.

Запускаем stunnel и смотрим, что демон пишет в /var/log/stunnel.log. Должны увидеть что-то подобное:

Теперь нужно снова посмотреть, что нам скажет коман-да:

Как видите, список портов, ожидающих входящие со-единения, существенно увеличился.

Самое время настроить почтовый клиент. В качестве по-допытного кролика будет использоваться Microsoft OutlookExpress 6. Первым делом будут не самолеты, о которых по-думали поклонники советской эстрады, а копирование сер-тификата с почтового сервера и импортирование его в по-чтовый клиент. С первым заданием, я думаю, вы и сами спра-витесь. Подойдет любой способ, лишь бы файл mailserver.certоказался на Windows-машине. В Outlook Express задейству-ем меню «Сервис →→→→→ Параметры», затем выбираем вкладку

# chmod 600 ./mailserver.cert ./mailserver.key

# Êëþ÷è è ñåðòèôèêàòûcert = /usr/local/etc/stunnel/certs/mailserver.certkey = /usr/local/etc/stunnel/certs/mailserver.key# Äèðåêòîðèÿ, âíóòðè êîòîðîé áóäåò ðàáîòàòü äåìîíchroot = /var/tmp/stunnel# Ôàéë pid. pid = /stunnel.pid# Èìÿ ïîëüçîâàòåëÿ è ãðóïïà, ñ ÷üèìè ïðàâàìè áóäåò# ðàáîòàòü äåìîísetuid = stunnelsetgid = stunnel# Óðîâåíü ïîäðîáíîñòè îòëàäî÷íûõ ñîîáùåíèédebug = 7# Èìÿ ôàéëà ïðîòîêîëèðîâàíèÿoutput = /var/log/stunnel.log# Îïèñàíèå íàøèõ ñåðâèñîâ[pop3s]accept = 10.10.21.134:995connect = 110[imaps]accept = 993connect = 143[ssmtp]accept = 465connect = 127.0.0.1:25

2004.12.04 19:09:15 LOG5[2405:134598656]: stunnel 4.04

on i386-portbld-freebsd4.10 PTHREAD+LIBWRAP

with OpenSSL 0.9.7d 17 Mar 2004

2004.12.04 19:09:15 LOG7[2405:134598656]: Snagged 64 random bytes

from /root/.rnd

2004.12.04 19:09:15 LOG7[2405:134598656]: Wrote 1024 new random

bytes to /root/.rnd

2004.12.04 19:09:15 LOG7[2405:134598656]: RAND_status claims

sufficient entropy for the PRNG

2004.12.04 19:09:15 LOG6[2405:134598656]: PRNG seeded successfully

2004.12.04 19:09:15 LOG7[2405:134598656]: Certificate:

/usr/local/etc/stunnel/certs/mailserver.cert

2004.12.04 19:09:15 LOG7[2405:134598656]: Key file:

/usr/local/etc/stunnel/certs/mailserver.key

2004.12.04 19:09:15 LOG5[2405:134598656]: FD_SETSIZE=1024,

file ulimit=957 -> 467 clients allowed

2004.12.04 19:09:15 LOG7[2405:134598656]: FD 6 in non-blocking mode

2004.12.04 19:09:15 LOG7[2405:134598656]: SO_REUSEADDR option

set on accept socket

2004.12.04 19:09:15 LOG7[2405:134598656]: pop3s bound

to 10.10.21.134:995

2004.12.04 19:09:15 LOG7[2405:134598656]: FD 7 in non-blocking mode

2004.12.04 19:09:15 LOG7[2405:134598656]: SO_REUSEADDR option

set on accept socket

2004.12.04 19:09:15 LOG7[2405:134598656]: imaps bound to 0.0.0.0:993

2004.12.04 19:09:15 LOG7[2405:134598656]: FD 8 in non-blocking mode

2004.12.04 19:09:15 LOG7[2405:134598656]: SO_REUSEADDR option

set on accept socket

2004.12.04 19:09:15 LOG7[2405:134598656]: ssmtp bound to 0.0.0.0:465

2004.12.04 19:09:15 LOG7[2405:134598656]: FD 9 in non-blocking mode

2004.12.04 19:09:15 LOG7[2405:134598656]: FD 10 in non-blocking mode

2004.12.04 19:09:15 LOG7[2406:134598656]: Created pid file /stunnel.pid

netstat -na | grep LISTENtcp4 0 0 *.465 *.* LISTEN

tcp4 0 0 *.993 *.* LISTEN

tcp4 0 0 *.995 *.* LISTEN

tcp4 0 0 *.25 *.* LISTEN

tcp4 0 0 *.143 *.* LISTEN

tcp4 0 0 *.110 *.* LISTEN

# mkdir /var/tmp/stunnel# chown stunnel:stunnel /var/tmp/stunnel# chmod 700 /var/tmp/stunnel

# openssl req -new -x509 -days 365 -nodes ↵↵↵↵↵-out mailserver.cert -keyout mailserver.key

Generating a 1024 bit RSA private key

................++++++

......................++++++

writing new private key to 'mailserver.key'

-----

You are about to be asked to enter information that will be incorporated

into your certificate request.

What you are about to enter is what is called a Distinguished Name or a DN.

There are quite a few fields but you can leave some blank

For some fields there will be a default value,

If you enter '.', the field will be left blank.

-----

Country Name (2 letter code) [AU]:RU

State or Province Name (full name) [Some-State]:Rostov region

Locality Name (eg, city) []:Rostov-on-Don

Organization Name (eg, company) [Internet Widgits Pty Ltd]:Tigrisha home

Organizational Unit Name (eg, section) []:Test Lab

Common Name (eg, YOUR name) []:freebsd410.unreal.net

Email Address []:[email protected]

Page 47: 025 Системный Администратор 12 2004

45№12(25), декабрь 2004

безопасность

«Безопасность», незамедлительно жмем на кнопки «Серти-фикаты» и «Импортировать» и делаем все, как на следую-щих снимках.

После этого в списке доверенных центров сертифика-ции должно появиться имя нашего сервера.

На этом возню с сертификатом можно считать закон-ченной. Переходим к настройке учетной записи. Тут тоженет ничего сложного: нужно всего лишь сделать все так,как изображено на следующих снимках.

Ðèñóíîê 3

Ðèñóíîê 4

Ðèñóíîê 5

Ðèñóíîê 6Ðèñóíîê 2

Ðèñóíîê 7

Ðèñóíîê 8

Ðèñóíîê 9

Page 48: 025 Системный Администратор 12 2004

46

безопасность

После этого вся принимаемая и отправляемая почтабудет шифроваться с помощью SSL, а в файле /var/log/stunnel.log будут появляться подобные надписи:

Для того чтобы забирать письма с сервера, в данномпримере использовался POP3S, но смею вас уверить, чтоIMAPS будет также надежно выполнять эту задачу. Вдовольнаигравшись с Outlook Express, я принялся тестировать все

2004.12.04 22:40:01 LOG7[2406:134598656]: pop3s accepted FD=11 from

10.10.21.162:32872

2004.12.04 22:40:01 LOG7[2406:134598656]: FD 11 in non-blockingmode

2004.12.04 22:40:01 LOG7[2406:134600704]: pop3s started

2004.12.04 22:40:01 LOG5[2406:134600704]: pop3s connected from

10.10.21.162:32872

2004.12.04 22:40:02 LOG7[2406:134600704]: Relying on OpenSSL RSA Blinding.

2004.12.04 22:40:02 LOG7[2406:134600704]: SSL state (accept):

before/accept initialization

2004.12.04 22:40:02 LOG7[2406:134600704]: SSL state (accept):

SSLv3 read client hello A

2004.12.04 22:40:02 LOG7[2406:134600704]: SSL state (accept):

SSLv3 write server hello A

2004.12.04 22:40:02 LOG7[2406:134600704]: SSL state (accept):

SSLv3 write certificate A

2004.12.04 22:40:02 LOG7[2406:134600704]: SSL state (accept):

SSLv3 write server done A

2004.12.04 22:40:02 LOG7[2406:134600704]: SSL state (accept):

SSLv3 flush data

2004.12.04 22:40:02 LOG7[2406:134600704]: waitforsocket: FD=11, DIR=read

2004.12.04 22:40:02 LOG7[2406:134600704]: waitforsocket: ok

2004.12.04 22:40:02 LOG7[2406:134600704]: SSL state (accept):

SSLv3 read client key exchange A

2004.12.04 22:40:02 LOG7[2406:134600704]: SSL state (accept):

SSLv3 read finished A

2004.12.04 22:40:02 LOG7[2406:134600704]: SSL state (accept):

SSLv3 write change cipher spec A

2004.12.04 22:40:02 LOG7[2406:134600704]: SSL state (accept):

SSLv3 write finished A

2004.12.04 22:40:02 LOG7[2406:134600704]: SSL state (accept):

SSLv3 flush data

2004.12.04 22:40:02 LOG7[2406:134600704]: 3 items in the session cache

2004.12.04 22:40:02 LOG7[2406:134600704]: 0 client connects (SSL_connect())

2004.12.04 22:40:02 LOG7[2406:134600704]: 0 client connects that finished

2004.12.04 22:40:02 LOG7[2406:134600704]: 0 client renegotiatations requested

2004.12.04 22:40:02 LOG7[2406:134600704]: 9 server connects (SSL_accept())

2004.12.04 22:40:02 LOG7[2406:134600704]: 9 server connects that finished

2004.12.04 22:40:02 LOG7[2406:134600704]: 0 server renegotiatiations requested

2004.12.04 22:40:02 LOG7[2406:134600704]: 1 session cache hits

2004.12.04 22:40:02 LOG7[2406:134600704]: 1 session cache misses

2004.12.04 22:40:02 LOG7[2406:134600704]: 5 session cache timeouts

2004.12.04 22:40:02 LOG6[2406:134600704]: Negotiated ciphers: AES256-SHA

SSLv3 Kx=RSA Au=RSA Enc=AES(256) Mac=SHA1

2004.12.04 22:40:02 LOG7[2406:134600704]: FD 12 in non-blocking mode

2004.12.04 22:40:02 LOG7[2406:134600704]: pop3s connecting 127.0.0.1:110

2004.12.04 22:40:02 LOG7[2406:134600704]: Remote FD=12 initialized

2004.12.04 22:40:02 LOG7[2406:134600704]: Socket closed on read

2004.12.04 22:40:02 LOG7[2406:134600704]: SSL alert (write): warning:

close notify

2004.12.04 22:40:02 LOG7[2406:134600704]: SSL write shutdown

(output buffer empty)

2004.12.04 22:40:02 LOG7[2406:134600704]: SSL alert (read): warning: close notify

2004.12.04 22:40:02 LOG7[2406:134600704]: SSL closed on SSL_read

2004.12.04 22:40:02 LOG7[2406:134600704]: Socket write shutdown

(output buffer empty)

2004.12.04 22:40:02 LOG5[2406:134600704]: Connection closed:

12678 bytes sent to SSL, 10178 bytes sent to socket

2004.12.04 22:40:02 LOG7[2406:134600704]: pop3s finished (0 left)

почтовые клиенты, что были под рукой. Поэтому могу сме-ло заявить: как и ожидалось, Mozilla Thunderbird 0.6 и XimianEvolution 2.0.2 работают с SSL вполне стабильно и быстро.Единственное нарекание стоит адресовать Kmail 1.7.1, ко-торый при использовании защищенных протоколов стал ше-велиться в несколько раз медленнее, чем обычно. В част-ности, на получение тестового письма из 500 байт у него всреднем уходило примерно 45 секунд.

The Bat, любимый многими на постсоветских просторах,тоже отлично работает в наших условиях. Тесты, описан-ные ниже, проводились на версии 3.0.1.33. Впрочем, думаю,что с большинством версий The Bat это тоже будет рабо-тать. Итак, для того чтобы включить ночного вампира в нашусвязку, нужно установить все так же, как изображено наследующем снимке. Удивляться тому, что вместо SSL при-ходится выбирать TLS, не стоит. Главное, что такой подходработает.

При первой попытке соединения с сервером получаемследующее предупреждение. За исключением опечаток всев нем выглядит неплохо.

Первым делом жмем «Просмотреть сертификат». Иубеждаемся в том, что он действительно принадлежит нам.

Ðèñóíîê 10

Ðèñóíîê 11

Ðèñóíîê 12

Ðèñóíîê 13

Page 49: 025 Системный Администратор 12 2004

47№12(25), декабрь 2004

безопасность

С помощью кнопки «Добавить к доверенным» заверша-ем процедуру.

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

Итак, мы добились того, что данные нормально переда-ются по сети в защищенном виде. Теперь осталось сделатьтак, чтобы никто, кроме stunnel, не смог воспользоватьсястарыми версиями наших сервисов. Для этого нужно, чтобыстандартные демоны SMTP, POP3, IMAP принимали соеди-нения только от 127.0.0.1. Соответственно, клиенты смогутработать с сервером только через stunnel. В случае c postfixвсе довольно просто: необходимо всего лишь установить пе-ременную inet_interfaces = localhost в файле main.cf и пере-запустить его. А вот с cucipop и dkimap4 есть два вариантарешения проблемы. Первый – запретить входящие соедине-ния с помощью межсетевого экрана. Второй – использовать

tcp wrapper. О первом способе написано достаточно многостатей, поэтому давайте посмотрим, как работать с tcpwrapper. При обнаружении нового входящего соединенияinetd вызывает демона tcpd. Тот в свою очередь просматри-вает файл /etc/host.allow и в зависимости от адреса вызыва-ющей стороны принимает решение о том, что делать с со-единением. Если соединение проходит через этот контроль,то его передают демону, который будет в дальнейшем егообслуживать. В отличие от межсетевого экрана, который дляпринятия решений оперирует адресами и номерами портов,tcpd работает с адресами клиентов и именами вызываемыхдемонов. По умолчанию в /etc/hosts.allow описано разреше-ние принимать данные от любых хостов. Это нам не подхо-дит, а значит, надо удалить или закомментировать строкуALL : ALL : allow и добавить в файл вот это:

После внесения изменений все должно работать какчасы. Впрочем, для достижения наилучшего эффекта ник-то не мешает комбинировать настройки tcpd и запреты па-кетов на межсетевом экране. После всех действий данные,выдаваемые netstat, должны выглядеть так:

После некоторого количества тестов можно понижатьуровень подробности отладочных сообщений, описываемыйпеременной debug в файле /usr/local/etc/stunnel/stunnel.conf.Приемлемым значением будет цифра 3.

Кстати, если нужно, чтобы stunnel автоматически запус-кался после перезагрузки машины, не забудьте переиме-новать /usr/local/etc/rc.d/stunnel.sh.sample в /usr/local/etc/rc.d/stunnel.sh. В случае, когда у нас есть клиент, способныйсамостоятельно работать с SSL, все выглядит довольно про-сто. А вот что делать, если такового нет? Этот и многиедругие вопросы мы обсудим в следующей статье.

Ðèñóíîê 14

Ðèñóíîê 15

Ðèñóíîê 16

cucipop : localhost 127.0.0.1 : allowdkimap : localhost 127.0.0.1 : allow

tcp4 0 0 *.465 *.* LISTEN

tcp4 0 0 *.993 *.* LISTEN

tcp4 0 0 10.10.21.134.995 *.* LISTEN

tcp4 0 0 127.0.0.1.25 *.* LISTEN

tcp4 0 0 *.143 *.* LISTEN

tcp4 0 0 *.110 *.* LISTEN

Уважаемые читатели!

Продолжается подписка на журнална I-полугодие 2005 года.

Если вы не успели подписатьсяна все шесть выпусков следующего полугодия,вы сможете приобрести недостающие номера

через интернет-магазины

Доставка почтой в любую точку России.

Page 50: 025 Системный Администратор 12 2004

48

безопасность

ЖЕЛЕЗНЫЙ LOGIN:ЛОМАЕМ ЗУБЫ ГРУБОЙ СИЛЕ

АЛЕКСАНДР ПОХАБОВ

Page 51: 025 Системный Администратор 12 2004

49№12(25), декабрь 2004

безопасность

В этой статье будут рассмотрены решения проблем аутен-тификации и хранения сертификатов и ключей с помощьюhardware-ключей. В своей работе я использовал ОС GNU/Linux, рассматриваемый дистрибутив – Gentoo Linux. Тем,кто работает с другими дистрибутивами, использующихPluggable Authentication Modules, не стоит расстраиваться,разница будет заметна лишь при установке необходимогоПО.

Предполагается, что мы имеем два хоста – рабочая стан-ция и удаленный сервер под управлением ОС Linux. С сер-вером (назовем его «remote») работаем, используя sshd,на обоих хостах имеем привилегии суперпользователя.

Взглянем на проблемы, рассматриваемые в статье.

Проблема перваяЧасто приходится сталкиваться с проблемой запоминанияпаролей, запрашиваемых /bin/login. Все знают, что паролидолжны иметь минимальную длину в восемь символов ивключать в себя символы верхнего и нижнего регистров, атакже спецсимволы. Когда количество подконтрольных намсерверов и пользовательских учетных записей на них воз-растает, удержать в памяти все пароли зачастую почти не-посильная задача. Все принятые нормативные акты по ис-пользованию данных учетной записи запрещают записы-вать пароли на бумаге, сохранять их в файлах и так далее.Как же быть администратору, у которого десятки, а то исотни серверов и на каждом время от времени приходитсярегистрироваться с разными учетными данными?

Проблема втораяНапример, мы используем GnuPG, публичный ключ досту-пен многим, secret key защищен паролем (pass phrase), ноон является не более чем файлом на диске. Если этот файлпохищен злоумышленником, он попытается подобрать вер-ный pass phrase (brute force). Нет гарантии, что правиль-ный пароль не будет найден в ближайшее время.

Электронные USB-ключи, такие как Aladdin eToken илиRainbow iKey, а также смарткарты решают эти проблемы.USB-ключ или смарткарту удобно держать при себе, нельзяпросто получить доступ к хранящимся в них ключам и сер-тификатам, как в случае их хранения на жестком диске. Под-бор PIN по словарю также обречен на провал, так как пос-ле трех (в моем примере) неудачных попыток PIN будет заб-локирован.

Проект OpenSC основал Olaf Kirch. Он хотел написатьбиблиотеку, предоставляющую структуру для написаниядрайверов устройств чтения смарткарт по принципу «все водном», как для работы с устройствами, подключаемыми кпоследовательному порту, так и для USB-ключей.

К моменту написания данной статьи поддерживаютсяследующие устройства:! KOBIL KAAN Professional! Schlumberger e-gate! Aladdin eToken PRO! Eutron CryptoIdentity IT-SEC! Rainbow iKey 3000

Список поддерживаемого оборудования всегда можнопосмотреть на веб-сайте проекта OpenSC – http://opensc.org.

УстановкаТак как в моем примере рассматривается USB-token отAladdin (Aladdin eToken PRO 32K), ядро должно быть собра-но с поддержкой USB device filesystem.

Убедимся, что установлено все необходимое для пос-ледующей работы:

Копируем пример конфигурационного файла opensc.conf:

Сделаем openct и hotplug демонами, запускаемыми поумолчанию:

Запускаем их:

Чтобы не работать постоянно с учетной записью root,добавим непривилегированного пользователя chiko в груп-пу openct и wheel (для возможности использования $ su):

Далее работаем уже под непривилегированной учетнойзаписью.

Вставим USB-ключ и убедимся, что он распознан:

Наш ключ имеет идентификатор 0 – запомним его. Иден-тификаторы ключа всегда присваиваются по возрастаниюначиная с 0. Если ключ не распознан, проверьте исправ-ность USB-порта и наличие в ядре поддержки USB:

а также вывод mount:

# USE='usb pam' emerge opensc

# qpkg -I -v | grep open

# cp /usr/share/opensc/opensc.conf.example /etc/opensc.conf

# rc-update add hotplug default# rc-update add openct default

# usermod -G openct,wheel chiko

* Starting input hotplugging... [ ok ]

* Starting pci hotplugging... [ ok ]

* Starting usb hotplugging... [ ok ]

* Starting OpenCT... [ ok ]

# rc

# qpkg -I -v | grep hotplug

net-misc/openssh-3.8.1_p1-r1 *

dev-libs/openssl-0.9.7d-r1 *

dev-libs/opensc-0.8.1-r1 *

dev-libs/openct-0.5.0 *

sys-apps/hotplug-base-20040401 *

sys-apps/hotplug-20040401 *

# openct-tool list 0 Aladdin eToken PRO

# cat /ïóòü/ê/èñõîäíèêàì_ÿäðà/.config | grep CONFIG_USB_DEVICEFS

CONFIG_USB_DEVICEFS=y

# mount | grep usbfsusbfs on /proc/bus/usb type usbfs (rw)

Page 52: 025 Системный Администратор 12 2004

50

безопасность

Все готово для создания RSA-ключей и X509-сертифи-ката, приступим:

Примечание: все будет временно храниться в директо-рии ~/demoCA.

Создаем пароль:

Подписываем:

Экспортируем наш закрытый ключ:

Сертификат и ключи готовы, поместим их на наш USB-token. Смарткарты, как и USB-ключи используют для хра-нения сертификатов и ключей файловую систему. Многиепроизводители в своих устройствах используют собствен-ные проприетарные механизмы хранения ключей и серти-фикатов, например различные имена директорий. OpenSCреализует PKCS #15 стандарт и имеет модуль эмуляции длянесовместимых механизмов хранения. Необходимо отфор-матировать аппаратный ключ (параметры «-EC» – сокра-щенные от «--erase-card» и «--create-pkcs15») перед его пер-вым использованием (внимание! вся информация на клю-че будет уничтожена!):

Параметр --no-so-pin указывает, что не будет использо-ваться Security Officer PIN. Это избавит вас от лишних зап-росов Security Officer PIN, но так вы понижаете планку бе-зопасности (владельцу ключа будут доступны возможнос-ти создания новых профилей). Также, в случае утери PIN иPUK-кодов пользовательского профиля вы не сможете раз-блокировать пользовательский PIN. Выбор за вами.

На следующем шаге создается пользовательский про-филь, выбираются PIN- и PUK-коды:

# /etc/ssl/misc/CA.pl �newcaCA certificate filename (or enter to create)

Making CA certificate ...

Generating a 1024 bit RSA private key

........++++++

.................................++++++

writing new private key to './demoCA/private/cakey.pem'

Enter PEM pass phrase:

Verifying - Enter PEM pass phrase:

-----

You are about to be asked to enter information that will be incorporated

into your certificate request.

What you are about to enter is what is called a Distinguished Nameor a DN.

There are quite a few fields but you can leave some blank.

For some fields there will be a default value,

If you enter '.', the field will be left blank.

-----

Country Name (2 letter code) [AU]:RU

State or Province Name (full name) [Some-State]:KRAST

Locality Name (eg, city) []:Achinsk

Organization Name (eg, company) [Internet Widgits Pty Ltd]:AGK

Organizational Unit Name (eg, section) []:SB

Common Name (eg, YOUR name) []:Pokhabov Aleksandr

Email Address []:[email protected]

# openssl x509 -in demoCA/cacert.pem -days 3650 ↵↵↵↵↵-out demoCA/cacert.pem -signkey demoCA/private/cakey.pem

Getting Private key

Enter pass phrase for demoCA/private/cakey.pem:

# /etc/ssl/misc/CA.pl �newreq

# /etc/ssl/misc/CA.pl �sign

Generating a 1024 bit RSA private key

......................++++++

............................................................................................................++++++

writing new private key to 'newreq.pem'

Enter PEM pass phrase:

Verifying - Enter PEM pass phrase:

-----

You are about to be asked to enter information that will be incorporated

into your certificate request.

What you are about to enter is what is called a Distinguished Name or a DN.

There are quite a few fields but you can leave some blank.

For some fields there will be a default value,

If you enter '.', the field will be left blank.

-----

Country Name (2 letter code) [AU]:RU

State or Province Name (full name) [Some-State]:KRAST

Locality Name (eg, city) []:Achinsk

Organization Name (eg, company) [Internet Widgits Pty Ltd]:AGK

Organizational Unit Name (eg, section) []:SB

Common Name (eg, YOUR name) []:Pokhabov Aleksandr

Email Address []:[email protected]

Please enter the following 'extra' attributes

to be sent with your certificate request

A challenge password []:OurChallengePass

An optional company name []:AGK

Request (and private key) is in newreq.pem

Using configuration from /etc/ssl/openssl.cnf

2745:error:0E06D06C:configuration file routines:NCONF_get_string:no value:

conf_lib.c:329:group=CA_default name=unique_subject

Enter pass phrase for ./demoCA/private/cakey.pem:

Check that the request matches the signature

Signature ok

Certificate Details:

Serial Number: 1 (0x1)

Validity

Not Before: Nov 4 09:48:50 2004 GMT

Not After : Nov 4 09:48:50 2005 GMT

Subject:

countryName = RU

stateOrProvinceName = KRAST

localityName = Achinsk

organizationName = AGK

organizationalUnitName = SB

commonName = Pokhabov Aleksandr

emailAddress = [email protected]

X509v3 extensions:

X509v3 Basic Constraints:

CA:FALSE

Netscape Comment:

OpenSSL Generated Certificate

X509v3 Subject Key Identifier:

D9:F9:DB:F8:59:4C:72:86:15:13:B0:C0:FE:76:5C:93:C0:FD:38:B9

X509v3 Authority Key Identifier:

keyid:6B:2E:C8:03:71:2E:67:62:71:BF:A7:93:56:52:C2:FF:62:30BA:F0

DirName:/C=RU/ST=KRAST/L=Achinsk/O=AGK/OU=SB/

` CN=Pokhabov Aleksandr/[email protected]

serial:00

Certificate is to be certified until Nov 4 09:48:50 2005 GMT (365 days)

Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y

Write out database with 1 new entries

Data Base Updated

Signed certificate is in newcert.pem

# openssl rsa -in newreq.pem -out newkey.pemEnter pass phrase for newreq.pem:

writing RSA key

# /etc/ssl/misc/CA.pl -pkcs12Enter pass phrase for newreq.pem:

Enter Export Password:

Verifying - Enter Export Password:

# pkcs15-init -EC --label 'Chiko Test Card' --no-so-pinConnecting to card in reader Aladdin eToken PRO...

Using card driver: Siemens CardOS

About to erase card.

About to create PKCS #15 meta structure.

Page 53: 025 Системный Администратор 12 2004

51№12(25), декабрь 2004

безопасность

Помещаем в аппаратный ключ только что созданныйсекретный ключ. На ошибку в пятой строке не обращаемвнимания:

Всё! Ключ прошит. Распорядитесь ключами и сертифи-катом, находящимися в ~/demoCA, подобающим образом.Не стоит забывать, что одна из преследуемых нами целей –исключить наличие сертификатов и закрытых ключей нажестком диске.

Теперь мы готовы настроить PAM-аутентификацию, ис-пользуя pam_opensc.so.

Регистрируемся как root и вносим необходимые изме-нения в настройку PAM. Для использования # su без запро-са пароля членами группы wheel, имеющими аппаратныйключ, привожу пример конфигурационного файла:

Так как мы работали с учетной записью chiko (в вашемслучае может быть другой), проверяем корректную работуследующим образом:

Работает! Вывод # ps auxf докажет, что нет никакогообмана. Проверим логи:

Извлечем ключ из USB:

Теперь не только длина, но и само наличие пароля необязательны. Можно удалить хэш пароля для пользовате-ля chiko (и не только для него) из /etc/shadow, заменив егона восклицательный знак.

При желании сделать аутентификацию только по hard-ware-ключу, /etc/pam.d/login должен быть соответствующеизменен.

У меня он имеет вид:

При попытке зарегистрироваться без наличия аппарат-ного ключа в USB получим:

Если предполагается регистрация в системе под root по# su, файл /root/.eid/authorized_certificates должен быть дос-тупен для чтения, иначе получим ошибку:

Будьте осторожны при изменении файлов конфигура-ции PAM, если допустить ошибки конфигурирования, то естьриск появления неприятного события – мы не сможем за-регистрироваться как root, и придется загружаться с LiveCD,монтировать раздел с /etc и править конфигурационныефайлы PAM. Если в ваши планы ни в коем случае не вхо-дит перезагрузка, предпочтительно сделать резервные ко-пии файлов конфигурации PAM, и используя crontab, по рас-писанию в определеное время вернуть их на место. Этоприменимо в случае ограничения количества pid и tty дляroot, если же таких ограничений нет, предпочтительнее ис-пользовать заранее открытую сессию. Подробнее о работес PAM можно узнать в страницах руководства по PAM.

Внимание! Во всех домашних каталогах пользователей,с учетными данными которых мы будем регистрироватьсяв системе, должен присутствовать корректный ~/.eid/authorized_certificates.

В моем примере до блокирования PIN дается три по-пытки его ввода. Как быть, если после третьей неудачнойпопытки ввести PIN мы получили предупреждение о его бло-кировке?

# pkcs15-init -P --auth-id 01 --label 'CHIKOPIN'Connecting to card in reader Aladdin eToken PRO...

Using card driver: Siemens CardOS

Found Chiko Test Card

About to store PIN.

New user PIN required.

Please enter PIN:

Please type again to verify:

Unlock code for new user PIN required (press return for no PIN).

Please enter PIN:

Please type again to verify:

# pkcs15-init -S newcert.p12 --format pkcs12 -a 01 --split-keyConnecting to card in reader Aladdin eToken PRO...

Using card driver: Siemens CardOS

Found Chiko Test Card

About to store private key.

error:23076071:PKCS12 routines:PKCS12_parse:mac verify failure

Please enter passphrase to unlock secret key:

Importing 2 certificates:

0: /C=RU/ST=KRAST/L=Achinsk/O=AGK/OU=SB/

CN=Pokhabov Aleksandr/[email protected]

1: /C=RU/ST=KRAST/L=Achinsk/O=AGK/OU=SB/

CN=Pokhabov Aleksandr/[email protected]

User PIN required.

Please enter PIN:

# mkdir ~/.eid# pkcs15-tool -r 45 -o ~/.eid/authorized_certificates

Connecting to card in reader Aladdin eToken PRO...

Using card driver: Siemens CardOS

Trying to find a PKCS#15 compatible card...

Found Chiko Test Card!

Reading certificate with ID '45'

# more /etc/pam.d/suauth sufficient /lib/security/pam_opensc.soauth required /lib/security/pam_wheel.so use_uidaccount required ↵↵↵↵↵

/lib/security/pam_stack.so service=system-authsession required ↵↵↵↵↵

/lib/security/pam_stack.so service=system-auth

# su chikoUsing card reader Aladdin eToken PRO

Enter PIN1 [CHIKOPIN]:

$

# grep -ir pam_opensc /var/log/messagesNov 11 16:43:00 workstation su(pam_opensc)[3374]:

Authentication successful for chiko at pts/0.

No smart card present

su: Permission denied

Sorry.

# su chiko

# more /etc/pam.d/loginauth required /lib/security/pam_opensc.soaccount required ↵↵↵↵↵

/lib/security/pam_stack.so service=system-authsession required ↵↵↵↵↵

/lib/security/pam_stack.so service=system-auth

workstation login: chiko

No smart card present

Login incorrect

# suUsing card reader Aladdin eToken PRO

Enter PIN1 [CHIKOPIN]:

No such user, user has no .eid directory or .eid unreadable.

# su

Page 54: 025 Системный Администратор 12 2004

52

безопасность

Ведь даже после ввода корректного PIN мы не увидимничего, кроме предупреждения о том, что он заблокирован.При создании пользовательского профиля на аппаратномключе, кроме PIN мы также указывали PUK-код, его необ-ходимо помнить именно для такого случая. Разблокирова-ние:

Если и PUK забыт и (в нашем примере) не использовал-ся Security Officer PIN, не остается ничего кроме формати-рования ключа, поэтому будьте максимально осторожны.

Первоочередная цель достигнута – dual factor authen-tication (наличие hardware-ключа и знание PIN) работает нанашей системе. Невооруженным глазом заметно, что та-кой способ аутентификации намного безопасней пары login/password.

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

Первое, что следует отметить, – openssh должен бытьсобран с поддержкой смарткарт. В Gentoo это делаетсяочень просто:

Пользователи других дистрибутивов применяют следу-ющее:

Как настроить и запустить sshd, думаю, объяснять нетнеобходимости. Никаких особенных настроек не требует-ся, за исключением вставки на рабочей станции в /etc/pam.d/sshd строки auth required /lib/security/pam_opensc.so. Вот какон выглядит у меня:

Итак, у нас имеется готовый ключ и корректно собран-ный, настроенный и активный sshd на сервере remote. Нанем есть учетная запись пользователя ajwol и в его домаш-нем каталоге имеется директория ~/.ssh . Чтобы зарегист-рироваться с его учетной записью, используя наш ключ, вдомашней директории ajwol, должен присутствовать и бытьдоступным для чтения файл ~/.ssh/authorized_keys, содер-жащий в себе публичный ключ. Создадим его на машине, скоторой будем регистрироваться:

где «0» – идентификатор ключа.Скопируем этот файл в /home/ajwol/.ssh/authorized_keys

на сервер remote:

Регистрируемся на удаленном сервере, используя па-раметр -I 0 (id ключа):

Задача выполнена. Вы можете регистрироваться ста-рым проверенным способом без ключа (не указывая пара-метр -I), используя login/password, но, по желанию, можететакже поиграть с настройками модулей PAM на сервереremote.

Примечание: ~/.ssh/authorized_keys должен быть досту-пен во всех домашних каталогах пользователей, с логина-ми которых будем регистрироваться удаленно.

Теперь не имеет значения длина пароля для логина ajwolна хосте remote, пользователь даже не обязан знать его,хватит и PIN. Эти шаги можно проделать со многими уда-ленными хостами, освободив себя от необходимости запо-минания массы длинных паролей к множеству пользова-тельских аккаунтов.

Задачи, поставленные в начале статьи, решены. В сле-дующих статьях об использовании аппаратных ключей бу-дут рассмотрены примеры их работы с Mozilla и Apache 2,шифрование домашних каталогов.

Ссылки:! http://opensc.org! http://www.openssl.org/docs! http://www.kernel.org/pub/linux/libs/pam! man opensc

Using card reader Aladdin eToken PRO

Enter PIN1 [CHIKOPIN]:

sc_pkcs15_verify_pin: Authentication method blocked

# pkcs15-tool -uConnecting to card in reader Aladdin eToken PRO...

Using card driver: Siemens CardOS

Trying to find a PKCS#15 compatible card...

Found Chiko Test Card!

Enter PUK [CHIKOPIN]:

Enter new PIN [CHIKOPIN]:

Enter new PIN again [CHIKOPIN]:

PIN successfully unblocked.

# USE='X509 pam smartcard' emerge openssh

./configure --with-opensc=/ïóòü/opensc

# more /etc/pam.d/sshdauth required /lib/security/pam_opensc.soaccoun required pam_stack.so service=system-authsession required pam_stack.so service=system-auth

# ssh-keygen -D 0 > ~/authorized_keys

# scp ~/authorized_keys ajwol@remote:.ssh

# ssh -I 0 -l ajwol remoteEnter PIN for Private Key:

Last login: Fri Nov 12 08:20:15 2004 from grayhat

ajwol@remote ajwol $

Page 55: 025 Системный Администратор 12 2004

53№12(25), декабрь 2004

bugtraq

Повышение привилегийв Microsoft WindowsПрограмма: Microsoft Windows 2000 Advanced Server,Microsoft Windows 2000 Datacenter Server, Microsoft Windows2000 Professional, Microsoft Windows 2000 Server MicrosoftWindows NT 4.0 Server Microsoft Windows NT 4.0 Server,Terminal Server Edition, Microsoft Windows Server 2003Datacenter Edition, Microsoft Windows Server 2003 EnterpriseEdition, Microsoft Windows Server 2003 Standard Edition,Microsoft Windows Server 2003 Web Edition, Microsoft WindowsXP Home Edition, Microsoft Windows XP Professional.Опасность: Высокая.Описание: Обнаружено несколько уязвимостей в ОСMicrosoft Windows. Локальный атакующий может повыситьсвои привилегии на системе.1. Уязвимость существует из-за некорректной проверки

буфера при обработке данных, посланных через портLPC (Local Procedure Call). Локальный атакующий мо-жет с помощью специально сформированного запросавызвать переполнение буфера и повысить свои приви-легии на системе.

2. Уязвимость существует при обработке identity токеновв службе LSASS. Локальный атакующий может повы-сить свои привилегии на системе.

Удачная эксплуатация этих уязвимостей дает атакую-щему полный контроль над уязвимой системой.URL производителя: www.microsoft.com.Решение: Установите обновления:1. Microsoft Windows NT Server 4.0 (requires Service Pack

6a): http://www.microsoft.com/downloa...AA8F-AF09-4839-B9E8-BB218C7A8564.

2. Microsoft Windows NT Server 4.0 Terminal Server Edition(requires Service Pack 6): http://www.microsoft.com/downloa...A61F-C69F-403A-BD6A-EF3984BFA2B8.

3. Microsoft Windows 2000 (requires Service Pack 3 or ServicePack 4): http://www.microsoft.com/downloa...A122-DDA4-40B8-A7AF-9DDCC3870C38.

4. Microsoft Windows XP (requires Service Pack 1 or ServicePack 2): http://www.microsoft.com/downloa...5D5C-3E4A-4F41-B81E-376AA1CD204F.

5. Microsoft Windows XP 64-Bit Edition (requires ServicePack 1): http://www.microsoft.com/downloa...AE1E-0ABF-4D31-BE12-3982C5146AE8/

6. Microsoft Windows XP 64-Bit Edition Version 2003: http://www.microsoft.com/downloa...9AB9-36BF-4A90-BC37-3B4FB6DCDF9A.

7. Microsoft Windows Server 2003: http://www.microsoft.com/downloa...97CB-E8F0-461F-B2D2-F1065229B64E.

8. Microsoft Windows Server 2003 64-Bit Edition: http://www.microsoft.com/downloa...9AB9-36BF-4A90-BC37-3B4FB6DCDF9A.

Множественные уязвимости в Linux-ядреПрограмма: Linux kernel 2.4 – 2.4.28, 2.6 – 2.6.9.Опасность: Высокая.Описание: Обнаружено несколько уязвимостей в реализа-ции IGMP-протокола в ядре Linux. Удаленный атакующийможет вызвать отказ в обслуживании. Локальный атакую-щий может повысить свои привилегии на системе.1. Уязвимость существует в функции ip_mc_source(), кото-

рая может быть вызвана с помощью пользовательскогоAPI (IP_(UN)BLOCK_SOURCE, IP_ADD/DROP_SOURCE_MEMBERSHIP, равно как и MCAST_(UN)BLOCK_SOURCEи MCAST_JOIN/LEAVE_SOURCE_GROUP уровня соке-та SOL_IP). Существует возможность уменьшить зна-чение «sl_count» счетчика структуры «ip_sf_socklist» до0xffffffff (т.е. -1 для целочисленных), что приведет к за-цикливанию вызова функции и вызовет зависание сис-темы на несколько минут (в зависимости от скоростиобработки данных на системе). Эти действия приведутк тому, что вся память ядра, которая следует за kmalloc-буфером, будет смещена на 4 байта, что должно приве-сти к немедленной перезагрузке системы в обычныхусловиях и позволить локальному атакующему повыситьсвои привилегии на системе.

2. Из-за уязвимости, описанной выше, возможно прочитатьбольшое количество памяти ядра с помощью функцийip_mc_msfget() и ip_mc_gsfget().

3. Уязвимость функции igmp_marksources() из модуляnetwork (которая вызывается в контексте группы запро-сов IGMP, полученных из сети) существует из-за недо-статочной проверки длины полученных параметровIGMP-сообщений. Эта уязвимость реализуема только намультикаст-системах, где приложение создает многоад-ресный сокет.

Удаленный атакующий может вызвать отказ в обслужи-вании системы.URL производителя: kernel.org.Решение: Установите обновление c сайта производителя.

Выполнение произвольного кода в WINSПрограмма: Семейство ОС Microsoft Windows.Опасность: Высокая.Описание: Обнаружено переполнение буфера в службеwins.exe. Удаленный атакующий может выполнить произ-вольный код на уязвимой системе.

Удаленный атакующий может послать специально сфор-мированный WINS-пакет на 42 TCP-порт, для того чтобыизменить указатель и записать произвольный код в любуюячейку памяти. Удаленный атакующий может выполнитьпроизвольный код на уязвимой системе.URL производителя: www.microsoft.com.Решение: Решения на данный момент не существует.

Составил Александр Антипов

Page 56: 025 Системный Администратор 12 2004

54

безопасность

Известно, что появлению Интернета мы обязаны американ-скому министерству обороны. Поэтому интересными явля-ются и разрабатываемые в этом ведомстве технологии,направленные на защиту информации. На страницах жур-нала уже рассказывалось о проекте Security Enhanced Linux1

(http://www.nsa.gov/selinux) от U.S. National Security Agency(NSA), основной задачей которого является создание вы-сокозащищенных систем. Сегодняшняя статья о не менееинтересной системе, помогающей выявить проблемы в сети.

Разработанная в 1994 году, система обнаружения атакSHADOW или Secondary Heuristic Analysis for Defensive

Online Warfare (http://www.nswc.navy.mil/ISSEC/CID) являетсярезультатом деятельности другого проекта CooperativeIntrusion Detection Evaluation and Response (CIDER). CIDERв свою очередь был попыткой совместной разработки ин-струментов для автоматического сбора и анализа потоковинформации в целях обнаружения атак. Основные работыведутся Naval Surface Warfare Center, но свои усилия при-ложили и другие не менее известные организации вродеNSWC Dahlgren, NFR, NSA и SANS. Некоторое время сис-тема была закрыта, затем SHADOW так же стал свободнодоступен, так как основой являются программы с откры-

СЕРГЕЙ ЯРЕМЧУК

ТЕНИ ИСЧЕЗАЮТ В ПОЛДЕНЬ

1 Яремчук С. SELinux. – Журнал «Системный администратор», №5, май 2003 г.

Page 57: 025 Системный Администратор 12 2004

55№12(25), декабрь 2004

безопасность

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

Это уникальная в своем роде разработка, она базиру-ется на идее статистического анализа потоков информа-ции. Проверяются только размеры пакетов, откуда они при-ходят и куда направлены, без проверки внутреннего содер-жания. Это означает, что SHADOW пытается отыскать впервую очередь исследования, предшествующие атаке, ане саму атаку. Поэтому такая система в принципе способ-на выдать раннее предупреждение, что отличает ее от сиг-натурных реализаций или определяющих аномалии в ре-альном времени. Такой анализ потоков информации дела-ет возможным работу системы при использовании различ-ных форм шифрования трафика. Также эта система можетпомочь отследить статистику работы компьютеров в сети,если же обнаружится неизвестный, то администратор по-лучит предупреждение. Также администратор получает всвои руки полезный инструмент, позволяющий визуальноопределить происходящее в сети. Собранная информацияпоможет определиться со стратегией безопасности и бу-дет полезна при задании правил firewall.

Архитектура SHADOWОснову проекта составляют tcpdump и libpcap, применяю-щиеся для сбора сетевых пакетов. Как уже говорилось,анализируются только заголовки без анализа информа-ции. Первоначально это может показаться не совсем ра-зумно, так как некоторые атаки могут быть выявлены толь-ко при анализе содержимого, но для организаций, в кото-рых повышенное внимание к конфиденциальности инфор-мации, – это, наверное, единственно разумный выход. Ведьесли злоумышленник либо лицо, на это не уполномочен-ное, сможет получить доступ к данным базы собранных па-кетов, то грош цена такой IDS. К тому же подобный подходтребует меньшего количества ресурсов.

Сама же система состоит из датчиков, анализаторов ибазы собранных пакетов (рис. 1). При этом не имеет значе-ния количество и место расположения датчиков, он простособирает пакеты и по запросу переправляет их дальше ана-лизатору. Их можно установить в зависимости от задач навнешнем интерфейсе, в DMZ или внутри сети. Установка внеfirewall – большой риск, поэтому разработчики старались мак-симально его уменьшить и подстраховаться от возможнойкомпрометации датчика. Анализатор всегда должен нахо-диться за firewall. Его задача загрузить и оценить данные,собранные различными датчиками. Датчики и анализаторыдля выборки данных и обслуживания соединяются посред-ством SSH. Для отбора событий, представляющих интерес,используются фильтры и скрипты. Последние позволяютобнаруживать и некоторые медленные, т.е. растянутые повремени атаки, а также распределенные атаки. Вся собран-ная информация в дальнейшем будет выводиться админис-тратору в виде веб-страницы. Веб-интерфейс позволяет ис-следовать информацию, полученную от различных датчиков,за различные периоды времени, с подробной информациейотносительно отдельного узла или образца, а также созда-вать готовые отчеты отправки для посылки в CIRT.

Установка SHADOWК сожалению, проект практически лишен нормальной до-кументации. Имеется инструкция по установке да пара ссы-лок на устаревшие статьи с других сайтов. Инструкция по-казывает процесс установки в пошаговом режиме, но приэтом в некоторых ключевых местах допущены мелкие, носбивающие и запутывающие ошибки, а о некоторых важ-ных деталях там совсем ничего не сказано. Вся же конфи-гурация производится исключительно вручную и требуетзнаний архитектуры сетей, строения UNIX и особенностейнастройки некоторых Open Source-разработок. Поэтому этозанятие не тривиальное, требующее внимательности и зна-ний, и у новичков, скорее всего, возникнут трудности. Новот что мне нравится, так это подход. Фактически пользо-ватель (или злоумышленник) в правильно настроенной си-стеме обставлен флажками, за которые он выскочить несможет при всем своем желании. Поэтому использованиеSHADOW, даже при многочисленных сенсорах, вряд лиможет снизить общую защищенность сети и служить ис-точником утечки информации или дать информацию о стро-ении сети. С другой стороны, тем, кто хочет разобраться сбезопасной настройкой и использованием всех упоминае-мых ниже сервисов, стоит для ознакомления почитать этуинструкцию. Также одной из целей этой статьи являетсяпоказ варианта безопасного конфигурирования разных сер-висов. В различной литературе не всегда можно найти от-веты на все вопросы.

Для датчиков и анализаторов подойдет любая UNIX-по-добная система, под которую можно скомпилироватьlibpcap, tcpdump, Perl, gzip, Apache и OpenSSH. Датчики ианализатор в целях безопасности должны находиться наразных машинах. Хотя в принципе и возможно их разме-щение на одном компьютере, но подразумевается, что дат-чик будет находиться в агрессивной среде, и поэтому в це-лях безопасности рекомендуется раздельное размещение.Девиз такой – никакого доверия датчикам. Датчик сконфи-гурирован так, чтобы работать только по SSH и только санализаторами. Датчики должны быть защищены в макси-мально возможной степени. Чтобы сделать датчик невиди-мым, рекомендуется использование двух сетевых плат.Одна «невидимая» без IP-адреса будет собирать данные, а

Ðèñóíîê 1

Page 58: 025 Системный Администратор 12 2004

56

безопасность

другая, которую желательно поместить за firewall, будет пе-редавать информацию анализаторам.

Для включения режима невидимости в дистрибутивеRed Hat и базирующихся на нем, файл /etc/sysconfig/network-scripts/ifcfg-eth0 (где eth0 – первая сетевая карта), долженсодержать такие строки.

В других дистрибутивах это будет скорее выглядеть не-сколько иначе, например, в SuSE за загрузку отвечает пе-ременная STARTMODE.

Системные требования невысоки. Единственное, в боль-ших и активных сетях может понадобиться применениеSCSI-диска и больший объем жесткого диска (в основномдля анализаторов) для хранения захваченной информации.В моем случае система на детекторы захватывала около2-3 Гб в день. Дополнительно рекомендуется выкинуть всененужное из ядра и отказаться от использования модулей(ответ «N» в «Enable loadable module support.»). В докумен-тации приведен пример .config-файла для перекомпиляцииядра, желательно также обновить систему.

В целях безопасности все процессы и каталоги на дат-чиках и анализаторах работают от имени отдельного не-привилегированного пользователя. Поэтому его необходи-мо будет завести перед установкой:

Для защиты рекомендуется выключить все лишние сер-висы на используемых компьютерах (получить их список мож-но, введя chkconfig --list). Для отключения запускаемых че-рез xinetd можно удалить все файлы в каталоге /etc/xinetd.dили проверить наличие строки «disable = yes» в каждом изних. Вторым шагом сетевой защиты является использова-ние tcp_wrappers. Для чего в файле /etc/hosts.allow должныбыть описаны адреса компьютеров, которым разрешен до-ступ к тем или иным сервисам. Формат файла прост:

Например:

В приложении «С», в инструкции по установке, вы най-дете рекомендуемые опции для настройки iptables.

Документ описывает установку на Red Hat Linux (конк-ретно версии 8.0), именно под него разрабатываетсяSHADOW. Я использовал White Box Linux 3.0 и SuSE Linux9.1. Если с первым проблем практически не было, что и не-удивительно, ведь его основой служат исходные коды RedHat Enterprise Linux. То при установке в SuSE пришлось не-много повозиться, в основном это касается путей к конфи-гурационным файлам, которые пришлось изменять прак-тически во всех скриптах. Это общие вопросы, теперь от-дельно рассмотрим особенности настройки датчика и ана-лизатора.

Построение датчикаСкачиваем архив размером чуть меньше 7 Мб. И создаемкаталоги для размещения. В документации предлагается/usr/local/, можно выбрать и другой, но при этом придетсяуказать новый путь во многих конфигурационных файлах.

И распаковываем в него архив (tar xvfz /tmp/SHADOW-1.8.tar.gz). Все основные файлы подписаны при помощиGPG, и при сомнении подпись можно проверить.

Теперь в каталоге появится большое количество скрип-тов и подкаталогов, о назначении некоторых станет яснопо ходу изложения. В подкаталоге Doc вы найдете инструк-цию по установке, в accessories – необходимые для работыутилиты libcap, tcpdump и openssh в rpm-пакетах и исход-ных кодах. Здесь последние версии этих утилит на моментвыпуска SHADOW (апрель 2003), поэтому можно оставитьимеющиеся в используемом дистрибутиве или взять болееновые версии с официальных сайтов. Еще один момент,связанный с tcpdump. В RedHat, начиная с версии 6.2, при-меняют патчи, расширяющие возможности, но изменяющиевыходной формат данных, с которыми анализатор работатьне может. Поэтому если вы не уверены, tcpdump лучше все-таки взять и установить с http://www.tcpdump.org. О настрой-ке и работе этих утилит уже рассказывалось на страницахжурнала, поэтому этот вопрос в статье затрагиваться бу-дет в объеме, необходимом для понимания процесса кон-фигурирования SHADOW.

Теперь три скрипта в /usr/local/SHADOW/sensor требу-ют настройки. Это sensor_init.sh, std.ph и std.filter.

Скрипт sensor_init.sh используется для запуска датчика.В нем переменная SENSOR_PATH должна указывать на

каталог, куда установлен сенсор, SENSOR_PARAMETERуказывает на файл, содержащий настройки датчика (безрасширения .ph). Для примера настроек, в каталоге имеет-ся файл std.ph. При необходимости можно использоватьсразу несколько сенсоров с индивидуальными конфигура-ционными файлами. Далее необходимо проверить наличиефайлов, прописанных в следующих переменных.

В SuSE первую строку пришлось закомментировать.Теперь копируем скрипт в положенное место.

Это для RedHat, в других дистрибутивах путь, возмож-но, будет другим. Например, в SuSE команда будет такой:

И добавляем скрипт в автозапуск.

# mkdir -p /usr/local/SHADOW

# gpg --verify some_file_name.sig

# Source function library.. /etc/rc.d/init.d/functions# Source networking configuration.. /etc/sysconfig/network

# cd /usr/local/SHADOW/sensor# cp sensor_init.sh /etc/rc.d/init.d/sensor

# cp sensor_init.sh /etc/rc.d/sensor

DEVICE=eth0ONBOOT= no

# useradd -c "SHADOW" -u 666 -d /home/SHADOW shadow

ñïèñîê_ñåðâèñîâ: ñïèñîê_ìàøèí [: êîìàíäà]

sshd: 192.168.2. : allowALL: 192.168.1.100,127.0.0.1 : allowALL: ALL : deny

Page 59: 025 Системный Администратор 12 2004

57№12(25), декабрь 2004

безопасность

В файле std.ph (или как вы его назвали) также проверь-те наличие файлов и каталогов, указанных в переменных.В std.filter указываются параметры фильтра для захватывае-мых tcpdump-пакетов. По умолчанию в файле одна строкаip, можно использовать и собственные конструкции вроде:

для icmp-пакетов или для NetBIOS:

Сценарий sensor_driver.pl управляет сенсорами. Для тогочтобы собирать данные, каждый час во время работы сис-темы используется crontab-сценарий – sensor_crontab. Дляреализации последней возможности копируем его в ката-лог /etc/cron.hourly. Этот сценарий содержит три строки.Первые две предназначены для синхронизации времени по-средством Network Time Protocol (NTP), последняя, которуюнужно раскомментировать, управляет запуском sensor_driver.pl. Параметры внутри, конечно же, можно подправить(список серверов времени на http://www.ntp.org, плюс статьяМихаила Платова «NTP – атомные часы на каждом столе»,журнал «Системный администратор», № 4, апрель 2004 г.).

Все, датчик готов, можно приступать к настройке ана-лизатора.

Настройка анализатораВсе первичные действия для анализаторов ничем не отли-чаются от проводимых на датчиках. Но после распаковкиархива на свое место внимания требуют совсем другие фай-лы.

Также для работы потребуется установленный веб-сер-вер Apache любой версии (в целях безопасности обновле-ние рекомендуемо всегда), желательно с модулями mod_sslи mod_perl. Практически во всех дистрибутивах он есть.Можно использовать веб-сервер параллельно основной ра-боте, но лучше только для работы с SHADOW. В каталоге/usr/local/SHADOW/httpd/apache-conf найдете примеры кон-фигурационных файлов для версий 1.3 и 2.0, в том числе иоригинальный httpd.conf. Общим для всех файлов веб-сер-вера, включая и .htaccess, является наличие для всех упо-минаемых в них каталогов, конструкций вида.

Не забудьте заменить адреса своими, иначе в доступебудет отказано.

В файле httpd-2.0.40.basic содержатся минимальныенастройки веб-сервера, с которыми система уже может быть

запущена (в RedHat). Для этого достаточно его скопиро-вать на свое место.

В SuSE необходимо заменить пользователя и группу.

И дописать в файл строку:

Можно как вариант использовать более подробныйhttpd-2.0.40.conf.

Теперь готовим каталоги, в которых будут размещать-ся результаты, выводимые пользователю.

Не забудьте изменить адреса в .htaccess.

Все, можно перезапускать веб-сервер.

И теперь самое интересное и хлопотное – настройкаключей ssh. Для правильной работы OpenSSH, необходи-мо, чтобы файл /home/shadow/.ssh/authorized_keys на де-текторах содержал копии открытых ключей пользователяshadow, которые были сгенерированы на анализаторе. Нопоначалу необходимо, естественно, установить OpenSSHна датчике и анализаторе. Если команда ls /etc/ssh не по-кажет наличия файлов вида ssh_host_key.pub, то ключи мож-но сгенерировать автоматически, просто запустив сервер.

И не забудьте добавить запуск OpenSSH при загрузкесистемы.

Теперь необходимо, чтобы участвующие в работе узлыузнали о публичных ключах друг друга. Есть много спосо-бов, самый простой – соединиться с нужным узлом, и этаоперация будет проделана автоматически. Разработчикисчитают более безопасным другой вариант. Монтируем дис-кету на датчике и копируем в нее все необходимые файлы.

# chkconfig --add sensor

icmp and icmp[0] != 8 and icmp[0] != 0

ip and (port 137 or port 138 or port 139)

17 23 * * * /usr/sbin/ntpdate time-a.nist.gov18 23 * * * /sbin/hwclock --systohc0 * * * * /usr/local/SHADOW/sensor/sensor_driver.pl std > ↵↵↵↵↵

/dev/null 2>&1

Order deny,allowDeny from allAllow from 172.21.122Allow from localhostAllow from 127.0.0.1

# mount -t vfat /dev/fd0 /mnt/floppy# cd /etc/ssh# cat ssh_host_key.pub ssh_host_dsa_key.pub ↵↵↵↵↵

ssh_host_rsa_key.pub > /mnt/floppy/ssh_known_hosts# umount /mnt/floppy

# cp /etc/apache2/httpd.conf /etc/apache2/httpd.conf.orig# cp /usr/local/SHADOW/httpd/apache-conf ↵↵↵↵↵

/httpd-2.0.40.basic /etc/apache2/httpd.conf

User wwwrunGroup www

Include /etc/apache2/sysconfig.d/loadmodule.conf

# mkdir -p /home/shadow/html/tcpdump_results# cd /usr/local/SHADOW/httpd/home# cp * /home/shadow/html# cp .htaccess /home/shadow/html

# chown -R shadow:shadow /home/shadow

# /etc/init.d/httpd restart

# /etc/init.d/sshd start

# chkconfig --add sshd

Page 60: 025 Системный Администратор 12 2004

58

безопасность

Теперь вставляем дискету в дисковод анализатора икопируем полученный файл на свое место.

Теперь на анализаторе необходимо сгенерировать отимени пользователя shadow ключи и скопировать их затемна датчики.

В некоторых дистрибутивах при создании пользовате-ля создается и каталог .ssh, если такого нет, создаем его.

Генерируем ключи:

В этом моменте в документации допущена ошибка. Поумолчанию ключ rsa генерирует вторую версию, а в инст-рукции указано rsa2, что приводит к ошибке. Номер пока-зывать необходимо как раз для первой версии.

И на датчиках:

Теперь можно попробовать зайти с анализатора по sshна датчик от имени пользователя shadow. Если получилось,

то можно продолжать дальше. Иначе проверьте имена фай-лов и права доступа к ним (700 для каталогов и 600 для фай-лов). Тему безопасности соединений ssh можно продолжатьи далее. Например, используя инструкции ListenAddress иAllowUsers файла /etc/ssh/sshd_config можно еще более су-зить диапазон возможных действий пользователя.

Еще для полноценной работы необходимо установитьnmap и сконфигурировать sudo, для того чтобы Apache могего запустить. Для этого редактируем файл /etc/sudoers,примерно так.

Кроме того, такой инструмент, как nmap, не рекоменду-ется раздавать кому попало, тем более что он запускаетсяот имени root. Поэтому некоторые скрипты, находящиесяв /home/shadow/httpd/cgi-bin/privileged (в документации здесьтоже ошибка), защищены дополнительно файлом .htaccessс использованием директивы Satisfy (надо отметить, что вбольшинстве советов по построению защищенного веб-сер-вера, о Satisfy почему-то забывают). Теперь при запросе изнезащищенной сети от пользователя потребуют дополни-тельной авторизации.

Как видите, только пользователи сети 172.16.47 могутзапускать nmap без ввода пароля. Пароль можно создатьпри помощи htpasswd, формат вызова которой:

Например:

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

В каталоге /usr/local/SHADOW/filters имеются шестьфильтров, отдельно для каждого протокола, с подробнымикомментариями внутри: filter.getall.doc, goodhost.filter.doc,icmp.filter.doc, ip.filter.doc, tcp.filter.doc, и udp.filter.doc.

Скрипт find_scan.pl использует файл filter.getall.doc дляопределения внутренних сетей, fetchem.pl при помощи goodhost.filter.doc определяет свои mail, web servers и DNS-сер-веры. После проверки адресов и внесения своих парамет-ров убираем комментарии при помощи скрипта comment_strip.

# mount -t vfat /dev/fd0 /mnt/floppy# cd /home/shadow/.ssh# cp /mnt/floppy/authorized_keys .# umount /mnt/floppy

# Host alias specificationHost_Alias SHADOW = analyzer1.com, analyzer2.com# Cmnd alias specificationCmnd_Alias NMAP = /usr/bin/nmap# User privilege specificationroot ALL=(ALL) ALLapache SHADOW=NOPASSWD: NMAP

AuthType BasicAuthName "Privileged SHADOW Users"AuthUserFile /usr/local/SHADOW/httpd/cgi-bin ↵↵↵↵↵

/privileged/nmap_pwdSatisfy anyrequire valid-userorder deny,allowdeny from allallow from 172.16.47

htpasswd -c /path/to/store/password username

# htpasswd -c /usr/local/SHADOW/httpd/cgi-bin ↵↵↵↵↵/privileged/nmap_pwd grinder

# mount -t vfat /dev/fd0 /mnt/floppy# cd /etc/ssh# cp /mnt/floppy/ssh_known_hosts .# umount /mnt/floppy

# su � shadow

# mkdir .ssh# chmod 700 .ssh# cd .ssh

# /usr/bin/ssh-keygen -b 1024 -t dsa -f .id_dsaGenerating public/private dsa key pair.

Enter passphrase (empty for no passphrase):

Enter same passphrase again:

Your identification has been saved in .id_dsa.

Your public key has been saved in .id_dsa.pub.

The key fingerprint is:

89:e5:73:fa:37:78:9d:4b:7f:a7:10:49:eb:21:27:21 shadow@notebook

# /usr/bin/ssh-keygen -b 1024 -t rsa -f .id_rsa2Generating public/private rsa key pair.

Enter passphrase (empty for no passphrase):

Enter same passphrase again:

Your identification has been saved in .id_rsa2.

Your public key has been saved in .id_rsa2.pub.

The key fingerprint is:

b6:63:24:af:1e:c1:c2:3a:f5:cc:6b:cd:e0:b2:19:89 shadow@notebook

# /usr/bin/ssh-keygen -b 1024 -t rsa1 -f .id_rsa1Generatingpublic/private rsa1 key pair.

Enterpassphrase (empty for no passphrase):

Enter same passphrase again:

Your identification has been saved in .id_rsa1.

Your public key has been saved in .id_rsa1.pub.

The key fingerprint is:

bf:9e:2e:44:3b:65:f1:2f:77:6b:23:bc:e6:a9:66:3f shadow@notebook

# cat .id_dsa.pub .id_rsa2.pub .id_rsa1.pub > authorized_keys# mount -t vfat /dev/fd0 /mnt/floppy/# cp authorized_keys /mnt/floppy/# umount /mnt/floppy

Page 61: 025 Системный Администратор 12 2004

59№12(25), декабрь 2004

безопасность

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

Если не получена ошибка «parse error», то фильтр мож-но использовать в работе.

Теперь осталось заглянуть в файл /usr/local/SHADOW/etc/shadow.conf, который содержит настройки для конкрет-ной системы. Надо отметить, что появление этого файла впоследних версиях SHADOW заметно упростило настрой-ку, теперь многие скрипты берут параметры отсюда. Ранеевсе параметры приходилось вбивать в каждый файл, чтоприводило к ошибкам и затрудняло конфигурацию.

Проверьте, чтобы совпадали пути к утилитам и изме-ните IP-адреса и e-mail на реальные. После этого его мож-но скопировать в /etc или просто создать символическуюссылку.

На сенсорах файл /etc/shadow.conf не используется, вме-сто него применяется файл Site.ph, лежащий в /usr/local/SHADOW/sites/. Файл примера, который найдете в этом ка-талоге, содержит настройки для первого детектора «OutsideNetwork Perimeter» с именем Site1.ph. Для других детекто-ров параметры $SITE и $SITE_LABEL и имя необходимо из-менить, сверившись с /etc/shadow.conf. Кроме того, в пере-менных $SENSOR, $WEB_SERVER и @LOCAL_IP проставь-те нужные параметры. Переменная $SENSOR_DIR=»/LOG»,указывает на каталог, куда детекторы будут сохранять со-бранные данные. Мне показалось, что-то вроде /var/shadowс вынесеным в отдельный дисковый раздел /var будет бо-лее правильно.

Теперь осталось проверить наличие всех каталогов, ука-занных в переменных файлов /etc/shadow.conf на анализа-торе и Site1.ph на всех детекторах и изменить пользовате-ля/группу chown –R shadow:shadow, где это потребуется.

Все детекторы собирают информацию (не менее часа),теперь можно попробовать ее получить и проанализировать.Для начала лучше это проделать вручную.

Для получения информации с определенного детекто-ра используется скрипт fetchem.pl. Основная задача кото-рого получить с указанного детектора нужный файл, содер-жащий собранные данные, создать для него подкаталог наанализаторе и выходной html-файл, сортировать данные,заменить IP-адреса именами и еще много чего. Например,данные за 21 час 31 октября 2004 года, с выводом логов в/tmp/fetchem.log можно получить так.

В результате с указанного детектора будет скачан файлс указанными данными и положен в /usr/local/SHADOW/data/Site1/Oct31/tcp.2004103120.gz. После первичного анализа вдомашнем каталоге веб-сервера будет создан каталог /home/shadow/html/tcpdump_results/Site1/Oct31 с несколькими фай-лами, пользователю будет выводиться 2004103121.html.

Для автоматизации этого процесса в работе использу-ется cron-файл analyzer_crontab.shadow

Скрипт do_daily_scripts.pl из собранных за день данныхсобирает статистику, эти данные будут затем выводиться понажатию кнопки «STATISTICS» в веб-браузере, cleanup.pl воизбежание исчерпания свободного дискового места, полно-стью удаляет собранные на датчиках данные.

Теперь можно запускать браузер и пробовать соединить-ся с веб-сервером, запустится два окна (рис. 2). В резуль-тате экспериментов выяснилось, что левая панель инстру-ментов, запускаемая из /cgi-bin/tools.cgi не может быть нор-мально отображаться всеми браузерами. Разработчики ука-зали на совместимость практически со всеми браузерамистарых версий, но из всего имеющегося набора в SuSE 9.1комфортно работать можно было только в konqueror. Веро-ятно, функции, прописанные в openwin.js, требуется пере-писать.

Если подойти к процессу настройки внимательно и твор-чески, то сейчас все должно работать. И только при жела-нии для удобства использования можно потихоньку подпра-вить скрипты под себя. В дальнейшем необходимо изучениезахваченной информации и подстройка фильтров, для тогочтобы система получала только необходимое. Успехов.

Ðèñóíîê 2

# /usr/local/SHADOW/fetchem.pl -l Site1 -d 2004103121 -debug

# Run fetchem to get SHADOW data files:#SHADOW_PATH=/usr/local/SHADOW#1 * * * * $SHADOW_PATH/fetchem.pl -l Site13 * * * * $SHADOW_PATH/fetchem.pl -l Site2 -debug## Cleanup once per day.#15 1 * * * $SHADOW_PATH/cleanup.pl -l Site124 1 * * * $SHADOW_PATH/cleanup.pl -l Site2## Collect statistics each night.#1 0 * * * $SHADOW_PATH/stats/do_daily_stats.pl -l Site11 3 * * * $SHADOW_PATH/stats/do_daily_stats.pl -l Site2

# /usr/local/SHADOW/comment_strip ip.filter.doc > ↵↵↵↵↵/usr/local/SHADOW/filters/Site1/ip.filter

# /usr/local/SHADOW/comment_strip icmp.filter.doc > ↵↵↵↵↵/usr/local/SHADOW/filters/Site1/icmp.filter

# /usr/local/SHADOW/comment_strip tcp.filter.doc > ↵↵↵↵↵/usr/local/SHADOW/filters/Site1/tcp.filter

# /usr/local/SHADOW/comment_strip udp.filter.doc > ↵↵↵↵↵/usr/local/SHADOW/filters/Site1/udp.filter

# /usr/local/SHADOW/comment_strip goodhost.filter.doc > ↵↵↵↵↵/usr/local/SHADOW/filters/Site1/goodhost.filter

#/usr/local/SHADOW/comment_strip filter.getall.doc > ↵↵↵↵↵/usr/local/SHADOW/filters/Site1/filter.getall

# tcpdump -i eth0 -n -F /usr/local/SHADOW/filters ↵↵↵↵↵/Site1/tcp.filter

# ln �s /usr/local/SHADOW/etc/shadow.conf /etc/shadow.conf

Page 62: 025 Системный Администратор 12 2004

60

web

Наверное, не стоит говорить о том, какое большое распро-странение получил язык PHP в настоящее время. Преиму-щественно он используется в веб-программировании (соб-ственно, как и задумывалось его создателем). Надёжноукрепившись на серверах, теперь не спеша переходит и надесктопы. Об этом свидетельствуют как минимум две вещи:появление поддержки ncurses и проект PHP-GTK, о чём ипоговорим сегодня.

Данная статья ориентирована на достаточно широкийкруг читателей, так как в ней не рассматриваются какие-либо сложные аспекты. И может оказаться полезной какдля людей, желающих использовать PHP для написанияприложений с графическим интерфейсом пользователя, вы-полняющихся на клиентской стороне, так и для тех, кто про-сто желает начать изучение GTK.

PHP-GTK представляет собой расширение (модуль), по-зволяющее создавать приложения с оконным графическиминтерфейсом. Стоит заметить, что данное расширение явля-ется кроссплатформенным, речь идёт не только о *nix-подоб-ных системах, но и Win. Всю документацию, исходные кодыили же откомпилированное расширение вы найдёте на сай-те проекта – gtk.php.net.

Что такое GTK?Итак, что же такое GTK? На самом деле в данном случаеправильней было бы говорить о GTK+. GTK представляетсобой набор библиотек, используемых для создания окон-ного графического интерфейса пользователя. Основнымотличием GTK+ от GTK является объектная ориентирован-ность и наличие механизма сигналов. Аббревиатура GTKозначает – GIMP Toolkit, так как изначально разрабатыва-лась для GIMP (в рамках одноименного проекта).

GTK+ основывается на двух основных понятиях: виджети сигнал.

Виджетом называется любой компонент графического

интерфейса, будь то кнопка, поле ввода или окно. Все вид-жеты наследуются от абстрактного класса GtkWidget. Вид-жеты, которые могут содержать другие виджеты, называ-ются контейнерами. Предком контейнеров является GtkContainer (сам же GtkContainer наследуется от GtkWidget).

Сигналами называются сообщения, создаваемые вид-жетами. Сигналы используются для того, чтобы реагиро-вать на действия пользователя. Например, при появлениикурсора над кнопкой – экземпляром класса GtkButton, ге-нерируется сигнал «enter», а при нажатии – сигнал «clicked».Сигналы наследуются. Для обработки сигналов использу-ются callback-фукции. Не стоит путать сигналы с события-ми. Сигналы существуют в рамках GTK. А события являют-ся отражением механизма событий в оконной системе.

Итак, несколько «оглядевшись», можно приступить и кпримерам.

Напишем простейшее приложение.

PHP-GTK

АНДРЕЙ УВАРОВ

<?phpif( !extension_loaded('gtk')) { dl( 'php_gtk.' . PHP_SHLIB_SUFFIX);}$window = &new GtkWindow();$window->show();gtk::main();

?>

Page 63: 025 Системный Администратор 12 2004

61№12(25), декабрь 2004

web

Разберём нашу программу «по косточкам».Осуществляем проверку, загружено ли уже расшире-

ние, если нет, то загружаем его.

Создаём экземпляр класса GtkWindow – окно. И осуще-ствляем его отображение вызовом метода show(). Если раз-мер окна не устанавливается в программе, как в нашемслучае, то используется размер по умолчанию – 200х200.То же касается и заголовка окна, по умолчанию это имяскрипта.

Вызовом gtk::main() мы «включаем» основной цикл про-граммы, то есть программа начинает слушать события. Безэтой строки наше приложение просто отобразило бы окнои завершило на этом свою работу.

Если вы попробуете закрыть приложение, то оно всё рав-но не завершит работу, так как сигнал о завершении вы-полнения игнорируется

Для нормального завершения мы должны были обра-батывать сигнал «destroy» объекта window.

Итак, овладев основами, можно приступить к рассмот-рению чуть более сложного примера.

Особый интерес для нас в данном случае представляетметод connect_object(). Данный метод осуществляет при-соединение callback-функции к нужному сигналу. По свое-му назначению метод connect_object() сходен с connect()(оба метода наследуются от GtkObject). Строку:

Можно было бы заменить вызовом метода connect(), нопри этом нам было бы необходимо определять функциюдля обработки сигнала «destroy».

Первым параметром connect() является имя сигнала,вторым – имя callback-функции.

Напишем похожую программу, только уже на языкеPython.

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

На данный момент PHP-GTK существует только дляPHP4, но сейчас ведётся разработка следующей версии, вкоторой будет реализована поддержка GTK2 и PHP5, чтовыглядит весьма перспективно.

if( !extension_loaded('gtk')) { dl( 'php_gtk.' . PHP_SHLIB_SUFFIX);}

$window = &new GtkWindow();$window->show();

<?phpif( !extension_loaded('gtk')) { dl( 'php_gtk.' . PHP_SHLIB_SUFFIX);}function button_click(&$text){

$window = &new GtkWindow();// óñòàíàâëèâàåì çàãîëîâîê îêíà$window->set_title('Message');// óñòàíàâëèâàåì ðàçìåð îêíà$window->set_usize(200, 30);$label = &new GtkLabel($text->get_text());// äîáàâëÿåì îáúåêò â êîíòåéíåð$window->add($label);$window->show_all();

}$mainwindow = &new GtkWindow();// óñòàíàâëèâàåì çàãîëîâîê îêíà$mainwindow->set_title('Hello world');$mainwindow->connect_object('destroy', Array('gtk', ↵↵↵↵↵

'main_quit'));// Ýòîò êëàññ ÿâëÿåòñÿ ñïåöèàëüíûì êîíòåéíåðîì,// êîòîðûé ïîçâîëÿåò ðàçìåùàòü ïî ãîðèçîíòàëè// äîáàâëåííûå â íåãî îáúåêòû.$box = &new GtkHBox();$button = &new GtkButton('press me');$entry = &new GtkEntry();$button->connect_object('clicked', 'button_click', ↵↵↵↵↵

$entry);$box->pack_start($entry);$box->pack_end($button);$mainwindow->add($box);$mainwindow->show_all();gtk::main();

?>

sample.py:import gtkdef button_click(text):

window = gtk.Window()window.set_title("Message")window.set_usize(200, 30)label = gtk.Label(text.get_text())window.add(label)window.show_all()

def main_quit(object):gtk.main_quit()

mainwindow = gtk.Window()mainwindow.set_title("Hello world")mainwindow.connect("destroy", main_quit)box = gtk.HBox()button = gtk.Button("press me")entry = gtk.Entry()button.connect_object("clicked", button_click, entry)box.pack_start(entry)box.pack_end(button)mainwindow.add(box)mainwindow.show_all()gtk.main()

$mainwindow->connect_object('destroy', Array('gtk', ↵↵↵↵↵'main_quit'));

...function mainDestroy(){

gtk::main_quit();}:...$mainwindow->connect('destroy', 'mainDestroy');...

Page 64: 025 Системный Администратор 12 2004

62

web

Согласитесь, что адрес http://site.ru/news/page2.html намногоудобнее, чем http://site.ru/cgi-bin/news/view.cgi?page=2. Пер-вый из них гораздо легче запомнить, записать, продикто-вать по телефону. В этой статье я хотел бы рассмотретьнаиболее доступные приёмы перенаправления http-запро-сов, делая упор на способы их обработки.

Знакомство с проблемойКогда обсуждается некая обработка запроса, конечно, под-разумевается, что на сервере есть какие-то активные эле-менты (программы, сценарии...), способные обработать зап-рос и обеспечить определённую «реакцию». Программыобычно получают необходимую информацию либо со стан-дартного потока ввода (при запросе POST), либо из строкизапроса, содержащейся в адресе справа от вопроситель-ного знака (при запросе GET). Эти механизмы передачи дан-ных прекрасно известны, документированы, поддержаны внеисчислимом множестве модулей и библиотек, и я не будукасаться их в настоящей статье. Я как раз хотел бы обсу-дить другие возможности, позволяющие передать инфор-мацию на сервер. То есть мы будем запускать сценарии,формировать веб-страницы динамически, но не будем вклю-чать в адрес ни знака вопроса, ни строку запроса. МетодPOST мы тоже использовать не будем.

Как же в таком случае передать скрипту информацию?Ответ прост: через адрес. То есть мы рассмотрим приёмы,позволяющие вызвать один и тот же скрипт, используя раз-ные адреса; а также обсудим, как скрипт может получитьинформацию о том, по какому адресу он был вызван наэтот раз. Обсудим, какие дополнительные возможностиобеспечивает такой способ управления скриптами.

Я буду ориентироваться не на администраторов серве-ров, полномочия которых практически безграничны, а нагораздо более многочисленную армию веб-мастеров, кото-рые обычно пользуются готовым хостингом и имеют огра-ниченный доступ к настройкам сервера. В этой статье мырассмотрим только те возможности, которые могут быть на-строены в файле .htaccess. Конечно, все описываемые при-ёмы доступны и администраторам.

Материал расположен в порядке от простого и широкоизвестного к более сложному. Читатели, частично знако-мые с вопросом, могут пропустить первые разделы, прак-тически ничего не теряя.

Несколько слов о файле .htaccessФайл .htaccess – это просто текстовый файл, который раз-мещается в одной директории с веб-документами или сце-нариями. То есть для его редактирования вполне достаточ-

ОБРАБОТКА ПЕРЕАДРЕСОВАННЫХHTTP-ЗАПРОСОВОБРАБОТКА ПЕРЕАДРЕСОВАННЫХHTTP-ЗАПРОСОВ

АЛЕКСЕЙ МИЧУРИН

Page 65: 025 Системный Администратор 12 2004

63№12(25), декабрь 2004

web

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

Вообще говоря, использование имени .htaccess совсемне обязательно. Ваш сервер может быть настроен на ис-пользование другого имени вместо .htaccess. Настройкапроизводится инструкцией:

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

Какие настройки можно производить в .htaccess? От-вет зависит от нравов администратора. Все конфигураци-онные инструкции Apache, допустимые в .htaccess, поде-лены на категории. Администратор обычно даёт пользова-телю только часть полномочий, разрешая ему изменять на-стройки, принадлежащие только к определённым катего-риям. Настройка этих ограничений производится инструк-цией:

Поэтому прежде чем писать свой .htaccess, осведоми-тесь у администратора сервера, какие категории настроеквам доступны.

Существует всего пять категорий:! AuthConfig – директивы, отвечающие за организацию

авторизованного доступа;! FileInfo – директивы, управляющие обработкой ошибок

и отвечающие за информацию о языках и кодировках ипрочее;

! Indexes – команды, отвечающие за доступ к директори-ям, то есть за те случаи, когда файл в адресе не указан;

! Limit – команды, позволяющие ограничить доступ к ре-сурсу, например, закрыть или открыть доступ для кли-ентов, имеющих определённые IP-адреса;

! Options – всего две инструкции Options и XBitHack; пер-вая регламентирует работу механизмов CGI, SSI и ав-томатического составления листинга директорий; вто-рая управляет реакцией SSI-процессора на атрибутфайла «исполняемый» и используется весьма редко.

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

Директива DirectoryIndexНачнём наш экскурс с самой простой возможности, о кото-рой знают практически все. Директива DirectoryIndex при-

надлежит к категории Indexes и служит для определенияфайлов, выступающих в роли традиционного index.html.

Если .htaccess, расположенный в некоторой директории,содержит инструкцию:

то при обращении к этой директории (без указания файла)сервер действует по следующему алгоритму: сперва онбудет искать файл index.html, если таковой существует, тобудет выдан клиенту, в противном случае, сервер выдастрезультат выполнения сценария /cgi-bin/index.cgi. Если и пос-ледний не существует, то клиент получит сообщение обошибке 404.

Если разместить такой .htaccess сразу в двух директо-риях /one/ и /two/, то и по адресу /one/, и по адресу /two/клиент получит результат работы /cgi-bin/index.cgi (есте-ственно, если соответствующий index.html не найден). Мывызываем один и тот же скрипт по разным адресам. Дляполучения такого эффекта может быть достаточно и од-ного подобного .htaccess. В нашем случае и для директо-рии /one/first/, и /one/second/ в отсутствии index.html будетвызван /cgi-bin/index.cgi.

Для нас существенно то, что сценарий /cgi-bin/index.cgi,кроме обычных переменных окружения, получит две допол-нительные: REDIRECT_URL и REDIRECT_STATUS. Перваябудет содержать запрошенный адрес без имени сервера.Вторая – статус (обычно 200). То есть сценарий может «оп-ределить», для какой директории он вызван, и совершитьадекватные действия. Например, для одних директорий(скажем, с html-документами) он может составлять индекс,придавая ему должный вид и включая в него только опре-делённые файлы, а для других директорий (допустим, с гра-фикой) он будет перенаправлять пользователя на первуюстраницу или выдавать сообщение об ошибке.

Для полноты картины осталось только сказать о пере-менной REDIRECT_QUERY_STRING: она практически эк-вивалентна QUERY_STRING (о которой мы договорилисьне упоминать в этой статье). Если в директории /paper сер-вера paper.ru в файле .htaccess находится инструкция:

то при запросе адреса http://paper.ru/paper?string=data илиhttp://paper.ru/paper/?string=data, как вы уже догадались, бу-дет вызван сценарий /cgi-bin/index.cgi, но наряду с перемен-ной QUERY_STRING ему будет передана ещё и REDIRECT_QUERY_STRING. Обе они будут равны строке запроса, внашем примере string=data. Разница между этими перемен-ными состоит только в том, что когда строка запроса отсут-ствует, переменная QUERY_STRING существует, но равнапустой строке, а REDIRECT_QUERY_STRING не существу-ет вовсе.

Обработка ошибок.Директива ErrorDocumentДиректива ErrorDocument принадлежит к категории FileInfoи предназначена для определения файлов, выдаваемыхклиенту, если обработка запроса вызвала ошибку.

AccessFileName èìÿ_ôàéëà

AllowOverride ñïèñîê_êàòåãîðèé_èëè_All_èëè_None

DirectoryIndex index.html /cgi-bin/index.cgi

DirectoryIndex /cgi-bin/index.cgi

Page 66: 025 Системный Администратор 12 2004

64

web

Если добавить в .htaccess инструкцию:

то при возникновении ошибки 404 будет выполнен сцена-рий /cgi-bin/error.cgi. Ему будут переданы четыре дополни-тельные переменные:! REDIRECT_REQUEST_METHOD – метод, которым был

выполнен ошибочный запрос;! REDIRECT_STATUS – статус, его удобно использовать

в обработчиках, предназначенных для ошибок разноготипа, очевидно, в нашем случае статус может равнять-ся только 404;

! REDIRECT_URL – адрес несуществующего ресурса безимени сервера, этот адрес, например, можно использо-вать для регистрации в журнале;

! REDIRECT_ERROR_NOTES – сообщение об ошибке.

Кроме того, при наличии строки запроса создаётся пе-ременная REDIRECT_QUERY_STRING, описанная выше.

Эти переменные удобно использовать не только в CGI-сценариях, но в SSI-документах. Так, если создать .htaccessс директивой:

а в файле /error/404.shtml разместить следующий SSI-код:

то при обращении к несуществующему файлу /is_it_is.htmlклиент получит следующее сообщение:

Ещё один пример обработчика ошибок мы увидим ужев следующем разделе. А здесь осталось добавить, что ди-ректива ErrorDocument допускает и другой синтаксис:

При возникновении ошибки пользователю будет выда-но указанное сообщение. Никакого перенаправления приэтом не происходит, сервер сам генерирует соответствую-щий документ.

Обратите внимание, закрывающей кавычки в указан-ной директиве нет.

Авторизованный доступПрежде всего, скажу несколько слов о том, как активизи-ровать механизм авторизации. Чтобы ограничить доступ кнекоторой директории (и ко всем вложенным директори-ям), следует написать в .htaccess приблизительно такие ин-струкции:

Все они, как вы, наверное, догадались, принадлежат ккатегории AuthConfig.

Первая из них задаёт тип процедуры авторизации, напрактике используется только Basic.

Вторая инструкция задаёт текст, который отобразит бра-узер в окне диалога.

Директива AuthUserFile определяет файл с паролямипользователей, который легко создать с помощью утилитыhtpasswd, входящей в поставку Apache. Обратите внима-ние, файл паролей в целях безопасности можно (и жела-тельно!) размещать вне дерева директорий, доступных че-рез Web.

Директива Require регламентирует, какие пользовате-ли или группы пользователей имеют доступ к данному ре-сурсу. В приведённом примере я позволил всем пользова-телям (конечно, только если они пройдут процедуру авто-ризации) обращаться к файлам и подкаталогам директо-рии, где размещён наш .htaccess.

Техника ограничения доступа описана многократно, и яне хотел бы повторять здесь других авторов. Для нас будетважно то, что когда клиент работает в директории автори-зованно, сервер создаёт ещё две дополнительные перемен-ные: REMOTE_USER и AUTH_TYPE. Первая, как вы пони-маете, содержит имя пользователя, вторая – тип авториза-ции (Basic).

Если несколько пользователей имеют доступ к одномуресурсу, то переменную REMOTE_USER удобно использо-вать в системах хранения персональных настроек или дляведения журналов.

Эти переменные доступны и CGI-сценариям, и SSI-до-кументам. Например, страница enter.shtml:

Будет выглядеть так:

ErrorDocument 404 /error/404.shtml

<html><head><title>404</title></head><body><h1>Ôàéë íå íàéäåí!</h1>Ôàéë <b><!--#echo var="REDIRECT_URL" --></b> áûë çàïðîøåíìåòîäîì <b><!--#echo var="REDIRECT_REQUEST_METHOD" --></b>.Çàïðîñ áûë ïåðåíàïðàâëåí íà ýòîò äîêóìåíò ñî ñòàòóñîì<b><!--#echo var="REDIRECT_STATUS" --></b>. Ïîëíàÿ äèàãíîñòèêàòàêîâà: <b><!--#echo var="REDIRECT_ERROR_NOTES" --></b>.(âñå èñïîëüçîâàííûå ïåðåìåííûå äîñòóïíû è â CGI)</body></html>

ErrorDocument 404 "Sorry. File not found

AuthType BasicAuthName "By Invitation Only"AuthUserFile /home/www/paper/secret/passwdRequire valid-user

<html><head><title>Enter</title></head><body><h1>Hi, <!--#echo var="REMOTE_USER" -->!</h1><p>(AUTH_TYPE=<!--#echo var="AUTH_TYPE" -->)</p></body></html>

ErrorDocument 404 /cgi-bin/error.cgi

Page 67: 025 Системный Администратор 12 2004

65№12(25), декабрь 2004

web

После успешной авторизации переменные REMOTE_USER и AUTH_TYPE передаются и обработчикам ошибок вдополнение ко всем перечисленным выше, содержащиминформацию об ошибке. Эта передача происходит даже втом случае, если обработчик находится за пределами за-секреченной области (ошибка, конечно, должна произойтив засекреченной области).

При неудачной авторизации возникает ошибка 401, длякоторой тоже может быть назначен обработчик:

или

Мне осталось только заметить, что пользователи могутбыть объединены в группы. Для этого существует директи-ва AuthGroupFile. Так вот, информация о том, к какой груп-пе принадлежит пользователь, не передаётся сценарию.

Применение PATH_INFOСервер Apache (и не только он) предоставляет интереснуювозможность: если существует сценарий /cgi-bin/script.cgi,то любой адрес вида /cgi-bin/script.cgi/location/doc.ext счита-ется вполне допустимым. При его обработке выполняетсясценарий /cgi-bin/script.cgi, а строка /location/doc.ext переда-ётся ему в переменной PATH_INFO. Кроме неё, создаётсяпеременная PATH_TRANSLATED, содержащая как бы путьк запрашиваемому файлу относительно корня файловойсистемы сервера. Если в нашем примере предположить, чтодокументы сервера расположены в директории /www/docs,то PATH_TRANSLATED будет содержать путь /www/docs/location/doc.ext.

Путь, который был на самом деле запрошен клиентом,как обычно, доступен через переменную REQUEST_URI.

Эта возможность находит самые разные применения.Например, вы можете хранить все документы в кодировкеКОИ-8, и их CP-1251-модификации создавать «на лету»,используя виртуальные пути вида /cgi-bin/koi2win.cgi/...Единственное, что может доставить вам хлопоты – для ре-ализации такого подхода потребуется все перекрёстныессылки в документах делать относительными, а все адресаграфических и мультимедийных объектов, CSS-, JS-компо-нент делать абсолютными. В противном случае вам при-дётся сделать сценарий koi2win.cgi чуть умнее, чем простоперекодировщик: он должен будет правильно (без искаже-ний) передавать файлы, не являющиеся HTML-документа-ми и не требующие перекодировки, что, впрочем, не так ужсложно реализовать.

Другое применение – хранение в виртуальном пути не-кой информации (например, идентификатора сессии). Это

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

Пример такого сценария я и хочу привести:

Как видите, сценарий выделяет из строки PATH_INFO(сохранённой в переменной $path) два последние элемен-та пути. Первая из этих частей интерпретируется как цвет(сохраняется в переменой $color), вторая – как имя файла(переменная $file), её можно было бы использовать дляподключения определённого содержания.

В цикле foreach мы создаём небольшое навигационноеменю с относительными ссылками.

Разместим наш сценарий по адресу: /cgi-bin/pi.cgi.Теперь по адресу /cgi-bin/pi.cgi/gray/3.html мы увидим:

Код страницы таков:

Как видите, все ссылки «указывают» тоже на серые

#!/usr/bin/perluse strict;my ($path, $script) = @ENV{qw/PATH_INFO SCRIPT_NAME/};my ($color, $file) = $path=~m|/([^/]+)/([^/]+)$|;my $html_list='';foreach (1..5) {

$html_list .= <<"TEXT";<li><a href="$_.html">$_.html</a></li>TEXT}print <<"TEXT";Content-Type: text/html<html><head><title>$script</title></head><body text="$color" bgcolor="white" link="$color" vlink="$color"><h1>$file</h1><ul>$html_list</ul></body></html>TEXT

<html><head><title>/cgi-bin/pi.cgi</title></head><body text="gray" bgcolor="white" link="gray" vlink="gray"><h1>3.html</h1><ul><li><a href="1.html">1.html</a></li><li><a href="2.html">2.html</a></li><li><a href="3.html">3.html</a></li><li><a href="4.html">4.html</a></li><li><a href="5.html">5.html</a></li></ul></body></html>

ErrorDocument 401 /error/401.shtml

ErrorDocument 401 /cgi-bin/error.cgi

Page 68: 025 Системный Администратор 12 2004

66

web

документы, вернее, они оставляют информацию о цвете(путь) неизменной.

По адресу /cgi-bin/pi.cgi/red/1.html мы обнаружим анало-гичную структуру «красных документов».

Мысль, намеченную в этом сценарии, легко развить внеобходимом русле. Единственное, о чем следует позабо-титься – это безопасность. Отсутствие хотя бы каких-ни-будь проверок в сценарии pi.cgi чревато только комичнымиситуациями. Например, такой: /cgi-bin/pi.cgi/white/1.html. Ноесли ваш сценарий работает с файлами, то всегда надобыть готовым к тому, что кто-то запросит документ /cgi-bin/koi2win.cgi/../../../etc/passwd. Конечно, конкретно эта атаканаивна и, скорее всего, не представляет серьёзной опас-ности, хотя всё зависит от того, как устроен koi2win.cgi.

Замечу ещё, что всё сказанное справедливо не толькодля CGI-сценариев, но и для SSI-документов. При обраще-нии к ресурсу /dir/doc.shtml/data (конечно, предполагается,что doc.shtml не директория, а SSI-документ) будут такжесозданы две дополнительные переменные PATH_INFO иPATH_TRANSLATED.

Кроме того, SSI-процессором всегда создаётся перемен-ная DOCUMENT_PATH_INFO, которая пуста, если PATH_INFOи PATH_TRANSLATED отсутствуют.

Я думаю, что у внимательного читателя уже возник воп-рос, можно ли усовершенствовать наше решение так, что-бы избежать таких «неповоротливых» адресов, превратив,например, /cgi-bin/pi.cgi/gray/3.html в /color/gray/3.html. От-вет на этот вопрос – да, возможно. Как раз это обсуждает-ся в следующем разделе.

Магия ActionНаверное, самые большие возможности предоставляет ди-ректива Action. С её помощью вы можете назначить скрипт-обработчик для определённых типов файлов.

Приведу пример. Напишем в .htaccess следующие ди-рективы:

Обе директивы, содержащиеся в этом файле, принад-лежат к категории FileInfo.

Первая – добавляет новый дескриптор файла, ассоции-рованный с расширением .para. Теперь все файлы *.paraбудут ассоциироваться с манипулятором my-handler. Осо-бенностью директивы AddHandler является то, что она нечувствительна к регистру, то есть распространяется в рав-ной мере и на файлы *.Para, *.PARA, *.PaRa и так далее.Кроме того, символ «точка» необязателен.

Вторая директива – Action – назначает действие, кото-рое необходимо выполнять для файлов, ассоциированныхс манипулятором my-handler. Теперь любое обращение кфайлу *.para должно приводить к запуску сценария /cgi-bin/para.cgi.

Для полноты картины добавлю, что вместо дескрипто-ра можно использовать MIME-тип. В принципе, нетруднопредставить случаи, когда это будет удобно. Например, выподдерживаете публичный хостинг и хотите, чтобы ко всемстраницам ваших клиентов автоматически добавлялся бан-нер. Тогда проще привязать обработчик html-документов

не к двум расширениям (.html и .htm), а к одному-единствен-ному MIME-типу (text/html).

С содержимым .htaccess разобрались, давайте теперьрассмотрим /cgi-bin/para.cgi.

Если разместить наш .htaccess в директории /action, топри обработке адреса /action/1.para будет выполнен сцена-рий /cgi-bin/para.cgi, которому будет передан целый ряддополнительных переменных:! PATH_INFO – содержит адрес запрошенной «страницы»,

в нашем случае это /action/1.para;! PATH_TRANSLATED – полное имя запрошенного фай-

ла, например, /www/docs/action/1.para;! REDIRECT_STATUS – если всё в порядке, то 200. Обра-

тите внимание: если файл 1.para не существует, то кодвсё равно будет 200. То есть сервер успешно запустилскрипт /cgi-bin/para.cgi, а существует ли файл 1.para –проблема скрипта.

! REDIRECT_URL – равно PATH_INFO.

Если в адресе содержалась ещё и строка запроса (на-пример, /action/1.para?subsection=3), то она не включаетсяв PATH_INFO и REDIRECT_URL, а попадает в переменныеQUERY_STRING и REDIRECT_QUERY_STRING, о которыхуже говорилось в начале статьи. Если вам понадобитсяполный адрес (вместе со строкой запроса), то ищите его,как обычно, в переменной REQUEST_URI.

Давайте разберём простенький пример. Пусть в файлах*.para будет храниться просто ASCII-текст, а скрипт /cgi-bin/para.cgi будет формировать html-документы из ASCII-тек-ста, производя с ним нехитрые преобразования: квотиро-вание небезопасных символов (&, «, >, <), добавление тега<br> в конце каждой строки, добавление тегов, открываю-щих и закрывающих html-документ. Имя файла, которыйследует обработать, сценарий будет брать из переменнойPATH_TRANSLATED. Код сценария таков:

Теперь, если в файле /action/1.para находится следую-щие три строки:

#!/usr/bin/perluse strict;my ($file, $url)=@ENV{qw/PATH_TRANSLATED REDIRECT_URL/};open FH, "<$file" or die;my $f=join('', <FH>);close FH;$f=~s/\&/&amp;/g;$f=~s/\</&lt;/g;$f=~s/\>/&gt;/g;$f=~s/\"/&quot;/g;$f=~s/\n/<br>\n/g;print <<"TEXT";Content-Type: text/html<html><head><title>$url</title></head><body><h1>$url</h1>$f</body></html>TEXT

"AAA"<BBB>CCC

AddHandler my-handler .paraAction my-handler /cgi-bin/para.cgi

Page 69: 025 Системный Администратор 12 2004

67№12(25), декабрь 2004

web

то по адресу /action/1.para браузер обнаружит результатработы нашего скрипта:

Выглядеть он будет так:

Как видите, текст корректно преобразован в HTML-до-кумент.

Вы, наверное, уже обратили внимание на то, что опи-санный подход очень похож на подход предыдущего разде-ла. Действительно, по адресу /cgi-bin/para.cgi/action/1.para мыувидим почти то же самое. «Почти» потому, что в этом слу-чае переменной REDIRECT_URL уже не будет. Если бы мыиспользовали вместо неё PATH_INFO, то скрипт вообще «непочувствовал» бы разницы, будь он вызван как /cgi-bin/para.cgi/action/1.para или как /action/1.para.

Но самое интересное – сходства этих двух подходов наэтом не заканчиваются. Оказывается, что и при Action-под-ходе сервер не проверяет, существует ли файл на самомделе! При обращении к любому файлу с расширением .para(в директории /action), независимо от того, существует лифайл, вызывается скрипт /cgi-bin/para.cgi. Даже REDIRECT_STATUS сохраняет значение 200. То есть все замечанияотносительно безопасности остаются в силе.

А теперь вопрос «на засыпку»: как отреагирует серверна запросы /action/dir/1.para, /action/dir.para/1.para, /action/dir.para/1.text?

Естественно, ни директории /action/dir, ни директории/action/dir.para не существует.

Правильный ответ таков: в первом случае возникнетошибка 404. Её бы не возникло, если бы /action/dir суще-ствовала, даже в том случае, если сам файл /action/dir/1.paraотсутствовал. Во втором и третьем случаях будет как ни вчем не бывало вызван скрипт /cgi-bin/para.cgi.

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

Например, мы можем создать директорию /color и раз-местить в ней .htaccess со следующей директивой:

<html><head><title>/action/1.para</title></head><body><h1>/action/1.para</h1>&quot;AAA&quot;<br>&lt;BBB&gt;<br>CCC</body></html>

Action text/html /cgi-bin/pi.cgi

Кстати, обратите внимание, в этом примере мы обо-шлись без директивы AddHandler, так как обработчик при-вязан к определённому MIME-типу.

Теперь мы можем запустить pi.cgi двумя способами.Первый – создать в директории /color директории, соот-

ветствующие необходимым цветам, скажем gray и green.Теперь по адресу /color/green/1.html мы обнаружим систе-му «зелёных» документов.

Обратите внимание: если директория /color/cyan не су-ществует, то запрос документа /color/cyan/1.html вызоветошибку 404.

Второй способ (внимание! это может быть потенциаль-ная дыра в системе безопасности) – обратиться по адре-су /color/hole.html/cyan/1.html. При этом директория hole.htmlне должна существовать. Теперь наличие расширения .htmlу директории hole.html приведёт к запуску pi.cgi, а он будетрассматривать только последние две компоненты пути –cyan и 1.html. Таким образом всё сработает «как часы». Такможно получить документ любого цвета, если на серверене выполняется никаких проверок (как это сделано в на-шем беспечном pi.cgi).

И снова обращаю ваше внимание на то, что если ди-ректория /color/hole.html существует, а /color/hole.html/cyanне существует, то по адресу /color/hole.html/cyan/1.html мыполучим ошибку 404.

ОграниченияВы видите, что сценарий или скрипт можно запустить нетолько «напрямую» (как /cgi-bin/forum.cgi), но и многимидругими вполне доступными способами. И кроме традици-онно используемой переменной QUERY_STRING серверсоздаёт множество полезных переменных, но не забывай-те, что использовать их надо не менее осторожно, чемQUERY_STRING.

Даже мои небольшие примеры не лишены изъянов. Так,я довольно опрометчиво встраиваю в HTML-код, создавае-мый SSI-процессором, такие переменные, как PATH_INFO.Подобные переменные задаются удалённым пользовате-лем. Не исключено, что он сформирует такой адрес, по ко-торому будет выдаваться HTML-документ, оснащённый вре-доносным JavaScript-кодом или иным аппаратом (иногда дляосуществления атаки оказывается достаточно считаныхбайт). Таким образом злоумышленник может скомбиниро-вать адрес, наделяющий ваш ресурс вредоносными свой-ствами. Никогда нельзя использовать напрямую перемен-ные, значение которых определяется удалённо.

Следует отметить, что описанный подход, будучи реа-лизован в чистом виде, практически полностью исключаетвозможность обработки форм. Это большой минус, но ниодин из перечисленных приёмов не лишает вас возможно-сти использовать переменную QUERY_STRING илиREDIRECT_QUERY_STRING и обрабатывать формы, от-правленные методом GET. Также к любому сценарию мож-но обратиться методом POST. Но самое главное, существу-ет широкий круг задач, ограничивающихся организациейнавигации и не предполагающих работу с формами (от лентновостей и фото-галерей до веб-каталогов). Именно в этихслучаях наиболее оправданно применение подходов, опи-санных в настоящей статье.

Page 70: 025 Системный Администратор 12 2004

68

hardware

Во второй части статьи рассмотрены примеры программ,выполняющих запись различной информации – музыкаль-ных треков и данных – на компакт-диск CD-R/RW.

Запись информации на компакт-диск

Запись данных на компакт-дискРассмотрим пример программы, выполняющей запись дан-ных на компакт-диск. Под термином «данные» понимаетсяфайл в формате ISO (файл-образ), полученный при помо-щи утилиты mkisofs или каким-либо другим способом.

Исходные тексты всех программ доступны на сайте жур-нала (www.samag.ru/source).

Алгоритм выполнения операции записи данных на ком-пакт-диск следующий:! Определяются текущие параметры режима записи уст-

ройства путем считывания страницы параметров режи-ма записи, код 0x05.

! Устанавливаются требуемые значения полей страницыпараметров режима записи – режим записи, тип блокаданных, режим трека (аудио/данные) и др.

! Из файла образа считываются блоки данных, и коман-да WRITE_10 выполняет запись этих блоков в соответ-ствующие сектора компакт-диска. Стартовый номер сек-тора, с которого начинается запись, равен 0. Размер бло-ка определяет значение поля «Data Block Type» страни-цы параметров режима записи (см. рис. 15 первой час-ти статьи).

! По окончании записи данных (достигнут конец файла-образа) последовательно выполняются команды SYNC-HRONIZE CACHE, CLOSE TRACK, CLOSE SESSION. Покоманде SYNCHRONIZE CACHE все данные, подлежа-щие записи, переносятся на носитель, кэш устройстваосвобождается. Команда CLOSE TRACK завершаеттрек, а CLOSE SESSION завершает сессию – формиру-ет Lead-In и Lead-Out-области сессии (диска).

Для определения текущих параметров устройства при-меняется команда MODE SENSE, а для установки парамет-ров – команда MODE SELECT. Формат команды MODESENSE приведен на рисунке:

Поле Page Code содержит код запрашиваемой страни-цы режимов, поле Allocation Length – размер считываемыхданных.

Формат команды MODE SELECT приведен на рисунке:

Поле Parameter List Length содержит размер передава-емого списка параметров в байтах. Бит PF (Page Format)установлен в единицу. Это означает, что формат страницысоответствует стандарту SCSI.

Запись данных на диск выполняет команда WRITE_10.Формат этой команды представлен на рис. 3.

ЗАПИСЬ ДИСКОВ CD-R/RW В LINUXЧАСТЬ 2

ВЛАДИМИР МЕШКОВ

Ðèñóíîê 1. Ôîðìàò êîìàíäû MODE SENSE

Ðèñóíîê 2. Ôîðìàò êîìàíäû MODE SELECT

Page 71: 025 Системный Администратор 12 2004

69№12(25), декабрь 2004

hardware

Назначение полей:! Logical Block Address – адрес блока, в который будет

записана информация.! Transfer Length – число блоков для записи на диск.

В команде SYNCHRONIZE CACHE используется тольконулевой байт – он содержит код операции 0x35.

Формат команды CLOSE TRACK/SESSION представленна рисунке:

Поле Close Function может принимать следующие зна-чения:! 001b – закрыть трек, номер которого указан в поле Track

Number.! 010b – закрыть последнюю незавершенную сессию, зна-

чение поля Track Number игнорируется.

Следующая структура описывает формат страницы па-раметров режима записи (см. рис. 15 в первой части ста-тьи):

Определим глобальные переменные:

Функция mode_sense() считывает страницу параметроврежима записи устройства:

Установку требуемых параметров режима записи вы-полняет функция mode_select(). Этой функции мы переда-ем два параметра – тип блока данных (поле dbt структурыwpm_t) и тип информации, находящейся в треке (полеtrack_mode структуры wpm_t):

typedef struct {__u8 page_code :6;__u8 rez :1;__u8 ps :1;__u8 page_length;__u8 write_type :4;__u8 test_write :1;__u8 ls_v :1;__u8 BUFE :1;__u8 rez1 :1;__u8 track_mode :4;__u8 copy :1;__u8 FP :1;__u8 multises :2;__u8 dbt :4;__u8 rez2 :4;__u8 link_size;__u8 rez3;__u8 hac :6;__u8 rez4 :2;__u8 s_format;__u8 rez5;__u32 packet_size;__u16 apl;__u8 mcn[16];

Ðèñóíîê 3. Ôîðìàò êîìàíäû WRITE_10

Ðèñóíîê 4. Ôîðìàò êîìàíäû CLOSE TRACK/SESSION

__u8 isrc[16];__u32 sh;

} __attribute__ ((packed)) wpm_t;

// äåñêðèïòîð ôàéëà sg-óñòðîéñòâàint sg_fd;// óêàçàòåëü íà äàííûå ñòðàíèöû ïàðàìåòðîâ ðåæèìà çàïèñèwpm_t *wpm;// çíà÷åíèå ïîëÿ Mode Data Length çàãîëîâêà Mode Parameter// Header__u16 mode_page_len = 0;// ðàçìåð ñïèñêà ñòðàíèö ðåæèìà Mode Parameter List � 8

áàéò// çàãîëîâêà ñïèñêà Mode Parameter Header + 52 áàéòà ñàìîé// ñòðàíèöû (ñì. ðèñ. 13-15, ïåðâîé ÷àñòè ñòàòüè)__u16 data_len = 60;// áëîê ïàìÿòè äëÿ ÷òåíèÿ ñïèñêà Mode Parameter List__u8 data_buff[60];

int mode_sense(){

__u8 mode_sense_cmd[10];/* Óñòðîéñòâà ãîòîâî? */

if(test_unit_ready() < 0) exit(-1);memset(data_buff, 0, 60);// wpm óêàçûâàåò íà íà÷àëî ñòðàíèöû ïàðàìåòðîâ ðåæèìà// çàïèñèwpm = (void *)(data_buff + 8);

/* Ôîðìèðóåì êîìàíäûé ïàêåò */memset(mode_sense_cmd, 0, 10);// êîä êîìàíäû MODE SENSEmode_sense_cmd[0] = MODE_SENSE_10;// êîä ñòðàíèöû ïàðàìåòðîâ ðåæèìà çàïèñèmode_sense_cmd[2] = 5;// ðàçìåð äàííûõ - 60 áàéòmode_sense_cmd[8] = data_len;

/* Ïîñûëàåì êîìàíäó óñòðîéñòâó */if(send_cmd(mode_sense_cmd, 10, SG_DXFER_FROM_DEV, ↵↵↵↵↵

data_buff, data_len, 20000) < 0) return -1;/* Ðàçìåð ñ÷èòàííûõ äàííûõ � çíà÷åíèå ïîëÿ Mode Data Length* çàãîëîâêà ñïèñêà ñòðàíèö*/

memcpy((void *)&mode_page_len, data_buff, 2);mode_page_len = __swab16(mode_page_len);printf("Mode data length - %d\n", mode_page_len);

/* Îòîáðàçèì òåêóùèå ïàðàìåòðû ðåæèìà çàïèñè */// êîä ñòðàíèöûprintf("Page code - %d\n", wpm->page_code);// ðàçìåð ñòðàíèöûprintf("Page length - %d\n", wpm->page_length);// ðåæèì çàïèñèprintf("Write type - %d\n", wpm->write_type);// òèï áëîêà äàííûõprintf("Data block type - %d\n", wpm->dbt);// ôîðìàò ñåññèèprintf("Session format - %d\n", wpm->s_format);// ðåæèì òðåêà (ïîëå Control Field)printf("Track mode - %d\n", wpm->track_mode);return 0;

}

int mode_select(__u8 dbt, __u8 track_mode){

__u8 mode_select_cmd[10];

Page 72: 025 Системный Администратор 12 2004

70

hardware

Запись данных на компакт-диск выполняет функцияwrite_iso(). Входные параметры функции – указатель настроку, содержащую имя файла-образа:

По окончании записи данных необходимо, как было ужесказано выше, послать устройству три команды: SYNCHRO-

NIZE CACHE, CLOSE TRACK, CLOSE SESSION. КомандуSYNCHRONIZE CACHE формирует и посылает устройствуфункция sync_cache():

Закрывает трек функция close_track():

Функция close_session() закрывает текущую сессию:

После того как данные записаны, извлекаем компакт-диск из привода, послав устройству команду START/STOPUNIT (см. [5]):

/* Îïðåäåëÿåì òåêóùèå ïàðàìåòðû ðåæèìà çàïèñè */if(mode_sense() < 0) exit(-1);

/* Óñòàíàâëèâàåì ïàðàìåòðû äëÿ çàïèñè äàííûõ */wpm->write_type = 1; // ðåæèì çàïèñè � TAOwpm->dbt = dbt; // òèï áëîêà äàííûõwpm->s_format = 0; // îòêðûòèå íîâîé ñåññèè çàïðåùåíîwpm->track_mode = track_mode; // ðåæèì òðåêà

/* Óñòðîéñòâî ãîòîâî? */if(test_unit_ready() < 0) exit(-1);

/* Ôîðìèðóåì êîìàíäíûé ïàêåò */memset(mode_select_cmd, 0, 10);// êîä êîìàíäû MODE SELECTmode_select_cmd[0] = MODE_SELECT_10;// óñòàíàâëèâàåì â 1 áèò PF (Page Format)mode_select_cmd[1] = 1 << 4;

/* Â ïîëå Parameter List Header çàïèñûâàåì ðàçìåð áëîêà* äàííûõ*/

data_len = 60;mode_page_len = __swab16(data_len);memcpy((void *)(mode_select_cmd + 7), ↵↵↵↵↵

(void *)&mode_page_len, 2);/* Ïîñûëàåì óñòðîéñòâó êîìàíäó */

if(send_cmd(mode_select_cmd, 10, SG_DXFER_TO_DEV, ↵↵↵↵↵data_buff, data_len, 20000) < 0) return -1;

/* Äëÿ êîíòðîëÿ îòîáðàçèì óñòàíîâëåííûå ïàðàìåòðû ðåæèìà* çàïèñè*/

if(mode_sense() < 0) exit(-1);return 0;

}

int sync_cache(){

__u8 flush_cache[10];if(test_unit_ready() < 0) exit(-1);

/* Ôîðìèðóåì è ïîñûëàåì êîìàíäó */memset(flush_cache, 0, 10);flush_cache[0] = SYNCHRONIZE_CACHE; // êîä êîìàíäûif(send_cmd(flush_cache, 10, SG_DXFER_NONE, ↵↵↵↵↵

NULL, 0, 20000) < 0) return -1;return 0;

}

int close_track(){

__u8 close_trk_cmd[10];if(sync_cache() < 0) {printf("Cannot synchronize cache\n");return -1;}if(test_unit_ready() < 0) exit(-1);

/* Ôîðìèðóåì êîìàíäó çàêðûòèÿ òðåêà è ïîñûëàåì* åå óñòðîéñòâó*/

memset(close_trk_cmd, 0, 10);close_trk_cmd[0] = 0x5B; // êîä êîìàíäû CLOSE TRACKclose_trk_cmd[2] = 1; // ôëàã çàêðûòèÿ òðåêàclose_trk_cmd[5] = 1; // íîìåð òðåêà, îí ó íàñ îäèíif(send_cmd(close_trk_cmd, 10, SG_DXFER_NONE, ↵↵↵↵↵

NULL, 0, 20000) < 0) return -1;return 0;

}

int write_iso(__u8 *file_name){

int in_f;__u8 write_cmd[10];__u8 write_buff[CD_FRAMESIZE];__u32 lba = 0, lba1 = 0;if(test_unit_ready() < 0) exit(-1);

/* Îòêðûâàåì ôàéë-îáðàç */in_f = open(file_name, O_RDONLY, 0600);memset(write_buff, 0, CD_FRAMESIZE);

/* Öèêë ÷òåíèÿ áëîêîâ äàííûõ èç ôàéëà.* Ðàçìåð áëîêà � 2048 áàéò*/

while(read(in_f, write_buff, CD_FRAMESIZE) > 0) {/* Ôîðìèðóåì êîìàíäíûé ïàêåò */

memset(write_cmd, 0, 10);write_cmd[0] = WRITE_10; // êîä êîìàíäûwrite_cmd[8] = 1; // êîëè÷åñòâî ñåêòîðîâ äëÿ çàïèñèprintf("%c", 0x0D);printf("lba - %6d", lba1);

/* Àäðåñ áëîêà äëÿ çàïèñè */lba = __swab32(lba1);memcpy((write_cmd + 2), (void *)&lba, 4);lba1 += 1;

/* Ïîñûëàåì óñòðîéñòâó êîìàíäó */if(send_cmd(write_cmd, 10, SG_DXFER_TO_DEV, write_buff, ↵↵↵↵↵

CD_FRAMESIZE, 20000) < 0) return -1;}printf("\n");return 0;

}

int close_session(){

__u8 close_sess_cmd[10];if(test_unit_ready() < 0) exit(-1);memset(close_sess_cmd, 0, 10);close_sess_cmd[0] = 0x5B; // êîä êîìàíäû CLOSE SESSIONclose_sess_cmd[2] = 2; // ôëàã çàêðûòèÿ òåêóùåé ñåññèèif(send_cmd(close_sess_cmd, 10, SG_DXFER_NONE, ↵↵↵↵↵

NULL, 0, 60000) < 0) return -1;return 0;

}

void eject_cd(){

__u8 start_stop_cmd[6];memset(start_stop_cmd, 0, 6);start_stop_cmd[0] = 0x1B; // êîä êîìàíäû START/STOP UNITstart_stop_cmd[4] = 2; // èçâëå÷ü êîìïàêò-äèñêsend_cmd(start_stop_cmd, 6, SG_DXFER_NONE, NULL, 0, 20000);return;

}

Page 73: 025 Системный Администратор 12 2004

71№12(25), декабрь 2004

hardware

Имя файла-образа передается главной функции про-граммы в виде параметра. Функция main() выглядит следу-ющим образом:

Полный текст программы записи ISO-образа на компакт-диск находится в файле SG/iso_write.c.

Запись аудиоданныхАлгоритм записи аудиоданных практически не отличаетсяот приведенного ранее алгоритма записи данных. Но таккак в одной сессии теперь будет находиться несколько тре-ков, то при записи аудиотрека на компакт-диск необходи-мо будет знать стартовый адрес трека. Этот адрес можновычислить самостоятельно, можно определить его как ад-рес невидимого, незавершенного трека (invisible, incompletetrack) либо предварительно зарезервировать на компакт-диске пространство для каждого трека.

Резервирование пространства для трека выполняет ко-манда RESERVE TRACK. Формат этой команды представ-лен на рисунке:

В поле Reservation size указывается размер трека в бло-ках. Каждый вызов команды RESERVE TRACK модифици-рует PMA-область, добавляя в нее запись о координатах

нового трека (таблица 4 первой части статьи). Считать ин-формацию о координатах трека можно при помощи коман-ды READ TRACK INFORMATION. Формат команды:

Значение поля Address/Number Type определяет содер-жание поля Logical Block Address/Track/Session Number. ЕслиAddress/Number Type = 01b, то устройство вернет блок ин-формации о треке, номер которого находится в поле LogicalBlock Address/Track/Session Number. Формат блока инфор-мации о треке представлен на рис. 7.

Из всего многообразия данных, находящихся в блоке,нас интересует только поле Track Start Address. Это полесодержит стартовый адрес трека, с этого адреса выполня-ется запись трека. Назначение остальных полей приведе-но в спецификации SCSI MMC-4 ([1]).

Функция reserv_track() выполняет резервирование накомпакт-диске пространства для трека. Входной параметрфункции – размер трека в блоках.

Ðèñóíîê 7. Ôîðìàò áëîêà èíôîðìàöèè î òðåêå

int main(int argc, char **argv){/* Ïðîâåðÿåì íàëè÷èå âõîäíûõ ïàðàìåòðîâ */

if(argc != 2) {printf("\n\tUsage: write_iso [ISO-image]\n\n");return 0;}

/* Îòêðûâàåì ôàéë sg-óñòðîéñòâà */if((sg_fd = open(SG_DEV, O_RDWR)) < 0) {

perror("open");return -1;

}/* Óñòàíàâëèâàåì ïàðàìåòðû ðåæèìà çàïèñè äàííûõ:* òèï áëîêà äàííûõ dbt = 8 � ôîðìàò áëîêà Mode 1, ðàçìåð* áëîêà 2048 áàéò;* òèï èíôîðìàöèè, íàõîäÿùåéñÿ â òðåêå track_mode = 4 �* òðåê ñîäåðæèò äàííûå.*/

mode_select(8, 4);/* Âûïîëíÿåì çàïèñü äàííûõ íà êîìïàêò-äèñê */

if(write_iso(argv[1]) < 0) {printf("Cannot write image %s\n", argv[1]);return -1;}

/* Çàêðûâàåì òðåê, ñåññèþ è èçâëåêàåì êîìïàêò-äèñê èç ïðèâîäà*/close_track();close_session();eject_cd();close(sg_fd);return 0;

}

Ðèñóíîê 5. Ôîðìàò êîìàíäû RESERVE TRACK

Ðèñóíîê 6. Ôîðìàò êîìàíäû READ TRACK INFORMATION

Page 74: 025 Системный Администратор 12 2004

72

hardware

Чтение информации о треке выполняет функцияread_track_info(). Параметр функции – номер трека. Возвра-щаемое значение – стартовый адрес трека.

Рассмотрим главную функцию программы записи аудио-данных. Входные параметры – список файлов в форматеOgg Vorbis.

Преобразование файла из формата Ogg Vorbis в WAVвыполняет функция ogg_decoder(). Входной параметр функ-ции – имя файла в формате Ogg Vorbis. Для конвертирова-ния используются библиотека libvorbis (http://www.vorbis.org).На выходе получается файл track.cdr в формате WAV, нобез RIFF-заголовка.

/* Îòêðûâàåì ôàéë óñòðîéñòâà */sg_fd = open(SG_DEV, O_RDWR);

/* Óñòàíàâëèâàåì ïàðàìåòðû ðåæèìà çàïèñè:* òèï áëîêà äàííûõ dbt = 0 � «ñûðûå» äàííûå, ðàçìåð áëîêà* 2352 áàéòà;* track_mode = 0 � òðåê ñîäåðæèò àóäèîäàííûå.*/

mode_select(0, 0);/* Ñ÷èòûâàåì èíôîðìàöèþ èç PMA */

printf("Display PMA:\n");read_pma();

/* Öèêë çàïèñè òðåêîâ íà äèñê */for(i = 1; i < argc; i++) {

/* Ïðåîáðàçóåì ôàéë èç ôîðìàòà Ogg Vorbis â WAV* (áåç çàãîëîâêà). Èìÿ âûõîäíîãî ôàéëà � track.cdr*/

ogg_decoder(argv[i]);/* Îïðåäåëÿåì ðàçìåð ôàéëà track.cdr â áàéòàõ*/

memset((void *)&s, 0, sizeof(struct stat));stat("./track.cdr", &s);

/* Ðàçìåð ôàéëà â áëîêàõ */track_size = s.st_size / CD_FRAMESIZE_RAW;printf("File size - %u\n", s.st_size);printf("Sectors in file - %u\n", track_size);printf("Reserve track #%d\n", i);

/* Ðåçåðâèðóåì ïðîñòðàíñòâî äëÿ òðåêà */reserv_track(track_size);

/* Îïðåäåëÿåì ñòàðòîâûé àäðåñ òðåêà */start_lba = read_track_info(i);printf("Start LBA for track #%d - %u\n", i, start_lba);

/* Çàïèñûâàåì â òðåê àóäèîäàííûå. Íîìåð ñòàðòîâîãî áëîêà* ðàâåí start_lba*/

total_sectors = write_audio("./track.cdr", start_lba);if(total_sectors == 0) return -1;

/* Çàêðûâàåì òðåê */close_track(i);}

/* Öèêë çàïèñè òðåêîâ çàâåðøåí. Çàêðûâàåì ñåññèþ */close_session();

/* Óäàëÿåì ôàéë track.cdr è èçâëåêàåì äèñê èç ïðèâîäà */unlink("./track.cdr");eject_cd();close(sg_fd);return 0;

}

void ogg_decoder(__u8 *file_name){

__u8 pcmout[8192];FILE *f;int out;OggVorbis_File vf;int current_section;printf("\nDecoding file %s..", file_name);f = fopen(file_name,"r");out = open("./track.cdr", O_CREAT|O_RDWR|O_TRUNC, 0600);if(ov_open(f, &vf, NULL, 0) < 0) {printf("Input does not appear to be an Ogg bitstream.\n");exit(-1);}for(;;) {

int reserv_track(__u32 track_size){

__u8 reserv_track_cmd[10];__u32 size = 0;if(test_unit_ready() < 0) exit(-1);

/* Ôîðìèðóåì êîìàíäíûé ïàêåò */memset(reserv_track_cmd, 0, 10);reserv_track_cmd[0] = 0x53; // êîä êîìàíäû RESERVE TRACK

/* Çàïîëíÿåì ïîëå Reservation size */size = __swab32(track_size);memcpy((void *)(reserv_track_cmd + 5), (void *)&size, 4);if(send_cmd(reserv_track_cmd, 10, SG_DXFER_NONE, ↵↵↵↵↵

NULL, 0, 20000) < 0) return -1;/* C÷èòûâàåì PMA */

read_pma();return 0;

}

__u32 read_track_info(int trk_num){

__u8 read_track_info_cmd[10];__u8 data_buff[40]; // áëîê èíôîðìàöèè î òðåêå__u16 len = 40; // ðàçìåð áëîêà__u32 lba = 0;if(test_unit_ready() < 0) exit(-1);

/* Ôîðìèðóåì êîìàíäíûé ïàêåò */memset(data_buff, 0, 40);memset(read_track_info_cmd, 0, 10);read_track_info_cmd[0] = 0x52;// ïîëå Address/Number Type = 01bread_track_info_cmd[1] = 1;read_track_info_cmd[5] = trk_num; // íîìåð òðåêàlen = __swab16(len);memcpy((void *)(read_track_info_cmd + 7), (void *)&len, 2);if(send_cmd(read_track_info_cmd, 10, SG_DXFER_FROM_DEV, ↵↵↵↵↵

data_buff, 40, 20000) < 0) {printf("Cannot read track #%d info!\n", trk_num);exit(-1);}

/* Èç áëîêà èíôîðìàöèè î òðåêå ñ÷èòûâàåì äàííûå î ðàçìåðå* òðåêà (ïîëå Track Size )*/

memcpy((void *)&lba, (void *)(data_buff + 24), 4);printf("Track #%d size - %u sectors\n", ↵↵↵↵↵

trk_num, __swab32(lba));/* Ñòàðòîâûé àäðåñ òðåêà */

memcpy((void *)&lba, (void *)(data_buff + 8), 4);return __swab32(lba);

}

int main(int argc, char **argv){

int i = 1;struct stat s;__u32 start_lba = 0, total_sectors = 0;__u32 track_size = 0;

/* Ïðîâåðÿåì íàëè÷èå âõîäíûõ ïàðàìåòðîâ */if(argc == 1) {printf("\n\tUsage: write_audio [OGG-files]\n\n");return 0;}

Page 75: 025 Системный Администратор 12 2004

73№12(25), декабрь 2004

hardware

Функция write_audio() выполняет запись аудиотрека надиск. Входные параметры – имя файла WAV-формата (беззаголовка), содержащего аудиоданные, и стартовый адрес,с которого начинается запись. Возвращаемое значение –общее число записанных на диск блоков:

Полный текст программы создания аудиодиска из фай-лов формата Ogg Vorbis находится с файле SG/ogg2cdda.c.

Получаем исполняемый файл при помощи команды:

Рассмотрим пример работы программы ogg2cdda. Ус-танавливаем в привод диск CD-RW и запускаем програм-му на выполнение, указав в командной строке имена трехфайлов в формате Ogg Vorbis:

Результаты работы программы:

Хорошо видно, что после каждого вызова функцииreserv_track в PMA добавляется запись о новом треке. Рас-стояние между треками – 2 секунды.

Теперь рассмотрим пример записи аудиоданных безпредварительного резервирования треков. Для определе-ния стартового адреса трека при помощи команды READTRACK INFORMATION считывается адрес невидимого, не-завершенного (invisible) трека. В этом случае поле Address/Number Type команды READ TRACK INFORMATION содер-жит 01b, поле Logical Block Address/Track/Session Number –значение 0xFF (см. табл. 452, стр. 374 спецификации [1]).

Функция определения стартового адреса невидимоготрека:

__u32 read_track_info(){

__u8 read_track_info_cmd[10];__u8 data_buff[40]; // áëîê èíôîðìàöèè î òðåêå__u16 len = 40; // ðàçìåð áëîêà èíôîðìàöèè î òðåêå__u32 lba = 0;if(test_unit_ready() < 0) exit(-1);

/* Ôîðìèðóåì êîìàíäíûé ïàêåò */memset(data_buff, 0, 40);memset(read_track_info_cmd, 0, 10);read_track_info_cmd[0] = 0x52;read_track_info_cmd[1] = 1;read_track_info_cmd[5] = 0xFF; // invisible tracklen = __swab16(len);memcpy((void *)(read_track_info_cmd + 7), (void *)&len, 2);if(send_cmd(read_track_info_cmd, 10, SG_DXFER_FROM_DEV, ↵↵↵↵↵

data_buff, 40, 20000) < 0) {printf("Cannot read track info!\n");exit(-1);}

/* Ñòàðòîâûé àäðåñ íåâèäèìîãî òðåêà. Ñ ýòîãî àäðåñà áóäåò* âûïîëíÿòüñÿ çàïèñü

memset(pcmout, 0, 8192);long ret = ov_read(&vf, pcmout, sizeof(pcmout), ↵↵↵↵↵0, 2, 1, &current_section);if (ret == 0) break;if(ret < 0) {

printf("Error OGG bitsream");exit(-1);

}if(write(out, pcmout, ret) < 0) {

printf("write");exit(-1);

}}fclose(f);close(out);printf("OK\n");return;

}

__u32 write_audio(__u8 *file_name, __u32 start_lba){

int in_f;__u8 write_cmd[10];// áëîê äëÿ àóäèîäàííûõ, 2352 áàéò__u8 write_buff[CD_FRAMESIZE_RAW];

__u32 lba = 0, lba1 = 0;if(test_unit_ready() < 0) exit(-1);lba1 = start_lba;

/* Îòêðûâàåì ôàéë ñ àóäèîäàííûìè */in_f = open(file_name, O_RDONLY, 0600);memset(write_buff, 0, CD_FRAMESIZE_RAW);

/* Öèêë ÷òåíèÿ äàííûõ èç ôàéëà è çàïèñè */while(read(in_f, write_buff, CD_FRAMESIZE_RAW) > 0) {

/* Ôîðìèðóåì êîìàíäíûé ïàêåò */memset(write_cmd, 0, 10);write_cmd[0] = WRITE_10;write_cmd[8] = 1; // ÷èñëî áëîêîâ äëÿ çàïèñèprintf("%c", 0x0D);printf("lba - %6d", lba1);// àäðåñ áëîêà, â êîòîðûé âûïîëíÿåòñÿ çàïèñü äàííûõlba = __swab32(lba1);memcpy((write_cmd + 2), (void *)&lba, 4);lba1 += 1;if(send_cmd(write_cmd, 10, SG_DXFER_TO_DEV, write_buff, ↵↵↵↵↵

CD_FRAMESIZE_RAW, 20000) < 0) return 0;memset(write_buff, 0, CD_FRAMESIZE_RAW);}close(in_f);printf("\n");return lba1; // ÷èñëî áëîêîâ, çàïèñàííûõ íà äèñê

}

Decoding file trk1.ogg..OK

File size – 41505744 bytes

Sectors in file - 17647

Reserve track #1

PMA data length - 24

PMA entries - 2

Entry ADR CTRL Point Min Sec Frame PMin Psec Pframe LBA

0 2 0 0 80 71 82 0 0 0 ---

1 1 0 1 3 57 24 0 2 0 0

Track #1 size - 17647 sectors

Start LBA for track #1 - 0

Decoding file trk2.ogg..OK

File size – 36604176 bytes

Sectors in file - 15563

Reserve track #2

PMA data length - 35

PMA entries - 3

Entry ADR CTRL Point Min Sec Frame PMin Psec Pframe LBA

0 2 0 0 80 71 82 0 0 0 ---

1 1 0 1 3 57 24 0 2 0 0

2 1 0 2 7 26 64 3 59 24 17799

Track #2 size - 15563 sectors

Start LBA for track #2 - 17799

Decoding file trk3.ogg..OK

File size – 47684448 bytes

Sectors in file - 20274

Reserve track #3

PMA data length - 46

PMA entries - 4

Entry ADR CTRL Point Min Sec Frame PMin Psec PFrame LBA

0 2 0 0 80 71 82 0 0 0 ---

1 1 0 1 3 57 24 0 2 0 0

2 1 0 2 7 26 64 3 59 24 17799

3 1 0 3 11 59 15 7 28 64 33514

Track #3 size - 20274 sectors

Start LBA for track #3 - 33514

Close session..OK

# gcc -o ogg2cdda ogg2cdda.c -lvorbis -lvorbisfile

# ./ogg2cdda trk1.ogg trk2.ogg trk3.ogg

Page 76: 025 Системный Администратор 12 2004

74

hardware

Рассмотрим главную функцию программы записи аудио-данных. Входные параметры – список файлов в форматеMP3.

Преобразование файлов из формата MP3 в WAV вы-полняет функция mp3_decoder(). Входные параметры фун-кции – имя файла формата MP3. На выходе получаем файлtrack.wav в формате WAV. Для конвертирования использу-ется программа mpg321:

При записи WAV-файла необходимо отбросить его за-головок. В функции записи файла write_audio() после от-крытия файла необходимо сместиться к началу аудиодан-ных при помощи вызова:

где WAV_HEADER_SIZE = 44 – размер заголовка WAV-фай-ла.

Полный текст программы создания аудиодиска из фай-лов формата MP3 находится в файле SG/mp2cd_inv_track.c.

Следующий фрагмент программы выполняет записьтреков, и стартовый адрес мы вычисляем самостоятельно:

Стартовый адрес первого трека нам известен – он ра-вен нулю. Адрес нового трека вычисляется по формуле:

где total_sector – общее число секторов, записанных на диск,apl – длина аудиопаузы, значение поля Audio Pause Length(APL) страницы параметров режима записи (рис. 15 пер-вой части статьи).

Значение APL хранится в поле apl структуры wpm, и оп-ределяется следующим образом:

В файле SG/write_audio.c находится полный текст про-граммы, выполняющей запись WAV-файлов на аудиоком-пакт. Стартовый адрес трека вычисляется вышеприведен-ным способом.

А теперь давайте сотрем с диска все, что мы на негозаписали. Для стирания информации с диска используетсякоманда BLANK. Формат этой команды приведен на рис. 8.

Поле Blanking type устанавливает режим очистки дис-ка. Может принимать следующие значения:! 000b – стирается вся информация, находящаяся на дис-

ке. Значение поля Start Address игнорируется.! 001b – минимальная очистка диска. Стирается PMA,

Lead-In-область диска и pre-gap-область первого трека.Параметр Start Address игнорируется.

int main(int argc, char **argv){

int i = 1;__u32 start_lba = 0, total_sectors = 0;

/* Ïðîâåðÿåì âõîäíûå ïàðàìåòðû */if(argc == 1) {printf("\n\tUsage: write_audio [MP3-files]\n\n");return 0;}

/* Îòêðûâàåì ôàéë óñòðîéñòâà */if((sg_fd = open(SG_DEV, O_RDWR)) < 0) {

perror("open");return -1;

}/* Óñòàíàâëèâàåì ïàðàìåòðû ðåæèìà çàïèñè* (ñì. ïðåäûäóùèé ïðèìåð)*/

mode_select(0, 0);/* Öèêë çàïèñè òðåêîâ íà äèñê */

for(i = 1; i < argc; i++) {/* Äåêîäèðóåì ôàéë èç MP3-ôîðìàòà â WAV */

printf("\nDecoding file %s..\n", argv[i]);mp3_decoder(argv[i]);

/* Îïðåäåëÿåì ñòàðòîâûé àäðåñ òðåêà */start_lba = read_track_info();printf("Start LBA for track #%d - %u\n", i, start_lba);

/* Çàïèñûâàåì òðåê íà äèñê è çàêðûâàåì òðåê */total_sectors = write_audio("./track.wav", start_lba);if(total_sectors == 0) return -1;close_track(i);}

/* Öèêë çàïèñè òðåêîâ çàâåðøèëñÿ, çàêðûâàåì ñåññèþ */close_session();

/* Óäàëÿåì ôàéë track.wav è èçâëåêàåì äèñê èç ïðèâîäà */unlink("./track.wav");eject_cd();close(sg_fd);return 0;

}

*/memcpy((void *)&lba, (void *)(data_buff + 8), 4);return __swab32(lba);

}

void mp3_decoder(__u8 *file_name){

static pid_t pid;int status;switch(pid = fork()) {case -1:

perror("fork");exit(-1);

case 0:execl("/usr/bin/mpg321", "mpg321", "-q", ↵↵↵↵↵"-w", "track.wav", file_name, 0);exit(-1);

}

if((pid = waitpid(pid, &status, 0)) && ↵↵↵↵↵WIFEXITED(status)) return;

}

start_lba = total_sectors + apl + 2

mode_sense();apl = __swab16(wpm->apl);

lseek(in_f, WAV_HEADER_SIZE, 0)

total_sectors = 0;/* Öèêë çàïèñè òðåêîâ */

for(i = 1; i < argc; i++) {printf("\nWriting track #%d:\n", i);

/* Îïðåäåëÿåì ñòàðòîâûé àäðåñ òðåêà è çàïèñûâàåì òðåê* íà äèñê. Ïîñëå ýòîãî çàêðûâàåì òðåê*/

// ñòàðòîâûé àäðåñ òðåêàif(i > 1) start_lba = total_sectors + apl + 2;printf("Start sector - %u\n", start_lba);total_sectors = write_audio(argv[i], start_lba);if(total_sectors == 0) return -1;close_track(i);

}

Page 77: 025 Системный Администратор 12 2004

75№12(25), декабрь 2004

hardware

Остальные значения поля Blanking type и их описаниеприведены в спецификации [1], табл. 219 «Blanking TypesCD-RW and DDCD-RW».

Функция blank() выполняет очистку CD-RW-диска. Па-раметр функции blank_type устанавливает режим очисткидиска. Допустимые значения этого параметра – 0 или 1:

Полный текст программы очистки CD-RW-диска приве-ден в файле SG/blank.c.

Общее замечание по работе всех программ. Иногдапрограмма после запуска выдает сообщение об ошибке:

и завершает работу. Здесь Sense Key = 0x06, ASC = 0x28,ASCQ = 0x00 (см. [3, 5]), что означает «UNIT ATTENTION.Indicates that the removable medium may have been changed orthe ATAPI CD-ROM Drive has been reset. NOT READY TOREADY TRANSITION, MEDIUM MAY HAVE CHANGED» (Носи-тель был заменен или выполнен сброс ATAPI-контроллера).

При повторном запуске программа выполняется безошибок.

Литература и ссылки:1. Спецификация SCSI Multimedia Commands-4 (SCSI MMC-4),

http://www.t10.org/ftp/t10/drafts/mmc4/mmc4r03d.pdf.2. Спецификация SCSI-3 Multimedia Commands, http://

www.t10.org/ftp/t10/drafts/mmc/mmc-r10a.pdf.3. Specification for ATAPI DVD Devices, ftp.seagate.com/sff/

INF-8090.pdf.4. SCSI-Generic-HOWTO, http://www.linux.org/docs/ldp/

howto/SCSI-Generic-HOWTO/index.html.5. Мешков В. «Пакетные команды интерфейса ATAPI» –

Журнал «Системный администратор», № 9, сентябрь2004 г. – 70-84 с.

int blank(__u8 blank_type){

__u8 blank_cmd[12];if(test_unit_ready() < 0) exit(-1);memset(blank_cmd, 0, 12);blank_cmd[0] = 0xA1; // êîä êîìàíäû BLANK// ðåæèì î÷èñòêè: 0 � ïîëíàÿ, 1 � ìèíèìàëüíàÿblank_cmd[1] = blank_type;if(send_cmd(blank_cmd, 12, SG_DXFER_NONE, ↵↵↵↵↵

NULL, 0, 9600*1000) < 0) return -1;return 0;

}

Sense data: 0x70 0x00 0x06 0x00 0x00 0x00 0x00 0x0a 0x00 0x00

0x00 0x00 0x28 0x00 0x00 0x00 0x00 0x00

Driver_status=0x28

Unit not ready

Ðèñóíîê 8. Ôîðìàò êîìàíäû BLANK

Page 78: 025 Системный Администратор 12 2004

76

образование

АтрибутыСтруктурно всякий атрибут состоит из заголовка (attributeheader) и тела (attribute body). Заголовок атрибута всегдахранится в файловой записи, расположенной внутри MFT

(см. первую часть статьи, «Файловые записи»). Тела рези-дентных атрибутов хранятся там же. Нерезидентные атри-буты хранят свое тело вне MFT, в одном или несколькихкластерах, перечисленных в заголовке данного атрибута в

ФАЙЛОВАЯ СИСТЕМА NTFS ИЗВНЕ И ИЗНУТРИЧАСТЬ 2

ФАЙЛОВАЯ СИСТЕМА NTFS ИЗВНЕ И ИЗНУТРИЧАСТЬ 2

КРИС КАСПЕРСКИ

В продолжение знакомства с файловой системойNTFS сегодня мы сосредоточимся на строенииатрибутов, исследовав их заголовок и механизмыхранения нерезидентного тела на диске, а такжепокажем, как рассмотренные нами структурыданных выглядят вживую в дисковом редакторетипа Disk Probe или Sector Inspector.

Page 79: 025 Системный Администратор 12 2004

77№12(25), декабрь 2004

образование

специальном списке (см. «Списки отрезков»). Если 8-раз-рядное поле, расположенное по смещению 08h байт от на-чала атрибутного заголовка, равно нулю, атрибут считает-ся резидентным, а если единице – то нет. Любые другиезначения недопустимы.

Первые четыре байта атрибутного заголовка определя-ют его тип. Тип атрибута в свою очередь определяет фор-мат представления тела атрибута. В частности, тело атри-бута данных (тип: 80h – $DATA) представляет собой «сы-рую» последовательность байт. Тело атрибута стандартнойинформации (тип: 10h – $STANDARD_INFORMATION) опи-сывает время его создания, права доступа и т. д. Подроб-нее см. «Типы атрибутов».

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

Длина тела резидентных атрибутов, выраженная в бай-тах, хранится в 32-разрядном поле, расположенном по сме-щению 10h байт от начала атрибутного заголовка. 16-раз-рядное поле, следующее за его концом, хранит смещениерезидентного тела, отсчитываемое от начала атрибутногозаголовка.

С нерезидентными атрибутами в этом плане все намногосложнее и для хранения длины их тела используется мно-жество полей. Реальный размер тела атрибута (real size ofattribute), выраженный в байтах, хранится в 64-разрядном (!)поле, находящемся по смещению 30h байт от начала атри-бутного заголовка. Следующее за ним 64-разрядное полехранит инициализированный размер потока (initialized datasize of the stream), выраженный в байтах и, судя по всему,всегда равный реальному размеру тела атрибута. 64-раз-рядное поле, расположенное по смещению 28h байт от на-чала атрибутного заголовка, хранит выделенный размер(allocated size of attribute), выраженный в байтах и равныйреальному размеру тела атрибута, округленному до раз-мера кластера (в большую сторону).

Два 64-разрядных поля, расположенные по смещению10h и 18h байт от начала атрибутного заголовка, задаютпервый (starting VCN) и последний (last VCN) номер вирту-ального кластера, принадлежащего телу нерезидентногоатрибута. Виртуальные кластеры представляют собой ло-гические номера кластеров, не зависящие от своего физи-ческого расположения на диске. В подавляющем большин-стве случав номер первого кластера тела нерезидентногоатрибута равен нулю, а последний – количеству кластеров,занятых телом атрибута, уменьшенном на единицу. 16-раз-рядное поле, расположенное по смещению 20h от началаатрибутного заголовка, содержит указатель на массив DataRuns, расположенный внутри этого заголовка и описываю-щий логический порядок размещения нерезидентного телаатрибута на диске (подробнее см. «Списки отрезков»).

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

Если атрибут имеет имя (attribute Name), то 16-разряд-ное поле, расположенное по смещению 0Ah байт от атри-бутного заголовка, содержит указатель на него. Для безы-мянных атрибутов оно равно нулю (а большинство атрибу-тов безымянны!). Имя атрибута хранится в атрибутном за-головке в формате UNICODE, а его длина определяется 8-разрядным полем, расположенным по смещению 09h байтот начала атрибутного заголовка.

Если тело атрибута сжато, зашифровано или разряже-но, 16-разрядное поле флагов, расположенное по смещению0Ch байт от начала атрибутного заголовка, не равно нулю.

Остальные поля не играют сколь-нибудь существеннойроли и потому здесь не рассматриваются.

Типы атрибутовNTFS поддерживает большее количество предопределен-ных типов атрибутов, перечисленных в таблице 3. Как ужеговорилось выше, тип атрибута определяет его назначениеи формат представления тела. Полное описание всех атри-бутов заняло бы очень много места и поэтому здесь приво-дятся лишь наиболее «ходовые» из них, а за информациейоб остальных обращайтесь к Linux-NTFS Project.

Òàáëèöà 1. Ñòðóêòóðà ðåçèäåíòíîãî àòðèáóòà

Òàáëèöà 2. Ñòðóêòóðà íåðåçèäåíòíîãî àòðèáóòà

Page 80: 025 Системный Администратор 12 2004

78

образование

Атрибут стандартной информации$STANDARD_INFORMATIONАтрибут стандартной информации описывает время созда-ния/изменения/последнего доступа к файлу и права досту-па, а также некоторую другую вспомогательную информа-цию (например, квоты):

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

При каких обстоятельствах атрибуты не умещаются водной файловой записи? Это может произойти, когда:

! файл содержит много альтернативных имен или жест-ких ссылок;

! файл очень сильно фрагментирован;! файл содержит очень сложный дескриптор безопасно-

сти;! файл имеет очень много потоков данных (т.е. атрибу-

тов типа $DATA).

Структура атрибута списка атрибутов приведена ниже:

Атрибут полного имени $FILE_NAMEАтрибут полного имени файла хранит имя файла в соот-ветствующем пространстве имен. Таких атрибутов у фай-ла может быть и несколько (например, win32-имя и MS-DOSимя). Здесь же хранятся и жесткие ссылки (hard link), еслиони есть.

Структура атрибута полного имени приведена ниже:

Списки отрезков (data runs)Тела нерезидентных атрибутов хранятся на диске в однойили нескольких кластерных цепочках, называемых отрез-ками (runs). Отрезком называется последовательностьсмежных кластеров, характеризующаяся номером началь-ного кластера и длиной. Совокупность отрезков называет-ся списком, run-list или data run.

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

Сами же поля размеров хранятся в 4-байтовых ячейках,называемых нибблами (nibble) или полубайтами. Шестнад-цатеричная система исчисления позволяет легко перево-

Òàáëèöà 5. Ñòðóêòóðà àòðèáóòà $ATTRIBUTE_LIST

Òàáëèöà 6. Ñòðóêòóðà àòðèáóòà $FILE_NAME

Òàáëèöà 3. Îñíîâíûå òèïû àòðèáóòîâ

Òàáëèöà 4. Ñòðóêòóðà àòðèáóòà $STANDARD_INFORMATION

Page 81: 025 Системный Администратор 12 2004

79№12(25), декабрь 2004

образование

дить байты в нибблы и наоборот. Младший ниббл равен(X & 15), а старший – (X / 16). Легко видеть, что младшийниббл соответствует младшему шестнадцатеричному раз-ряду байта, а старший – старшему. Например, 69h состоитиз двух нибблов – младший равен 9h, а старший – 6h.

Список отрезков представляет собой массив структур,каждая из которых описывает характеристики «своего» от-резка, а в конце списка находится завершающий нуль. Пер-вый байт структуры состоит из двух полубайт: младший за-дает длину поля начального кластера отрезка (условно обо-значаемого буквой F), старший – количество кластеров вотрезке (L). Поле длины отрезка идет следом. В зависимо-сти от значения L оно может занимать от одного до восьмибайт (более длинные поля недопустимы). Первый байт полястартового кластера файла расположен по смещению 1 + Lбайт от начала структуры (что соответствует 2+2∗L ниб-блам). Кстати говоря, в документации Linux-NTFS Project(версия 0.4) поля размеров начального кластера и количе-ства кластеров в отрезке перепутаны местами.

Покажем, как с этим работать на практике. Допустим,мы имеем следующий run-list, соответствующий нормаль-ному нефрагментированному файлу (что может быть про-ще!): «21 18 34 56 00». Попробуем его декодировать.

Начнем с первого байта – 21h. Младший полубайт (01h)описывает размер поля длины отрезка, старший (02h) –размер поля начального кластера. Следующие несколькобайт представляют поле длины отрезка, размер которого вданном случае равен одному байту – 18h. Два других бай-та (34h 56h) задают номер начального кластера отрезка.Нулевой байт на конце сигнализирует о том, что это после-дний отрезок в файле. Итак, наш файл состоит из одного-единственного отрезка, начинающегося с кластера 5634hи заканчивающегося кластером 5634h+ 18h == 564Ch.

Рассмотрим более сложный пример фрагментирован-ного файла со следующим списком отрезков: «31 38 73 2534 32 14 01 E5 11 02 31 42 AA 00 03 00». Извлекаем первыйбайт – 31h. Один байт приходится на поле длины и три бай-та на поле начального кластера. Таким образом, первыйотрезок (run 1) начинается с кластера 342573h и продол-жается вплоть до кластера 342573h + 38 == 3425ABh. Что-бы найти смещение следующего отрезка в списке, мы скла-дываем размер обоих полей с их начальным смещением:3 + 1 == 4. Отсчитываем четыре байта от начала run-list ипереходим к декодированию следующего отрезка: 32h – двабайта на поле длины отрезка (равное в данном случае0114h) и три байта на поле номера начального кластера(0211E5h). Следовательно, второй отрезок (run 2) начина-ется с кластера 0211E5h и продолжается вплоть до класте-ра 0211E5h + 114h == 212F9h. Третий отрезок (run 3): 31h –один байт на поле длины и три байта на поле начальногокластера, равные 42h и 0300AAh соответственно. Поэтомутретий отрезок (run 3) начинается с кластера 0300AAh ипродолжается вплоть до кластера 0300AAh + 42h == 300ECh.

Завершающий нуль на конце run-list сигнализирует о том,что это последний отрезок в файле.

Таким образом, подопытный файл состоит из трех от-резков, разбросанных по диску в следующем живописномпорядке: 342573h – 3425ABh; 0211E5h – 212F9h; 0300AAh –300ECh. Остается только прочитать его с диска!

Начиная с версии 3.0, NTFS поддерживает разряженные(sparse) атрибуты, т.е. такие, которые не записывают на дисккластеры, содержащие одни нули. При этом поле номера на-чального кластера отрезка может быть равным нулю, что оз-начает, что данному отрезку не выделен никакой кластер.Поле длины содержит количество кластеров, заполненныхнулями. Их не нужно считывать с диска. Вы должны само-стоятельно изготовить их в памяти. Кстати говоря, далеконе все дисковые доктора знают о существовании разряжен-ных атрибутов (если атрибут разряжен его флаг равен 8000h),и интерпретируют нулевую длину поля номера начальногокластера весьма странным образом. Последствия такого«лечения» обычно оказываются очень печальны.

Пространства имен (name spaces)NTFS изначально проектировалась как системно-незави-симая файловая система, способная работать со множе-ством различных подсистем, как то: Win32, MS-DOS, POSIXи т. д. Поскольку, каждая из них налагает свои собствен-ные ограничения на набор символов, допустимых для ис-пользования в имени файла, NTFS вынуждена поддерживатьнесколько независимых пространств имен (name space).

POSIXДопустимы все UNICODE-символы (с учетом регистра), заисключением символа нуля (NULL), обратного слеша («/»)и знака двоеточия («:»). Последнее, кстати говоря, не огра-ничение POSIX, а ограничение NTFS, использующей этотсимвол для доступа к именованным атрибутам. Максималь-но допустимая длина имени составляет 255 символов.

Win32Доступны все UNICODE-символы (без учета регистра), заисключением следующего набора: «“» (кавычки), «*» (звез-дочка), «/» (прямой слеш), «:» (двоеточие), «<» (знак мень-ше), «>» (знак больше), «?» (вопросительный знак), «\» (об-ратный слеш), «|» (символ конвейера). К тому же, имя фай-ла не может заканчиваться на точку или пробел. Макси-мально допустимая длина имени составляет 255 символов.

MS-DOSДоступны все символы пространства имен win32 (без уче-та регистра), за исключением: «+» (знак плюс), «,» (знакзапятая), «.» (знак точка), «;» (точка с запятой), «=» (знакравно). Имя файла не должно превышать восьми симво-лов за которыми следует необязательное расширение сдлиной от одного до трех символов.

Назначение некоторыхслужебных файловNTFS содержит большое количество служебных файлов(метафайлов) строго определенного формата, важнейшийиз которых – $MFT – мы только что рассмотрели. Осталь-

Òàáëèöà 7. Ñòðóêòóðà îäíîãî ýëåìåíòà ñïèñêà îòðåçêîâ

Page 82: 025 Системный Администратор 12 2004

80

образование

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

У нас нет возможности рассказать о структуре всехметафайлов (да и незачем дублировать Linux-NTFS Project),поэтому эта информация здесь не приводится.

Путешествие по NTFSРассказ о NTFS был бы неполным без практической иллю-страции техники разбора файловой записи «руками». Досих пор мы витали в облаках теоретической абстракции.Пора спускаться на грешную землю.

Воспользовавшись любым дисковым редактором, на-пример, Disk Probe, попробуем декодировать одну файло-вую запись вручную. Найдем сектор, содержащий сигнату-ру «FILE» в его начале (не обязательно брать первый встре-тившийся сектор). Он может выглядеть, например, так:

Первым делом необходимо восстановить оригинальное

содержимое последовательности обновления. По смеще-нию 04h от начала сектора лежит 16-разрядный указательна нее, равный в данном случае 2Ah (значит, это NTFS 3.0или младше). А что у нас лежит по смещению 2Ah? Парабайт 03 00. Это номер последовательности обновления.Сверяем его с содержимым двух последних байт этого иследующего секторов (смещения 1FEh и 3FEh соответствен-но). Они равны! Значит, данная файловая запись цела (покрайней мере внешне) и можно переходить к операции спа-сения. По смещению 2Ch расположен массив, содержащийоригинальные значения последовательности обновления.Количество элементов в нем равно содержимому 16-разряд-ного поля, расположенному по смещению 06h от начала сек-тора и уменьшенного на единицу (т.е. в данном случае 03h –01h == 02h). Извлекаем два слова начиная со смещения 2Ch

(в данном случае они равны 00 00 и 00 00) и записываем ихв конец первого и последнего секторов.

Теперь нам необходимо выяснить – используется ли дан-ная файловая запись или ассоциированный с ней файл/ка-талог был удален. 16-разрядное поле, расположенное посмещению 16h, содержит значение 01h. Следовательно,перед нами файл, а не каталог, и этот файл еще не удален.Но является ли данная файловая запись базовой для дан-ного файла или мы имеем дело с ее продолжением? 64-разрядное поле, расположенное по смещению 20h, равнонулю, следовательно, данная файловая запись – базовая.

Переходим к исследованию атрибутов. 16-разрядноеполе, находящееся по смещению 14h равно 30h, следова-тельно, заголовок первого атрибута начинается со смеще-ния 30h от начала сектора.

Первое двойное слово атрибута равно 10h, значит, пе-ред нами атрибут типа $STANDARD_INFORMATION. 32-раз-рядное поле длины атрибута, находящееся по смещению04h и равное в данном случае 60h байт, позволяет нам вы-числить смещение следующего атрибута в списке – 30h(смещение нашего атрибута) + 60h (его длина) == 90h (сме-щение следующего атрибута). Первое двойное слово сле-дующего атрибута равно 30h, значит, это атрибут типа$NAME и следующее 32-разрядное поле хранит его длину,равную в данном случае 70h. Сложив длину атрибута с егосмещением, мы получим смещение следующего атрибута –90h + 70h == 100h. Первое двойное слово третьего атрибу-та равно 80h, следовательно, это атрибут типа $DATA, хра-нящий основные данные файла. Складываем его смеше-ние с длиной – 100h + 32h == 132h. Мы наткнулись на час-токол FFFFFFh, сигнализирующий о том, что атрибут $DATAпоследний в списке.

Теперь, разбив файловую запись на атрибуты, присту-пить к исследованию каждого из атрибутов в отдельности.Начнем с имени. 8-разрядное поле, находящееся по сме-щению 08h от начала атрибутного заголовка (и по смеще-нию 98h от начала сектора), содержит флаг нерезидентно-сти, который в данном случае равен нулю (т.е. атрибут ре-зидентный и его тело хранится непосредственно в самойфайловой записи). 16-разрядное поле, расположенное посмещению 0Ch от начала атрибутного заголовка (и по сме-щению 9Ch от начала сектора) равно нулю, следовательнотело атрибута не сжато и не зашифровано. 32-разрядноеполе, расположенное по смещению 10h от начала атрибут-

Òàáëèöà 8. Íàçíà÷åíèå îñíîâíûõ ñòàíäàðòíûõ ôàéëîâ

Ëèñòèíã 1. Ðó÷íîå äåêîäèðîâàíèå ôàéëîâîé çàïèñè (ðàçíûåàòðèáóòû âûäåëåíû ðàçíûì öâåòîì)

Page 83: 025 Системный Администратор 12 2004

81№12(25), декабрь 2004

образование

ного заголовка и по смещению A0h от начала сектора, со-держит длину атрибутного тела, равную в данном случае54h байт, а 16-разрядное поле, расположенное по смеще-нию 14h от начала атрибутного заголовка и по смещениюA4h от начала сектора, хранит смещение атрибутного тела,равное в данном случае 18h, следовательно, тело атрибу-та $NAME располагается по смещению A8h от начала сек-тора.

Формат атрибута типа $NAME описан в таблице XX.Первые восемь байт содержат ссылку на материнский ка-талог данного файла, равную в данном случае 11ADBh:01(индекс – 11ADBh, номер последовательности – 01h). Сле-дующие 32-байта содержат штаммы времени создания,изменения и времени последнего доступа к файлу. По сме-щению 28h от начала тела атрибута и D0h от начала секто-ра лежит 64-разрядное поле выделенного размера, а заним – 64-разрядное поле реального размера. Оба равнынулю, что означает, что за размером файла следует обра-щаться к атрибутам типа $DATA.

Длина имени файла содержится в 8-разрядном поле,находящемся по смещению 40h байт от начала тела атри-бута и по смещению E8h от начала сектора. В данном слу-чае оно равно 09h. Само же имя начинается со смещения42h от начала тела атрибута и со смещения EAh от началасектора. И здесь находится Ilfak.dbx.

Переходим к атрибуту основных данных файла, пропу-стив атрибут стандартной информации, который не содер-жит решительно ничего интересного. 8-разрядный флаг не-резидентности, расположенный по смещению 08h от нача-ла атрибутного заголовка и по смещению 108h от началасектора, равен 01h, следовательно атрибут нерезидентный.16-разрядный флаг, расположенный по смещению 0Ch отначала атрибутного заголовка и по смещению 10Сh от на-чала сектора, равен нулю, значит, атрибут не сжат и не за-шифрован. 8-разрядное поле, расположенное по смещению

09h от начала атрибутного заголовка и по смещению 109hот начала сектора, равно нулю – атрибут безымянный. Ре-альная длина тела атрибута (в байтах) содержится в 64-разрядном поле, расположенном по смещению 30h от на-чала атрибутного заголовка и по смещению 130h от нача-ла сектора. В данном случае она равна 4ED1F0h (5.165.552).Два 64-разрядных поля, расположенных по смещениям 10h/110h и 18h/118h байт от начала атрибутного заголовка/сек-тора соответственно, содержат начальный и конечный но-мер виртуального кластера неризидентного тела. В данномслучае они равны: 0000h/4EDh.

Остается лишь декодировать список отрезков, адрес ко-торого хранится в 16-разрядном поле, находящемся по сме-щению 20h от начала атрибутного заголовка и 120h от на-чала сектора. В данном случае оно равно 40h, что соответ-ствует смещению от начала сектора в 140h. Сам же списокотрезков выглядит так: 32 EE 04 D9 91 00 00. Два байтазанимает поле длины (равное в данном случае 04EEh кла-стерам) и три – поле начального кластера (0091h). Завер-шающий ноль на конце говорит о том, что этот отрезок пос-ледний в списке отрезков.

Подытожим полученную информацию. Файл называет-ся Ilfak.dbx, он начинается с кластера 0091h и продолжает-ся вплоть до кластера 57Fh, при реальной длине файла в5 165 552 байт. За сим все! Теперь уже ничего не стоит ско-пировать файл на резервный носитель (например, ZIP илистример).

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

Что читатьОсновными источниками данных по NTFS служат:! Книга Хелен Кастер (Helen Custer, часто сокращаемая до просто «Helen») «Inside the Windows NT file system» (в рус-

ском издании она входит в состав «Основы Windows NT и NTFS»), подробно описывающая концепции файловойсистемы и дающая о ней общее представление. К сожалению, все объяснения ведутся на абстрактном уровне безуказания конкретных числовых значений, смещений и структур. К тому же в операционных системах Windows 2000 иWindows XP с файловой системой произошли значительные изменения, никак не отраженные в книге. Если не найде-те эту книгу в магазинах – ищите ее в файлообменных сетях. (Например, www.eMule.ru).

! Хакерская документация от коллектива «Linux-NTFS Project» (http://linux-ntfs.sourceforge.net), чьим хобби долгое вре-мя была разработка независимого NTFS-драйвера для OS Linux. Однако сейчас энтузиазм команды начал стреми-тельно угасать. Это выдающееся творение, подробно описывающее все ключевые структуры файловой системы(естественно, на английском языке), отнюдь не заменяет книгу Хелен, а лишь расширяет ее! Разобраться в NTFS-project без знаний NTFS очень и очень непросто!

! Документация от Active Data Recovery Software на утилиту Active Uneraser, бесплатную копию которой можно найти насайте www.NTFS.com. Это своеобразный синтез книги Хелен и Linux-NTFS Project, описывающий важнейшие струк-туры данных и обходящий стороной все вопросы, которые только можно обойти. Здесь же можно найти до пределавыхолощенное изложение методики восстановления данных. Если не найдете Хелен, скачайте демонстрационнуюверсию Active Uneraser и воспользуйтесь прилагаемой к нею документацией (Active Uneraser поставляется в двухвариантах – образе FDD и образе CD, документация присутствует только на последнем из них).

! Контекстная помощь на Runtime Software Disk Explorer также содержит достаточно подробное описание файловойсистемы, однако, на редкость бестолково организованное. Для упрощения навигации по тексту рекомендуется де-компилировать chm-файл в обычный текст, вручную перегнав его в MS Word, pdf или любой другой удобный для васформат.

Page 84: 025 Системный Администратор 12 2004

82

образование

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

Автоматическое подключениесетевых ресурсовК сетевым ресурсам относятся сетевые принтеры и диски.Рассмотрим подробнее каждый из них.

Подключение сетевых принтеров. Теория

Соглашение об именахИмя должно содержать как можно больше информации опринтере, при этом быть удобным для использования. Нарабочих станциях под управлением операционной систе-мы Windows пользователь имеет дело с двумя именами –непосредственное и сетевое имена принтера.

Чаще всего имя, назначаемое принтеру, представляетсобой реальное имя принтера с порядковым номером, еслиесть несколько принтеров одинаковой модели, например,HP LaserJet 1200 (1), HP LaserJet 2300 (2). Такой способименования рекомендуется использовать в небольших орга-низациях. В крупных корпорациях принцип именованияпринтеров может быть другим.

Сетевое имя, как отмечено ранее, должно быть болеекоротким, но при этом не должно терять смысловой нагруз-ки. Оно чаще всего представляет собой общую характери-стику принтера, например, HP1200_1, HP2300_2.

Предварительная настройка принтера и ADРабота сценария строится на анализе и обработке данных,содержащихся в Active Directory и пользовательском реес-тре. На основе полученных данных осуществляется подклю-чение и отключение принтера в зависимости от членствапользователя в соответствующих группах безопасности.Для обеспечения работоспособности сценария необходи-мо выполнение нескольких условий:

Первое условие – названия принтеров, групп безопас-ности должны удовлетворять соглашению об именах.

Второе – сетевые принтеры, подключением и отключе-нием которых должен управлять скрипт, должны быть опуб-ликованы в Active Directory.

Третье – названия групп безопасности должны строить-ся в соответствии со следующим шаблоном: название од-ной из групп, члены которой могут только выводить зада-ния на печать, образуется добавлением к сетевому именипринтера через дефис слова Print, например, «HP2300_1 –Print». Название другой группы строится аналогично, с тойразницей, что слово «Print» заменяют на словосочетание«Print Managers». Члены этой группы могут управлять оче-редью печати и принтером. Таким образом, принтеру с се-тевым именем «HP1200_1», соответствуют следующие на-звания групп: имя первой группы «HP1200_1 – Print», вто-рой «HP1200_1 – Print Managers».

Четвертое – должны быть определены параметры бе-зопасности принтера. В свойствах принтера (см. рис. 2) насервере печати во вкладке «Security» (безопасность) дол-жна быть удалена группа «Everyone» (в противном случаескрипт будет подключать этот принтер всем пользователямсети) и добавлены две группы безопасности, соответству-ющие данному принтеру: «HP1200_1 – Print» и «HP1200_1 –Print Managers». Для группы «HP1200_1 – Print» долженбыть установлен в разделе «Permissions» (разрешения)флажок напротив свойства «Print» (см. рис. 2), а для груп-пы «HP1200_1 – Print Managers» – флажки напротив «Print»

РАЗРАБОТКА СЦЕНАРИЯ РЕГИСТРАЦИИПОЛЬЗОВАТЕЛЕЙ В СЕТИЧАСТЬ 2

РАЗРАБОТКА СЦЕНАРИЯ РЕГИСТРАЦИИПОЛЬЗОВАТЕЛЕЙ В СЕТИЧАСТЬ 2

ИВАН КОРОБКО

Ðèñóíîê 1

1 Коробко И. Разработка сценария регистрации пользователей в сети. Часть 1. – Журнал «Системный администратор», №11, ноябрь, 2004 г.

Page 85: 025 Системный Администратор 12 2004

83№12(25), декабрь 2004

образование

(печать) и «Manage Documents» (управление документами).Ставить флажок напротив «Manage Printers» не рекомен-дуется, поскольку управление принтерами подразумеваетвозможность изменять настройки принтера, удалять его. Помнению автора, такими привилегиями может обладать толь-ко системный администратор.

Подключение сетевых принтеров. ПрактикаИтак, работа сценария строится на анализе данных, содер-жащихся в Active Directory и пользовательском реестре. Егоработу можно разбить на три этапа.

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

Формирование списка принтеров, которыенеобходимо подключить пользователю

Определение имени текущего доменаС помощью функции GetObject() осуществляется чтениекорня пространства имен, в данном случае определяетсяимя текущего домена.

Пример определения текущего домена:

Переменная domain_ имеет вид «dc=microsoft,dc=com»,если домен «microsoft.com».

Имя текущего домена, полученного провайдером WinNT,нельзя использовать, поскольку с его помощью можно по-лучить только сокращенное имя домена (в данном случае«microsoft»). Если все же указано сокращенное имя доме-на в строке с SQL-запросом, то при выполнении скриптапроизойдет ошибка. В сообщении о ней будет сказано, чтопо указанному пути база не обнаружена, поэтому устано-вить соединение невозможно.

Построение запроса SQLЗапрос SQL используется для осуществления процедурыпоиска объектов, при заданном типе объекта. В общем слу-чае он выглядит следующим образом:

В SELECT указываются поля, по которым идет выбор-ка. Поля перечисляются через запятую, «пробелы» послезапятой обязательны. Полный список полей объектов ADможно получить с помощью утилиты ADSI Edit, которая раз-мещается в дистрибутиве Microsoft Windows 2000 в дирек-тории /Support/Tools (см. статью «Программное управлениеADSI: LDAP», журнал «Системный администратор», №3,март 2004г.).

В FROM указывается путь к объекту. В данном случаеизвестен только домен. При описании данного раздела про-белы не допускаются.

В WHERE указывается тип объекта, к которому адресо-ван запрос. Данное поле является фильтром. ПровайдерLDAP поддерживает несколько типов объектов, которые взапросе SQL определяются переменной objectClass: PrintQueue – массив принтеров, опубликованных в AD; Group –группы, созданные в AD; User – пользователи, созданные вAD; Computer – массив компьютеров, зарегистрированныхв AD. Пример использования запроса SQL см. в следую-щем разделе.

Поиск опубликованных принтеров в ADПоиск объектов в Active Directory с помощью провайдераLDAP реализуется через ADODB-соединение. После созда-ния соединения формируется SQL-запрос и осуществляет-ся поиск по заданным критериям. Результатом поиска бу-дет массив, элементами которого являются значения по-лей, которые указаны в параметре SELECT SQL-запроса.Затем происходит вывод данных на экран. В приведенномпримере осуществляется поиск всех опубликованных прин-теров в текущем домене и вывод на экран названия прин-тера, его сетевого имени (ShareName):

Ðèñóíîê 2

$rootDSE_ = GetObject("LDAP://RootDSE")$domain_ = "LDAP://" + $rootDSE_.Get("defaultNamingContext")

SELECT ïîëå_1, ïîëå_2, �, ïîëå_n FROM ↵↵↵↵↵�LDAP://dc=äîìåí_1,dc=äîìåí_2�,domen_n� ↵↵↵↵↵WHERE objectClass=�òèï_îáúåêòà�

$strADSQuery = "SELECT shortservername, portname, ↵↵↵↵↵servername, printername, printsharename, location, ↵↵↵↵↵description FROM '" +$domain_+"' ↵↵↵↵↵WHERE objectClass='printQueue'"

$objConnection = CreateObject("ADODB.Connection")$objCommand = CreateObject("ADODB.Command")$objConnection.CommandTimeout = 120$objConnection.Provider = "ADsDSOObject"$objConnection.Open ("Active Directory Provider")$objCommand.ActiveConnection = $objConnection$objCommand.CommandText = $strADSQuery$st = $objCommand.Execute$st.Movefirst$i=0Do$server_enum=""$name_enum=""$shares_enum=""$description_enum=""

$server_enum = $St.Fields("shortservername").Value$name_enum = $St.Fields("printername").Value$shares=$St.Fields("printsharename").Value

for each $share in $shares$shares_enum = $shares_enum + $sharenext

$descrs=$St.Fields("description").Valuefor each $desc in $descrs$description_enum = $description_enum + $descNext

$st.MoveNext$temp="Íàçâàíèå ïðèíòåðà: " & $name_enum & chr(13) & ↵↵↵↵↵

"Ïóòü ê ïðèíòåðó: " & "\\" & $server_enum & "\" & ↵↵↵↵↵

Page 86: 025 Системный Администратор 12 2004

84

образование

В Active Directory объектом класса printQueue являетсяпринтер. Этот объект имеет свойства, значение которых мо-жет быть двух типов: строкой и массивом. В приведенномпримере поле, содержащее название принтера, являетсястроковой переменной, а сетевое имя принтера – массивом.

Ниже приведена таблица, содержащая названия и опи-сания часто используемых полей, соответствующий им типи формат данных:

Формирование массиваИдея, лежащая в основе механизма подключения принте-ров, следующая: осуществляется попытка подключить прин-тер, затем сценарий загрузки «смотрит», что из этого по-лучилось, и в зависимости от результата предпринимаетдействия. При объяснении работы этого механизма (дляоблегчения восприятия материала) я намеренно поменялместами причину и следствие.

После того как в Active Directory найден очередной опуб-ликованный принтер и прочитаны его свойства, для негоформируется UNC-путь (\\server\sharename). Затем осуще-ствляется попытка подключить пользователю принтер исчитывать код функции, производящей подключение.

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

Для тех принтеров, на которые пользователь имеет пра-во печатать (как минимум), формируется массив, напри-мер, $access_array[$i]. Формат элементов массива следую-щий: «,,server,printername», где server – короткое имя сер-вера, printername – локальное имя принтера.

Формирование списка сетевых принтеров,подключенных пользователюПроцесс определения подключенных пользователю сете-вых принтеров основан на анализе ветви HKCU локально-го реестра (см. рис. 3).

С помощью функции ENUM осуществляется чтение на-званий папок, содержащих в себе короткое имя сервера иполное имя принтера. На основе полученной информацииформируется массив, элементами которого являются стро-ки, имеющие следующий формат: «,,server,printername», гдеserver – короткое имя сервера, printername – локальное имяпринтера.

Для удобства сравнения обоих массивов (подключен-ных принтеров и принтеров, на которые пользователь име-ет права) необходимо, чтобы форматы элементов масси-вов совпадали. Формат элементов продиктован особенно-стью построения реестра Windows 2000.

Необходимо отметить, что после формирования второ-го массива между ними соблюдаются следующее неравен-ство: М2≥≥≥≥≥М1, где М2 – массив, элементами которого явля-ются названия подключенных принтеров, M1 – принтеров,на которые пользователь имеет права. На третьем, заклю-чительном этапе добиваются выполнения следующего ус-ловия: М1=М2.

Приведение созданных списков принтеровв соответствиеСопоставление массивов М1 и М2 осуществляется с помо-щью функции ASCAN. В том случае, если функция возвра-щает значение -1, то элемент, найденный в одном массиве,

$shares_enum & chr(13) & "Îïèñàíèå: " & $description_enum.MessageBox($temp,"Õàðàêòåðèñòèêè ïðèíòåðà",0,0)$temp=""Until $st.EOF

Òàáëèöà 1

$path_enum_connect = "\\" + $server_enum + "\" + $shares_enum$connect_flag = addprinterconnection( $path_enum_connect )

if $connect_flag=0$path_full =",," + $server_enum + "," + $name_enum$print_sysinfo=$print_sysinfo+$shares_enum+": ↵↵↵↵↵

"+$description_enum+chr(13)$access_array[$i] = lcase($path_full)$i=$i+1Endif

$Index=0DO$connected_array[$index]= lcase(ENUMKEY("HKEY_CURRENT_USER\ ↵↵↵↵↵

Printers\Connections\", $Index))$Index = $Index + 1UNTIL Len($Group) =0

Ðèñóíîê 3

Page 87: 025 Системный Администратор 12 2004

85№12(25), декабрь 2004

образование

не является элементом другого. Поэтому принтер, соответ-ствующий этому элементу, должен быть отключен.

Удаление принтера осуществляется с помощью соответ-ствующей функции, параметром которой является UNC-путьпринтера. Для того чтобы сформировать этот путь, осуще-ствляется анализ ветви HKLM (см. рис. 4):

Подключение сетевых дисков. ТеорияСценарий загрузки осуществляет подключение сетевыхдисков пользователям в зависимости от их членства в груп-пах, аналогично подключению сетевых принтеров. Главнаяособенность данного сценария заключается в том, что в немреализован механизм подключения различных ресурсов наодну и ту же букву. Реализовано для пользователей, вхо-дящих в непересекающиеся группы безопасности. Необхо-димо строго следить, чтобы членства пользователей в груп-пах, подключающихся на одну букву, не пересекались.

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

В файле в квадратных скобках перечислены названияразделов, которые включают в себя букву, на которую бу-

дет монтироваться ресурс и его порядковый номер. Он при-сваивается для обеспечения возможности подключать наодну и ту же букву разные ресурсы. Каждый раздел содер-жит пять параметров: название сервера (SERVER), путь ксетевой папке (SHARE), группы безопасности, членам ко-торых будет подключаться ресурс (ACCESSGROUP1 иACCESSGROUP2), описание ресурса (DESCRIPTION). При-мер файла приведен ниже:

Таким образом, на основе данных, прочитанных сцена-рием из примера, всем пользователям будет подключен«Консультант+» на букву «L», находящийся по пути \\main\consultant. Пользователям, являющимся членами группdepartament1, departament2, departament3, будет подключендиск W. Для членов групп departament1, departament3 под-ключается ресурс по адресу \\second\work\departament1, дляdepartament2 – \\second\work\departament2.

Сценарий, обеспечивающий автоматическое управле-ние подключением сетевых дисков, работает по схеме:! Чистка локального кэша на рабочей станции, содержа-

щего список групп, в которые входит пользователь. Уда-ление ветви реестра HKEY_CURRENT_USER\Software\KiXtart.

for $i=0 to ubound($connected_array)$flag_p=0$flag_p=Ascan($access_array,$connected_array[$i])

if $flag_p=-1���endif

next

if $flag_p=-1$group=$connected_array[$i]$name_=right($group, len($group)-instrrev($group,","))$server_=right(left($group,len($group)-len($name_)-1), ↵↵↵↵↵

len(left($group,len($group)-len($name_)-1))-2)$share_=readvalue("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ ↵↵↵↵↵

Windows NT\CurrentVersion\Print\Providers\ ↵↵↵↵↵LanMan Print Services\Servers\"+$server_+"\Printers\ ↵↵↵↵↵"+$name_,"Share Name")

$disconnect_ ="\\"+$server_+"\"+$share_$r=DelPrinterConnection( $disconnect_ )

endif

Ðèñóíîê 4

[L1]SERVER=MainSHARE=ConsultantACCESSGROUP1=everyoneACCESSGROUP2=ÂñåDESCRIPTION="Êîíñóëüòàíò+"[W1]SERVER=SecondSHARE=work\department1ACCESSGROUP1=department1ACCESSGROUP2=department3DESCRIPTION="Ðåñóðñû îòäåëà 1"[W2]SERVER=SecondSHARE=work\department2ACCESSGROUP1=department2ACCESSGROUP2=DESCRIPTION="Ðåñóðñû îòäåëà 2"

Page 88: 025 Системный Администратор 12 2004

86

образование

! Чтение параметрического файла. Данные рекомендует-ся помещать в соответствующие массивы.

! Отключение всех доступных сетевых дисков.! Подключение сетевых дисков, на которые данный поль-

зователь имеет права.! Вывод на экран статистики о подключенных сетевых

дисках.

Подключение сетевых дисков. ПрактикаВ теоретической части был описан алгоритм, обеспечива-ющий автоматическое управление подключением сетевыхдисков. Поскольку все этапы взаимосвязаны, то их необхо-димо рассматривать как единое целое.

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

Процедура удаления осуществляется с помощью функ-ции DelTree():

Затем рекомендуется создать и наполнить данными ди-намический массив. Элементами этого массива являютсяназвания групп, в которые входит пользователь. В синтак-сисе языка KIXTart существует специально созданная фун-кция – EnumGroup():

Переменная $Group содержит полное название группы.Формат названия группы следующий: \\domain\group_name.Для подключения различных ресурсов необходимо вычле-нить имя группы без префикса в виде имени домена илирабочей станции. Попутно необходимо исключить группы,в названиях которых присутствует слово «- print», посколь-

ку группы, содержащие это сочетание символов, предназ-начены для управления принтерами и не принимают учас-тия в процессе подключения сетевых дисков.

На следующем этапе осуществляется чтение конфигу-рационного файла с расширением INI. Чтение параметри-ческого файла осуществляется в соответствии с алгорит-мом, приведенным на рис. 5. Итак, поскольку названия под-разделов (значения, заключенные в INI-файлах в «квадрат-ные» скобки) неизвестны, то сначала файл рассматрива-ется как обычный текстовый файл, который читается пост-рочно. Каждая строка анализируется, и если она включаетв себе символ «[», то содержимое, находящееся междуквадратными скобками, помещается в динамический мас-сив $gr[]:

После того как сформирован массив, осуществляетсяповторное чтение INI-файла. На этот раз он рассматрива-ется как параметрический файл. Осуществляется чтениепараметров. По ходу чтения параметрического диска сна-чала осуществляется попытка отключить сетевой диск, за-тем подключить его, если пользователь входит в соответ-ствующую группу безопасности. Таким образом, соблюда-ется актуальность подключенных сетевых дисков.

Ðèñóíîê 5

DelTree("HKEY_CURRENT_USER\Software\KiXtart")

DO$Group = ENUMGROUP($i)

? $Group$i = $i + 1

UNTIL Len($Group) = 0

dim $usergroup_name[]$k=0DO

$Group = ENUMGROUP($i)if instr("$Group","- Print")=0

$ug1_len=len($group)-instrrev($group,"\")ReDim Preserve $usergroup_name[$k]

$usergroup_name[$k]=right($group,"$ug1_len")$u_val=$usergroup_name[$k]$k=$k+1

endif$i=$i+1UNTIL Len($Group) = 0

$i=1dim $gr[]open(2,"@LDRIVE/shared.ini",2) ; ôàéë shared.ini ↵↵↵↵↵

ðàñïîëàãàåòñÿ â îäíîì êàòàëîãå ñî ñêðèïòîì �\\Server\NetlogonWHILE @ERROR = 0$x=ReadLine(2)$skoba=instrrev("$x","[")

if $skoba<>0ReDim Preserve $gr[$i]

$gr[$i]=right(left($x,len("$x")-1), ↵↵↵↵↵len(left($x,len("$x")-1))-1)

$i = $i + 1endifLOOP

$k=ubound($gr)for $i=1 to $k

$letter=$gr[$i]$serv=readprofilestring("$ini_file1", "$letter","server")$share=readprofilestring("$ini_file1", "$letter","share")$accessgroup1=readprofilestring("$ini_file1", ↵↵↵↵↵

"$letter","accessgroup1")$accessgroup2=readprofilestring("$ini_file1", ↵↵↵↵↵

"$letter","accessgroup2")$description=readprofilestring("$ini_file1", ↵↵↵↵↵

"$letter","description")$share_name="\\"+$serv+"\"+$share+""$let=$letter+":"$letter_S=left($letter,1)use $letter_S /deleteif ingroup("$accessgroup1","$accessgroup2")use $letter_S+":" $share_name

Page 89: 025 Системный Администратор 12 2004

87№12(25), декабрь 2004

образование

Замечание. Данные, содержащие в себе имя монтируе-мого диска в конфигурационном файле, имеют структуру –название диска + номер. Нумерация сквозная. При под-ключении ресурса нумерация отбрасывается. Таким спо-собом на одну и ту же букву монтируются различные ре-сурсы для разных пользователей. Соответственно необ-ходимо помнить, что членства в группах не должны пере-секаться.

Автоматическое конфигурированиерабочей станцииПоскольку скрипт выполняется от имени пользователя, ко-торый не обладает правами системного администратора,то изменения могут быть внесены только в ветвь HKCU. Вэтом разделе хранятся сведения о текущем зарегистриро-ванном пользователе, и он имеет название, соответствую-щее значению идентификатора безопасности (SID) текуще-го пользователя. Каждый раз при перезагрузке компьюте-ра раздел создается заново на основе данных, считанныхиз HKU. Автоматическое конфигурирование ветви HKUвыполняется с помощью групповых политик (будет рассмот-рено позже), а ветви HKCU – с помощью скрипта.

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

Блочность скриптаСогласитесь, что скрипт – это программа, которая должнаотличаться стабильностью в своей работе. А разве это необязательно для всех без исключения программ? С другойстороны, используя его на практике, могу сказать, что внем постоянно что-то изменяется и никто не застрахованот ошибки. Тестирование на локальной машине и в сети,как говорят, две большие разницы. В данной статье рас-смотрены только основные задачи, реально их гораздо боль-ше, например, в крупных организациях может быть акту-ально автоматизированное подключение баз 1с в бухгал-терии и т. д. Поэтому правильным шагом будет создать кон-фигурационный файл для этого скрипта, который бы по-зволил оперативно управлять включением и выключениемразличных блоков. В случае внештатной ситуации вы смо-жете сохранить работоспособность скрипта на 70-90%, вык-

лючив сбойный блок. Согласитесь, это гораздо лучше, чемиметь только 2 варианта, характеризующих работоспособ-ность – 0% и 100%.

Реализация идеи следующая: из конфигурационногофайла (см. пример файла kix.ini) считываются параметры,которые имеют значение 0 (выключено) и 1 (включено):

Пример файла kix.ini:

В таком случае структура скрипта будет выглядеть сле-дующим образом:

Таким образом, если необходимо протестировать какую-либо новую функцию сценария, можно создать еще одинраздел, например, «test», и размещать в нем тестируемыйкод.

Обеспечение интерактивностиработы скриптаСценарии на языке KIXTart можно визуализировать, по край-ней мере, тремя способами:! с помощью стандартных диалоговых окон;! с помощью сторонней надстройки KIXTart в виде DLL-

библиотеки;! c помощью сторонней утилиты, передающей парамет-

ры из KIXTart в HTML-файл.

Выбор вариантаРассмотрим все три способа:

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

Визуализация скрипта с помощью стороннейнадстройки KIXTart в виде DLL-библиотекиВизуализация и интерактивность работы скрипта реализу-ется с помощью специально созданной для этих целей над-стройки – KIXForms 3.2 или KIXGui 1.1. Обе программы мож-но загрузить с сайта http://www.kixtart.org.

endifnext

Òàáëèöà 2

[part]print=1share=1sysinfo=1

$config_ini ="@LDRIVE/kix.ini"; ôàéë kix.ini ðàñïîëàãàåòñÿ ↵↵↵↵↵â îäíîì êàòàëîãå ñî ñêðèïòîì - \\Server\Netlogon

open(1, $config_ini, 2)������������; îïèñûâàþòñÿ ðàçëè÷íûå ãëîáàëüíûå ↵↵↵↵↵

ïåðåìåííûå, îñóùåñòâëÿåòñÿ ñîåäèíåíèå ñ AD è äð.if readprofilestring("$config_ini","part","sysinfo")=1������������Endifif readprofilestring("$config_ini","part"," share ")=1������������Endifif readprofilestring("$config_ini","part"," print ")=1������������Endif

Page 90: 025 Системный Администратор 12 2004

88

образование

У этих программ есть только один недостаток: для кор-ректной работы визуализационной части необходимо на ра-бочей станции зарегистрировать соответствующую DLL-библиотеку. Для регистрации этой библиотеки необходи-мо обладать правами администратора. Конечно, можно со-здать MSI-архив, который будет централизованно распрос-траняться по сети с помощью групповых политик, но этонеудобно. Использовать надстройки такого рода выгоднотолько в небольших сетях с маленьким количеством рабо-чих станций.

Визуализация работы скрипта c помощьюсторонней утилиты, передающей параметрыиз KIXTart в HTML-файлЭтот способ мне кажется наиболее оптимальным для реа-лизации визуализации и интерактивности работы скриптав крупных сетях, поскольку утилита самодостаточна и пред-ставляет собой файл с расширением EXE, который реко-мендуется располагать в каталоге Netlogon, вместе соскриптом. KixWin 1.1 (http://www.kixtart.org) вызывается изскрипта с набором параметров. Затем она передает этипараметры в DHTML-файл. Для корректной работы визуа-лизационной части необходимо дать ему право на запись впапке, в которой находится DHTML-файл.

Раздробление скрипта на две части является основнымнедостатком данного варианта. DHTML-файл вместе с со-путствующими ему файлами (GIF, JPEG, CSS) рекоменду-ется располагать в скрытой сетевой папке. DHTML-файлсодержит в себе сценарии, созданные с помощью VBScriptили JScript.

Синтаксис KIXWinПриведем синтаксис утилиты и фрагмент DHTML-файла:

Описание параметров:! «dialog» – строка, содержащая строку в формате URL к

HTML-документу.! «arguments» – строка, содержащая параметры, переда-

ваемые из KIX в HTML. Для разделения параметров вHTML-файле используют строку window.dialogArguments.split(«;»). В данном примере разделителем параметровявляется «;».

! «style» – строка, которая определяет оформление диа-логового окна. Используются один или несколько из сле-дующих параметров стиля:

Логическое разделение передаваемых параметров осу-ществляется с помощью заранее оговоренного символа.

DHTML возвращает в KIX код ошибки в виде целого числа,макросу @ERROR. В случае успешного завершения опе-рации @ERROR=0.

Передача данных с помощью утилиты KIXWIN осуще-ствляется сценарием загрузки следующим образом:

DHTML-файл

Основы формирования файлаКак отмечалось ранее, параметры передаются DHTML-стра-нице, содержащей вставки на VBScript. При загрузке стра-ницы в теге body указывается функция, например,onload=”startrun()”, с помощью которой запускается таймер.В том случае, если таймер не прерван, то по окончаниюотсчета автоматическое закрывание окна и продолженияпроцесса загрузки компьютера:

Как видно из примера, в текстовой области выводитсясообщение о том, что настройка рабочей станции завер-шена и запускается таймер. Если ни одна кнопка на клави-атуре не нажималась в течение 20 000 мсек, то осуществ-ляется вызов функции exit(), которая закрывает окно брау-зера (листинг DHTML-файла на www.samag.ru/source).

Кнопки, при нажатии на которые отображается инфор-мация различного рода, представляют собой картинку снадписями на ней, которая разделена на различные облас-ти. При нажатии на описанные области осуществляетсязапуск соответствующей функции, которая, в свою очередь,отображает информацию, переданную из скрипта в тексто-вую область window.form1.textarea1:

kixwin "dialog" ["arguments"] ["options"]

dialogHeight:sHeightdialogLeft:sXPosdialogTop:sYPosdialogWidth:sWidthcenter:{ yes | no | 1 | 0 | on | off }dialogHide:{ yes | no | 1 | 0 | on | off }edge:{ sunken | raised }help:{ yes | no | 1 | 0 | on | off }resizable:{ yes | no | 1 | 0 | on | off }scroll:{ yes | no | 1 | 0 | on | off }status:{ yes | no | 1 | 0 | on | off }unadorned:{ yes | no | 1 | 0 | on | off }

shell '%0/../kixwin.exe $html "$system_info ^ ↵↵↵↵↵$hardware_info ^ Óñòàíîâëåííûå ïðîãðàììû: $en $prog ^ ↵↵↵↵↵Ïîäêëþ÷åííûå ñåòåâûå äèñêè:$en $n1 ^ Ïîäêëþ÷åííûå ↵↵↵↵↵ñåòåâûå ïðèíòåðû:$en $n2" "scroll:off;resizable:on"'

<BODY onload="startrun()" TEXT="BLACK" �>���������������������<Script Language="JavaScript">function startrun(){window.form1.textarea1.value="Ïðîöåññ íàñòðîéêè êîìïüþòåðà ↵↵↵↵↵

çàâåðøåí.\nÄëÿ ïðîäîëæåíèÿ íàæìèòå êíîïêó ÏÐÎÄÎËÆÈÒÜ ↵↵↵↵↵èëè ïîäîæäèòå 7ñåê. � îêíî çàêðîåòñÿ ñàìî."

timer1=setTimeout('exit()', 20000);}�</Script></BODY>

��<img src="bar2.jpg" name="imgAdvert" usemap="#Prosv" border=0><map name="Prosv"><area onclick=system() alt="Ñâåäåíèÿ îá îïåðàöèîííîé ↵↵↵↵↵

ñèñòåìå" shape=circle coords="69,40,50"><area onclick=hardware() alt="Ñâåäåíèÿ î êîìïüþòåðå" ↵↵↵↵↵

shape=circle coords="166,40,50">��</map><Script Language="JavaScript">��function system(){clearTimeout(timer1);var argv;argv = window.dialogArguments.split("^");document.all.parametr0 = argv[0];

Page 91: 025 Системный Администратор 12 2004

89№12(25), декабрь 2004

образование

Обратите внимание, что при вызове любой функции осу-ществляется прерывание таймера функцией clearTimeout(timer1), затем чтение соответствующего аргумента.

Обеспечение удобстваДля обеспечения удобства работы со сценарием необхо-димо изменить представление окна браузера: сделать егонеизменяемым, убрать различные панели инструментови т. д. (см. рис. 6). Для того чтобы информация выводиласькорректно, необходимо в теге META указать кодировку, вкоторой должны быть отражены символы, а именноWindows-1251:

Внедрение скрипта в эксплуатациюСкрипт выполняется каждый раз при регистрации пользо-вателя в сети, если он указан в разделе Profile свойствахпользователя (см. рис. 7) службы Active Directory: Users andComputers.

Для автоматизации установки KIXtart на рабочих стан-циях домена предлагается следующее: в папку Netlogon по-местить файлы:! KIX32.EXE !! SCRIPT.KIX !! START.BAT !! подкаталог Win9x, содержит файлы KX16.DLL и KX32.DLL

В скрытую сетевую папку скопировать DHTML-файл ивсе сопутствующие ему файлы.

В ходе выполнения файла START.BAT определяется типоперационной системы, установленной на рабочей станции,и в зависимости от результатов происходит копирование

набора файлов, необходимых KIX для работы на даннойплатформе. А затем запускает скрипт.

Пояснения к синтаксису файла START.BAT:! Принцип определения операционной системы основан

на том, что в Win9x отсутствует переменная окружения%os%. В Windows 2k переменная %os%=WindowsNT.

! С помощью строки «start /wait Kix32.exe Script.kix» до-биваются последовательной загрузки – сначала скрипт,затем рабочий стол и т. д., а не одновременной. То естьна время выполнения скрипта многозадачность «отклю-чается». Это делается для того, чтобы до окончания дей-ствия скрипта дальнейшая загрузка операционной сис-темы не производилась.

! Для корректной работы win9x, в качестве пути к файлунеобходимо указывать «%0\..\filename.ext». Windows XPне воспринимает относительного пути «%0/./», поэтомудля Windows семейства 2k необходимо указать толькоимя файла, который находится в папке Netlogon.

На время выполнения скрипта необходимо скрыть CMD-панель, в которой выполняется скрипт, и приостановить заг-

window.form1.textarea1.value=''window.form1.textarea1.value=document.all.parametr0}function hardware(){clearTimeout(timer1);var argv;argv = window.dialogArguments.split("^");document.all.parametr1 = argv[1];window.form1.textarea1.value=''window.form1.textarea1.value=document.all.parametr1}�

<META http-equiv=Content-Type content="text/html; ↵↵↵↵↵charset=windows-1251">

Ðèñóíîê 6

KIXWIN.EXEKIX.INISHARED.INI

@ECHO OFFif c:\%os%==c:\ goto win9xif not c:\%os%==c:\ goto winnt:winntstart /wait Kix32.exe Script.kixgoto kix:win9xcopy %0\..\win9x\*.dll c:\windows\system /y%0\..\Kix32.exe %0\..\Script.kixgoto kix:kix@echo End Of Batch File

Ðèñóíîê 7

Page 92: 025 Системный Администратор 12 2004

90

образование

рузку рабочего стола до окончания всего скрипта. Этогорезультата добиваются с помощью групповой политики, рас-пространяющейся на домен («Default Domain ControllersPolicy»).

В разделе групповой политики «User Configuration» не-обходимо соответственно включить «Run legacy logon scriptsynhronously» (запускать сценарий загрузки синхронно) и«Run legasy script hidden» (запускать сценарий скрыто). Дляэтого необходимо проделать следующее:! Зарегистрироваться на сервере с помощью учетной за-

писи, имеющей административные права.! Загрузить в Active Directory Users and Computers (Start →→→→→

Programs →→→→→ Administrative Tools) и войти в свойства кон-троллера домена (см. рис. 8).

Ðèñóíîê 10

Ðèñóíîê 8

Ðèñóíîê 9

! Перейти во вкладку вкладку «Group Policy» и загрузить«Default Dоmain Policy» (см. рис. 9).

! В загруженной групповой политике (Default DomainPolicy) необходимо в «User Configuration» (настройкахпользователя) войти в «Administrative Templates» (адми-нистративные шаблоны). Там выбрать раздел «System»(система), вкладку «logon/logoff» (войти/выйти) и вклю-чить раннее оговоренные политики (см. рис. 10).

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

Листинг скрипта и всех вспомогательных подпрограммприведен на сайте журнала http://www.samag.ru/source.

Page 93: 025 Системный Администратор 12 2004

91№12(25), декабрь 2004

bugtraq

Раскрытие SMB-паролей в KDEПрограмма: KDE 3.2.x, 3.3.0, 3.3.1, and 3.3.2.Опасность: Средняя.Описание: Обнаружена уязвимость в KDE. Атакующий мо-жет получить пароль пользователя на доступ к удаленномуресурсу.

Когда пользователь создает ссылку на удаленный файл,используя любое KDE-приложение, эта ссылка может со-держать пароль на доступ к удаленному файлу. Пароль дляSMB-ссылок всегда добавляется к URL в виде обычного тек-ста и сохраняется в ярлыке («*.desktop»-файл).URL производителя: www.kde.org.Решение: Установите обновления.1. Патчи для KDE 3.3.1

ftp://ftp.kde.org/pub/kde/security_patches:501852d12f82aebe7eb73ec5d96c9e6d post-3.3.1-kdebase-smb.diff5b9c1738f2de3f00533e376eb64c7137 post-3.3.1-kdelibs-khtml.difff287c900c637af2452c7a554f2df166f post-3.3.1-kdelibs-kio.diff

2. Патч для KDE 3.3.2ftp://ftp.kde.org/pub/kde/security_patches:d3658e90acec6ff140463ed2fd0e7736 post-3.3.2-kdelibs-kio.diff

3. Патчи для KDE 3.2.3ftp://ftp.kde.org/pub/kde/security_patches:d080d9acf4d2abc5f91ccec8fc463568 post-3.2.3-kdebase-smb.diffd79d1717b4bc0b3891bacaaf37deade0 post-3.2.3-kdelibs-khtml.diff94e76ec98cd58ce27cad8f886d241986 post-3.2.3-kdelibs-kio.diff

Раскрытие информации в SquidПрограмма: Squid 2.5.Опасность: Низкая.Описание: Обнаружена уязвимость в Squid. Удаленный ата-кующий может получить внутреннюю информацию от це-левого сервера.

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

URL производителя: www.squid-cache.org.Решение: Установите обновление: http://www.squid-cache.org/Versions/v2/2.5/bugs/squid-2.5.STABLE7-dothost.patch.

http://./.gz/

Обход защитыперсональных брандмауэровПрограмма: большинство персональных брандмауэров.Опасность: Низкая.Описание: Вредоносное программное обеспечение можетреализовать атаку типа shatter на разрешенное брандмау-эром GUI-приложение и выполнить произвольный код в егоконтексте. После этого вредоносное программное обеспе-чение получает возможность взаимодействовать с внешни-ми сетями в обход политик безопасности брандмауэра.Решение: Решения не существует на данный момент.

Составил Александр Антипов

Выполнение произвольного кодав Microsoft Windows Resource KitПрограмма: Microsoft Windows 2000/XP Resource Kit.Опасность: Средняя.Описание: Обнаружено несколько уязвимостей в MicrosoftWindows 2000/XP Resource Kit. Удаленный атакующий мо-жет выполнить произвольный код на уязвимой системе. Уда-ленный атакующий может предпринять XSS-нападение.

Уязвимость существует в w3who.dll в расширении ISAPIдля Windows 2000/XP Resource Kit из-за некорректной об-работки входных данных пользователей перед отображе-нием их в HTTP-заголовках или в сообщениях об ошибках.Удаленный атакующий может создать специальным обра-зом URL и выполнить произвольный HTML-код в браузерецелевого пользователя. Примеры:

Переполнение буфера существует при обработке вход-ных параметров URL. Удаленный атакующий может с по-мощью специально сформированного URL вызвать пере-полнение буфера и потенциально выполнить произвольныйкод на системе. Пример:

URL производителя: www. microsoft.com.Решение: Решения не существует на данный момент.

Connection: keep-alive<script>alert(«Hello»)</script>/scripts/w3who.dll?bogus=<script>alert(«Hello»)</script>

/scripts/w3who.dll?AAAAAAAAA...[519 to 12571]....AAAAAAAAAAAAA

Переполнение буферав Microsoft HyperTerminalПрограмма: Microsoft Windows 2000 Advanced Server,Microsoft Windows 2000 Datacenter Server, Microsoft Windows2000 Server, Microsoft Windows NT 4.0 Server, MicrosoftWindows NT 4.0 Server, Terminal Server Edition, MicrosoftWindows Server 2003 Datacenter Edition, Microsoft WindowsServer 2003 Enterprise Edition, Microsoft Windows Server 2003Standard Edition, Microsoft Windows Server 2003 Web Edition,Microsoft Windows XP Home Edition, Microsoft Windows XPProfessional.Опасность: Средняя.Описание: Обнаружена уязвимость в Microsoft HyperTerminal.Удаленный атакующий может выполнить произвольный кодна уязвимой системе.

Уязвимость обнаружена при обработке файлов сессийи telnet-ссылок. Удаленный атакующий может специальнымобразом создать файл сессии (.ht) для HyperTerminal илиURL для telnet и выполнить произвольный код на системецелевого пользователя.URL производителя: www.microsoft.com.Решение: Установите обновления с сайта производителя.