Отслеживание операций в Unix



Отслеживание операций в Unix

Для отслеживания операций с файлами и сетью в Unix можно использовать один и тот же подход. Это один из тех редких случаев, когда вызов внешней программы намного предпочтительней. Вик Абель (Vic Abell) преподнес чудесный подарок системным администраторам, написав программу Isof (LiSt Open Files), которую можно найти на ftp:// vic.cc.purdue.edu/pub/tools/unix/lsof. Isof позволяет отобразить подробную информацию об открытых в настоящий момент файлах и сетевых соединениях на Unix-машине. По-настоящему удивительной эту программу делает ее переносимость. Последняя версия программы (на момент написания этой книги) работает по крайней мере на 18 видах Unix и поддерживает различные версии этих операционных систем.

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

COMMAND PID USER FO TYPE DEVICE SIZE/OFF NODE NAME

netscape 21065 dno cwd VOIR 172,289"; 8192 12129 /-OTie

netscape 21065 dnb txt VREG 172,1246 1438236Д 656749

/net/ arch-solans (fileserver-./vol/systems/arch-solaris)

netscape 21065 dnb txt VREG 32,6 54656 35172

/usr (,/dev/ dsk/cOtOdOs6)

netscape 21065 dnb txt VREG 32;6 146740 6321

/ubr/lro/ libelf.so.1

netscape 21065 dnb txt VREG 32,6 69292 102611

/usr (/dev/ dsk/cOtOdOs6)

netscape 21065 dnb txt VREG 32,6 21376 79751

/usr/iib/ locale/en_US/en_US.so.1

netscape 21065 dnb txt VREG 32,6 19304 5804

/usrЛib/ libmp.so.2



netscape 21065 dnb txt VREG 32,6 98284 22860

usr/onenwi:' lib/libICE.so.6

netscape 21065 dnb txt VREG 32,6 46576 22891

/usr/opftrwiv lib/libSM.so.6

netscape 21065 drib txt VREG 32.6 1014020 5810

/!jsr/::.t; libc.so.1

netscape 21065 dnb txt VREG 32.6 105788 5849

/usr/ln; libm.so.1

netscape 21065 dnb txt VREG 32,6 721924 5806

netscape 21065 ar.b txt VREG 32 6 156196 5774

netscape 21065 ri^t 0. VCHP 2-1.3 Ot73 5853 > .

pseudo/bls@C:3-> ttcoirpat ->lcter"b>:neii->pis netscape 21065 dnb 3u VCHR 13,12 oto 5821

/devices/ pseudo/mm@0:zero

netscape 21065 dnb 7u FIFO Ox6034d264 C;1 47151 PIPE-> Ox6034d1eO

netscape 21065 dnb 8u met Ox6084cb68 Oxfb210er, TCP host. cos.

ne^.. edu:46575->host2.ccs,neu. edu:6000 (ESTABLISHED)

netscape 21065 dnb 29u met 0x60642848 Ot215868 TCP nost, ccs. re.. edu:46758->

www.mind-bright.se:80 (CLOSE_ WAIT)

Из этого примера можно понять, насколько мощна эта команда. Мы можем увидеть текущий рабочий каталог (VDIR), обычные файлы (VREG), символьные устройства (VCHR), каналы (FIFO) и сетевые соединения (inet), открытые этим процессом.

Самый простой способ применить программу Isof из Perl - вызвать ее в специальном режиме «field» (-F). В этом режиме вывод программы делится на специальным образом отмеченные и разделенные поля, вместо использования колонок в стиле ps. Это позволяет надежно проанализировать и распознать вывод.

У этого способа вывода результатов есть одна особенность. Вывод организован в виде «наборов процессов» (process sets) и «наборов файлов» (file sets), как их называет автор. Набор процессов - это набор полей, относящихся к одному процессу; набор файлов - это подобный же набор для файла. Все приобретет больший смысл, если включить режим разбивки на поля с параметром 0. В этом случае поля будут разделены символом NUL (ASCII 0), а наборы - символом NL (ASCII 12). Вот как будет выглядеть предыдущий вариант вывода команды, если использовать режим разбивки на поля (NUL представлен в виде символов ~@):

p21065~@cnetscape~@u6700"@Ldnb~@

fcwd"@a ~@1 "@tVDIR"@DOx2bOOb4b"@s8192"@i12129"@n/home/dnb"@

ftxt"@a ~@1 >tVREG"@DOx2b004de"@s14382364"@i656749"@n/net/arch-solaris (fileserver:/vol/systems/arch-solaris)"@

