Сценарий Perl помогает предотвращать кражи

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

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

Технические требования и поиск решений

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

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

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

Решение. Использовать модули Perl Net::Ping для опроса рабочих станций и Mail::Sendmail для отправки уведомлений по электронной почте или на пейджер. Код сценария разбит на отдельные процедуры опроса и отправки уведомлений.

Требование 2. Отправляемое на пейджер сообщение должно содержать имя и местоположение выключившейся рабочей станции.

Соображения: помимо адресов IP в списке опрашиваемых компьютеров следует указывать их имена и местонахождение. В тексте описания местонахождения могут содержаться символы пробела.

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

Требование 3. Список получателей сообщений может изменяться, так что процедура внесения изменений должна быть максимально упрощена.

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

Решение. Создать список номеров пейджеров получателей сообщений в виде отдельного входного файла. Сценарий проверяет наличие входного файла и при его отсутствии возвращает сообщение об ошибке.

Требование 4. Необходимо фиксировать факт отсутствия связи с компьютером в специальном журнале. Описание события должно включать время возникновения события, имя компьютера и другие данные.

Соображения: и служба безопасности, и менеджеры компании должны иметь возможность анализировать время краж оборудования и место, где это происходит.

Решение. Сценарий ведет журнал, в который заносятся сведения о фактах отсутствия связи с компьютером. Имя файла журнала содержит сведения о дате и времени создания журнала. В журнал записывается время возникновения события, название компьютера и дополнительные сведения об инциденте.

Требование 5. При ежедневном запуске сценария происходит опрос всех компьютеров из списка. По результатам инициализации создается временный список компьютеров, работающих в данный момент.

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

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

Требование 6. Когда обнаруживается отключение компьютера, который считается работающим, об этом посылается уведомление. Если компьютер вновь начинает отвечать, должно посылаться сообщение «отбой тревоги».

Соображения: необходимо отслеживать предыдущее состояние каждого опрошенного узла. При обнаружении изменения состояния объекта посылается сообщение с указанием нового состояния объекта - включен или выключен. Для реализации описанной схемы можно использовать один файл, множество файлов (на каждый сетевой компьютер), потоковые файлы NTFS или же списки Perl. Операции чтения файлов и потоков NTFS потребуют дополнительных затрат и ресурсов.

Решение. Создать в Perl список отказавших узлов. Если узла в списке нет, значит, при последнем опросе он отзывался.

Требование 7. Минимизировать число ложных тревог, но не в ущерб скорости обнаружения и оповещения.

Соображения: результаты ping не всегда достоверны. Иногда случается, что ping в первый раз не проходит, но при повторной попытке выполняется успешно. Разовый отказ ping может быть вызван одномоментным сбоем в сети, и такую возможность необходимо предусмотреть, чтобы не вызывать ложную тревогу. Можно, конечно, при вызове ping указать длительное значение тай-маута, но это вызовет существенную задержку работы и снизит оперативность оповещения.

Решение. При разовом отказе ping производить повторный опрос того же компьютера. Сообщение на пейджер отправляется только в случае двойного отказа.

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

Соображения: мы все равно отслеживаем, включены компьютеры или выключены. Чтобы определить уровень риска, достаточно просто посчитать число отключенных компьютеров.

Решение. Посчитать число отказавших узлов в списке Perl (см. требование 6). Если такой компьютер всего один, риск невелик, два - уже «тепло», три и более - «горячо».

Дополнительное пожелание 2: при обнаружении потенциальной проблемы перевести систему обнаружения в состояние повышенной готовности.

Соображения: мы все равно выполняем опрос узлов сети, проверяя, все ли благополучно. Если один из узлов оказывается отключенным, мы сокращаем интервал между последующими опросами для повышения чувствительности системы контроля. Если отключенная машина включилась вновь, восстанавливается первоначальное значение интервала опроса.

Решение. Поместить проверку списка отказавших узлов в условный блок и сокращать интервал опроса с 30 до 10 с после обнаружения первого отказа одного из узлов. Замечание: если приходится опрашивать большое количество узлов, может потребоваться существенно увеличить интервал опроса, который производится последовательно, а не параллельно.

Необходимые ресурсы

Цели поставлены, задачи определены - теперь за работу! После того как были сформулированы требования и найдены решения, стало ясно, какие ресурсы нужны для создания сценария. В соответствии с требованием 1, нам понадобится Perl и дополнительные модули Net::Ping и Mail::Sendmail.

Дистрибутив Perl и модуль Net::Ping можно получить на сервере ActiveState (http://www.activestate.com). Мы установили ActivePerl на одном из компьютеров, который должен выполнять опрос всех машин. Далее мы выполнили приведенные в Листинге 1 команды для запуска диспетчера пакета Perl Package Manager (PPM), который включен в состав ActivePerl, чтобы загрузить и установить модули Net::Ping и Mail::Sendmail.

В Листинге 1 загрузка Mail::Sendmail происходит с сайта RTO (http://rto.dk/packages). Этот модуль можно загрузить и с Comprehensive Perl Archive Network (CPAN-http://www.cpan.org). Файлы документации PPM ppm.html и ppmproxy.htm устанавливаются вместе с ActivePerl. Данные документы помогут изучить PPR и настройки PPM для работы с межсетевым экраном.

Сценарий TheftDetector.pl

Для решения проблем службы безопасности мы написали сценарий TheftDetector.pl (в Листинге 2 приведен полный код программы без некоторых комментариев, опущенных из соображений экономии места). При разработке сценариев Perl мы придерживаемся определенного набора правил написания программ. В начале текста идут предложения Use, определяющие используемые модули. Команды Title и Color задают внешний вид на тот случай, если сценарий будет выполняться в интерактивном режиме. В заголовке мы всегда указываем автора, контактную информацию, дату создания, версию, синтаксис, необходимые модули, описание входных и выходных файлов, примеры значений параметров конфигурации.

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

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

Весь сценарий TheftDetector.pl разбит на три подпрограммы. В основном цикле сценария - TestObjects - выполняется опрос компьютеров и проверяется, какие из них откликаются, а какие нет. Модуль Net::Ping позволяет задать время ожидания отклика (мы установили 5 с) - см. метку E в Листинге 2 (если приходится выполнять сценарий в медленной сети, может потребоваться более длительный интервал тайм-аут). Обратите внимание на метку F, где код выполняется в случае отказа при первом вызове кода, помеченного E, - сообщение о тревоге посылается только в том случае, если компьютер не отзывается на оба вызова. Подпрограмма инициализации Initialize содержит еще один опрос H для создания списка работающих на момент инициализации компьютеров.

Процедура Page использует модуль Mail::Sendmail для отправки сообщений электронной почты или уведомлений на пейджер. Описание этого модуля содержится в тексте модуля sendmail.pm, устанавливаемого PPM, и на странице http://alma.ch/perl/mail.htm.

Загрузить полный текст сценария можно на сайте www.win2000mag.com. Там же находятся два тестовых входных файла со списками получателей сообщений и списком опрашиваемых компьютеров - PagerRecipients.txt и TestObjects.txt. Текст сценария содержит подробные комментарии.

Перед началом промышленного использования мы опробовали свой сценарий TheftDetector.pl на серверах и рабочих станциях, работающих под управлением Windows 2000 и Windows NT 4.0 с установленными пакетами исправлений SP5 и SP6. Мы использовали ActivePerl 5.6.1, сборки 623. Напомню, что все сценарии и программы перед использованием в реальных условиях необходимо проверять в тестовой среде.