ftxt~@a "@1 ~@tVREG"(5)DOx800006~@s54656~@i35172~@n/usr (/dev/dsk/cOtOdOs6)"@ ftxt"@a "@1 "@tVREG"@OOx800006"@s146740"@i6321"@n/usr/lib/libelf.so.1"@ ftxt"@a "@1 "@tVREG"@DOx800006"@s40184"@i6089"ian/usr (/dev/dsk/cOtOdOs6)"@ ftxt"(5>a "@1 "@tVREG"@DOx800006"@s69292"@i102611"@n/usr (/dev/dsk/cOtOdOs6)"@

ftxt"@a ~@1 •@tVREG"@DOx800006"@s21376"@i79751"@n/usr/lib/locale/en_US/ en_US.so.1"@

ftxt"@a ~@1 "@tVREG"№Ox800006"@s19304"@i5804"@n/usr/lib/libmp. so. 2"@

ftxt"@a "@1 ~@tVREG"@DOx800006"@s98284"@i22860"@n/L>sr/openwin/lib/ libICE.so.6"@ ftxt~@a ~@1 "@tVREG"@DOx800006"@s46576"@i22891"@n/usr/openwin/lib/ libSM.so.6"<°>

ftxt"@a ~@1 "@tVREG"@DOx800006"@s1014020"@i5810"@n/usr/lib/libc.so.1"@ ftxt~@a ~@1 ~@tVREG~№Ox800006~@s105788~@i5849~<a>n/usr/lib/libm. so. 1"@ ftxt"@a "@1 "§tVREG"@DOx800006'@s721924"@i5806"@n/usr/lib/libnsl.so.Г@

ftxt"@a "@1 "@tVREG"@DOx800006"§s166196"@i5774"@n/usr/lib/ld.so.Г@ fO"@au~@l "@tVCHR"@DOx600003"iao73~(ai5863"(an/devices/pseudo/ pts@0:3->ttcompat->ldterm->ptem->pts"@

f3"@au"@l "@tVCHR"@DOx34000c"@oO"§i5821"@n/devices/pseudo/mm(s)0:zero"(8i f7"@au"@l "@tFIFO"@dOx6034d264"@o1"@i47151"@nPIPE->Ox6034d1eO"@

f8"@au"@l "@tinet"@dOx6084cb68"@o270380692"(9>PTCP''@nhost.ccs.neu.edu:46575-> host2.cos.neu.edu: 6000"@TST=ESTABLISHED~@

f29"@au"@l "@tinet"@dOx60642848"@o215868~@PTCP"@nhost.ccs.neu.edu:46758-> www.mindbright.se: 80"(a>TST=CLOSE_WAIT~@

Давайте разберемся с этими данными. Первая строка - это набор процессов (это можно понять по первому символу р):

p21065~(acnetscape~@u6700~@Ldnb~(a

Каждое поле начинается с буквы, определяющей его содержимое (о -идентификатор процесса (pid), с - команда, и - идентификатор пользователя (uid) и L - имя пользователя (login)), и заканчивается символом разделителя. Все поля в строке создают набор процесса. Все последующие строки вплоть до очередного набора процесса описывают открытые файлы/сетевые соединения процесса, описываемого своим набором.

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

use Text::Wrap;

Slsofexec = "/usr/local/Din/lsof"; 8 путь к Isof

8 режим (F)ield, разделитель NUL (0), показывать (L)ogin,

8 тип файла (t)ype и имя файла (n)ame

$lsofflag = "-FLOtn";

open(LSOF,"$lsofexec $lsofflag[") or

die "Невозможно запустить $lsofexec:$!\n";

while(<LSOF>){

8 работаем с набором процесса if (substr($_,0,1) eq "p"){

($pid,$login) = split(/\0/);

$pid = substr($pid,1,length(Spid)); }

# работаем с набором файла.

# Замечание: мы интересуемся только обычными файлами

if (substr($_,0,5) eq "tVREG"){

($type,$pathname) = split(/\0/);

# процесс может дважды открыть один и тот же файл,

# поэтому мы должны убедиться, что запишем его

# только один раз

next if ($seen{$pathname} eq $pid); $seen{$pathname} = $pid;

Spathname = substr($pathname,1,length($pathname));

push(@{$paths{$pathname}},$pid);

}

close(LSOF);

for (sort keys %paths){

print "$_:\n";

print wrap("\t","\t",join(" ",@{$paths{$_}})),"\n";

}

В этом случае Isof будет показывать только некоторые из полей. Можно обойти в цикле весь вывод, собирая имена файлов и идентификаторы процессов в хэш списков. Когда будут обработаны все выведенные данные, следует ввести имена файлов в виде отформатированного списка процессов (спасибо Дэвиду Шарноффу (David Muir Sharnof f) за модуль Text: :Wrap):

/usr (/dev/dsk/cOtOdOs6):

115 117 128 145 150 152 167 171 184 191 200 222 232 238

247 251 276 285 286 292 293 296 297 298 4244 4709 4991

4993 14697 20946 21065 24530 25080 27266 27603

/usr/bin/tcsh:

4246 4249 5159 14699 20949

/usr/bin/zsh:

24532 25082 27292 27564

/usr/dt/lib/libXm.so.S: 21065 21080

/usr/lib/ld.so.1:

115 117 128 145 150 152 167 171 184 191 200 222 232 238

247 251 267 276 285 286 292 293 296 297 298 4244 4246 4249 4709 4991

4993 5159 14697 14699 20946 20949 21065

21080 24530 24532 25080 25082 25947 27266 27273 27291

27292 27306 27307 27308 27563 27564 27603

/usr/lib/libc.so.1:

267 4244 4246 4249 4991 4993 5159 14697 14699 20949

21065 21080 24530 24532 25080 25082 25947 27273 27291

27292 27306 27307 27308 27563 27564 27603

Чтобы показать последний код, относящийся к отслеживанию операций с файлами и сетью в Unix, вернемся к поиску запущенных IRC-po-ботов из приведенного ранее примера. Существует более надежный способ найти такие процессы-демоны, чем изучение таблицы процессов. Пользователь может скрыть имя робота, переименовав исполняемый файл, но для того чтобы спрятать сетевое соединение, ему придется очень хорошо потрудиться. В большинстве случаев это соединение с сервером на портах 6660-7000. Программа Isof позволяет без труда отыскивать такие процессы:

Slsofexec = "/usr/local/bin/lsof" Slsofflag = "-FLOc -iTCP: 6660-7000";

ft это срез хэша. используемый для предварительной загрузки

и таблицы хэшей, существование этих ключей мы будем проверять

и позже. Обычно это записывается так:

ft %approvedclients = ("ircll" => undef, "xirc" => undef, ...);

ft (но такой вариант - отличная идея, воплощенная Марком-

ft Джейсоном Доминусом(МагК-иа50п Dominus))

@>approvedclients{"ircH" , "xirc" , "pirc"} = ();

open(LSOF, "$lsofexec $lsofflag|") or die "Невозможно запустить $lsofexec:$! \n" ;

while(<LSOF>){

($pid,$command,$login) = /p(\d+)\000

c(.+)\000 L(\w+)\000/x;

warn "$login использует неразрешенный клиент с именем

$conimand (pid $pid)l\n" unless (exisTs $approvedclients{$command});

close(LSOF);

Это самая простая проверка из всех возможных. Она позволяет отловить тех, кто догадается переименовать eggdrop б pine или -tcsh, и тем более тех, кто даже не попытается спрятать своего робота. Тем не менее, она подвержена тому же недостатку, что и предыдущий вариант тестирования. Если пользователь достаточно умен, он может переименовать робота во что-то из списка «разрешенных клиентов». Чтобы продолжить игру в кошки-мышки, можно предпринять еще как минимум два шага:

  • Запустить Isof для проверки того, что файл, открытый для данной исполняемой программы, известен как тот, который мог быть открыт этой программой, а не произвольный файл из файловой системы.
  • Применить методы управления процессами для проверки того, что пользователь запускает программу из существующего интерпретатора. Если это единственный процесс, запущенный пользователем (т. е. если пользователь оставил его, а сам завершил работу), он, вероятно, является демоном, а значит и роботом.

Игра в кошки-мышки привела нас к точке, позволяющей завершить эту главу. В главе 3 мы говорили, что пользователи совершенно непредсказуемы. Они делают такие вещи, которые системные администраторы не могут даже предвидеть. Известно старое изречение: «Защиты от дураков не существует, потому что дураки изобретательны». С этим фактом придется считаться при программировании на Perl для администрирования пользователей. В итоге вы будете писать более надежные программы. Когда одна из ваших программ начнет «ругаться» из-за того, что пользователь сделал что-то неожиданное, вы сможете спокойно сидеть и наслаждаться человеческой изобретательностью.



Содержание раздела