2003 г
Cистемное протоколирование в Linux
Виктор Костромин
20.02.2003
Открытые системы, #02/2003
Каждый из начинающих пользователей Linux рано или поздно может встретиться с какими либо проблемами в работе системы. Обычно в таких случаях новичкам советуют смотреть <логи>.
На программистском сленге <логи> (журнальные файлы, log) - протоколы работы, которые ведутся операционной системой и многими программами (вместо слова <протокол> в этом смысле часто используется и слово <журнал>). Существует две основных ситуации, в которых возникает необходимость анализа протокола: когда происходят какие-то сбои в работе системы, или когда система взломана злоумышленником, и требуется провести расследование, чтобы закрыть <дыры>. Одним из самых известных случаев использования файлов протоколов для обнаружения вторжения злоумышленника является история поимки Кевина Митника, в которой немалую роль как раз и сыграли журнальные файлы.
Формирование сообщений для протокола
При создании программ на языке Си их разработчики имеют возможность в необходимых случаях вставить вызов специальных библиотечных функций openlog, setlogmask, syslog и closelog, посылающих сообщения о тех или иных событиях при выполнении программы специальному системному демону syslogd, ведущему системный протокол. Функция openlog устанавливает связь с этим демоном, функция syslog формирует конкретное сообщение для записи в протокол, а функция closelog закрывает связь. Сообщения, формируемые функцией syslog, состоят из нескольких полей, разделяемых пробелами. Каждое сообщение начинается с поля PRI, которое в закодированном виде содержит информацию о категории сообщения (facility) и уровне серьезности (severity level) или приоритете (priority) сообщения.
Категория (facility) - информация о том, к какому классу относится данное сообщение (от 0 до 23). Категории определяются в файле /usr/include/sys/syslog.h), например: 0 (kern) - сообщения ядра; 1 (user) - сообщения от программ пользователя; 3 (daemon) - сообщения системных демонов, которые в отличие от FTP или LPR не имеют выделенных специально для них категорий; 9 (cron) - сообщения от системного планировщика и т.п. Категория не имеет, вообще говоря, никакого отношения к имени программы, которая шлет сообщения демону syslogd. Более того, некоторые программы могут порождать сообщения разных категорий. Например, демон telnetd в случае неудачных попыток входа в систему порождает сообщения категории authpriv, а в других случаях относит свои сообщения к категории daemon.
Второй параметр, на основе которого формируется значение поля PRI - это уровень или приоритет сообщения (priority). Стандартно заданы 8 уровней важности (они тоже определены в файле /usr/include/sys/syslog.h), например: 0 (emerg) - чрезвычайная ситуация, система неработоспособна; 2 (crit) - критическая ошибка; 6 (info) - информационное сообщение. При формировании сообщения функцией syslog числовое значение категории умножается на 8 и складывается с числовым значением приоритета, получившееся число заключается в угловые скобки и записывается в поле PRI.
Вслед за полем PRI в сообщение включаются поля: TIMESTAMP - время формирования сообщения, HOSTNAME - имя или IP-адрес хоста, MSG - произвольный текст сообщения в коде ASCII. Время записывается в формате: без указания года, что необходимо учесть при организации долговременного хранения файлов протокола. Имя хоста включается в сообщение, чтобы обеспечить возможность ведения протоколов на одном из выделенных компьютеров в сети. Если компьютер имеет несколько интерфейсов с различными IP-адресами, то в качестве имени или адреса хоста может быть использовано любое из них. Текст сообщения (MSG) содержит этикетку (TAG) и тело сообщения (CONTENT). Обычно в качестве этикетки используется простое имя программы, иногда дополненное идентификатором процесса, заключенным в квадратные скобки.
Обработка сообщений демоном syslogd
Все сообщения, формируемые отдельными программами с помощью функции syslog, отправляются через сокет /dev/log системному демону syslogd. Надо сказать, что вообще-то в системе запускаются два демона протоколирования: syslogd и klogd, входящие в состав пакета sysklogd (www.infodrom.org/projects/sysklogd). Демон klogd отвечает за протоколирование событий, происходящих в ядре системы. Ядро не может использовать стандартную функцию syslog - стандартные библиотеки предназначены для использования только обычными приложениями, а поскольку ядро тоже нуждается в аналогичных функциях, в него включены свои библиотеки, недоступные приложениям, поэтому ядро использует свой собственный механизм генерации сообщений.
Обработка сообщений демоном syslogd состоит в том, что он постоянно отслеживает появление сообщений и сравнивает каждую пришедшую запись с правилами, которые находятся в файле /etc/syslog.conf и записываются в виде строки, состоящей из двух полей. Левое поле () задает один или несколько шаблонов, по которым отбираются сообщения. Правое (<действие>) определяет порядок обработки отобранных сообщений. Каждый шаблон в поле имеет вид <категория.уровень>. Значениями поля <категория> может служить одно из условных наименований категорий, несколько таких наименований или символ <*> (все категории). Значениями поля <уровень> может служить одно из условных наименований уровня, символ <*> (все сообщения данной категории, независимо от уровня) или слово none (не записывать сообщения данной категории).
Когда обнаруживается соответствие категории и уровня полученного сообщения с одним из шаблонов поля какой-то строки, syslogd обрабатывает запись в соответствии с действием, прописанным в правом поле данной строки. В поле <действие> может стоять:
- имя файла протокола;
- название именованного канала (FIFO);
- указание на терминал или консоль (как на устройство: /dev/tty1);
- указание на удаленный хост;
- список пользователей, на терминалы которых будет послано сообщение по данному правилу.
В качестве устройства в поле <действие> можно указать также принтер - /dev/lp0, что целесообразно, когда речь идет об особо важных системах. Протоколы, которые распечатаны, не могут быть стерты или изменены хакерами, так что это неплохое применение для старого матричного принтера.
Кроме строк с правилами в файле /etc/syslog.conf, могут содержаться пустые строки и строки комментариев. Подробнее о структуре файла /etc/syslog.conf можно прочитать на man-страничке syslog.conf.
Если сообщение соответствует шаблонам двух или более строк, оно будет обрабатываться по каждому из этих правил. Кроме того, если в поле перечислены несколько пар <категория.уровень>, то последующие пары могут отменить действие предыдущих. Пример такой отмены дан на рис. 1 - в файл /var/log/messages записываются все сообщения, уровень которых равен или выше info, однако при этом пропускаются (не записываются) сообщения категорий mail, authpriv и cron.
![](/pictures/1x1.gif) |
![](/pictures/1x1.gif) |
# Выдавать все сообщения от ядра на консоль.
#kern.* /dev/console
# Записывать в протокол все сообщения уровня info или выше,
# кроме сообщений почтовой системы, содержащих конфиденциальную
# информацию аутентификационных сообщений и сообщений демона cron.
*.info;mail.none;authpriv.none;cron.none /var/log/messages
# Записывать в отдельный файл сообщения, содержащие конфиденциальную
# информацию аутентификации, независимо от их уровня.
authpriv.* /var/log/secure
# Все сообщения почтовой системы тоже записывать отдельно.
mail.* /var/log/maillog
# Протоколировать действия демона cron.
cron.* /var/log/cron
# Сообщения о чрезвычайных ситуациях должны немедленно
# получить все пользователи системы
*.emerg *
# Сообщения от служб новостей уровня crit и выше записывать в отдельный файл.
uucp,news.crit /var/log/spooler
# Сообщения, выдаваемые на этапе загрузки, копировать в файл boot.log
local7.* /var/log/boot.log
|
|
Рис. 1. Пример файла /etc/syslog.conf для Red Hat Linux 7.1
Из рис. 1 видно, что большинство сообщений просто записывается в различные файлы протоколов, расположенные в каталоге /var/log или его подкаталогах, причем основным файлом системного протокола в Red Hat Linux является файл /var/log/messages. В него не попадают только сообщения категорий mail, authpriv и cron (для которых выделены отдельные файлы).
Файл протокола /var/log/messages
Каждая строка в файле протокола содержит запись одного сообщения, состоящую из следующих полей: дата, имя хоста и текст сообщения. Во-первых, стоит заметить, что если ваш компьютер не работает круглосуточно, а выключается на ночь, то в этом файле можно обнаружить записи о нескольких <рабочих циклах>, начинающихся с загрузки компьютера и заканчивающихся выключением его. Начинается такой цикл с сообщения о запуске демонов протоколирования (это и понятно, до их запуска сообщения не фиксировались):
Sep 17 08:32:56 kos3 syslogd 1.4-0: restart.
Сен 17 08:32:56 kos3 syslog: запуск syslogd
succeeded
Sep 17 08:32:56 kos3 kernel: klogd 1.4-0, log
source = /proc/kmsg started.
Сен 17 08:32:56 kos3 syslog: запуск klogd
succeeded
Далее в файле протокола можно обнаружить версию ядра, параметры его запуска:
Sep 17 08:32:56 kos3 kernel: Kernel command line:
auto BOOT_IMAGE=linux ro root=303
BOOT_FILE=/boot/vmlinuz-2.4.2-2
информацию о типе процессора и объеме оперативной памяти:
Sep 17 08:32:56 kos3 kernel: Memory:
125652k/130560k available (1365k kernel code,
4200k reserved, 92k data, 236k init, 0k highmem)
Sep 17 08:32:56 kos3 kernel: CPU: Intel(R)
Pentium(R) 4 CPU 1.60GHz stepping 02
Без труда в этом файле можно найти строки, содержащие информацию о дисковой памяти (включая информацию о геометрии диска, структуре дисковых разделов и используемых прерываниях), информацию о периферийных устройствах, о запуске отдельных служб и сервисов, информацию о подключении файловых систем и сообщения о логировании пользователей, а также сообщения о некоторых ошибках. Структура каждого такого сообщения подобна структуре записей, приведенных выше в качестве примеров. Записи в других файлах протоколов, упоминаемых в файле /etc/syslog.conf, имеют примерно такую же структуру, как записи в /var/log/massages.
Команды logger и tailf
Из предыдущего описания можно сделать вывод, что выдача всех сообщений для системных журналов должна быть заложена программистом на этапе создания программы. Это не совсем так. Пользователь тоже имеет возможность послать сообщение демону syslogd. Для этого в Linux имеется команда logger, входящая в состав пакета util-linux. В первую очередь эта команда предназначена для обеспечения возможностей протоколирования при создании разного рода скриптов оболочки. Но ее можно запустить и непосредственно из командной строки, например, для ознакомления с возможностями системы протоколирования. Формат запуска команды:
logger [-isd] [-f file] [-p PRI] [-t TAG]
[-u socket] [MSG ...]
Параметры командной строки:
- -i - включать в сообщение номер процесса;
- -s - дублировать сообщение на stderr;
- -d - использовать при отправке сообщений режим дейтаграмм (вместо обычного потокового);
- -f имя-файла - сохранять сообщение в указанном файле;
- -p facility.level - задать категорию и приоритет сообщения;
- -t TAG - задать поле TAG;
- -u socket - отправлять сообщение в указанный сокет, вместо обращения к syslogd;
- MSG - текст сообщения.
Пошлите несколько сообщений с помощью программы logger и полюбуйтесь на результат в файле /var/log/messages. Кстати, имеется очень интересный способ просмотра сообщений, записываемых в файл /var/log/messages командой logger. Способ этот основан на использовании специальной программы tailf. Откройте окно терминала, получите права суперпользователя и выполните в этом окне команду tailf /var/log/messages. После этого переключитесь в другой терминал и выполните команду logger произвольный_текст. Ваше сообщение тут же отобразится в том окне, где запущена программа tailf.
Протоколирование в сети
Как было сказано, сообщения системы протоколирования могут отправляться демоном syslogd на удаленный хост, но там его кто-то должен принять. Оказывается, делает это такой же демон syslogd, запущенный на этом удаленном хосте. Точнее, syslogd на любом компьютере может прослушивать не только сокет /dev/log (принимая тем самым сообщения от местных источников), но еще и порт 514/UDP, что обеспечивает прием сообщений с других компьютеров локальной сети (и последующую запись их в локальный файл). Тем самым обеспечивается возможность создания <сервера протоколирования>, что может оказаться очень удобно для системного администратора (в одном месте отслеживаются все события в сети), а также повышается безопасность, поскольку сообщения о проникновении хакера на один из хостов сети не могут быть тут же этим хакером удалены из протокола. Однако для организации такого <сетевого протоколирования> необходимо предпринять некоторые дополнительные усилия.
Во-первых, поскольку для приема и отправки сообщений по сети используется порт 514/UDP, он должен быть доступен на обоих компьютерах (клиенте и сервере). Для этого в файле /etc/services на обоих компьютерах должна присутствовать строка
syslog 514/udp.
Если такая строка отсутствует, syslogd не может ни принимать сообщения, ни отправлять их в сеть, поскольку не может открыть UDP-порт. Если такая ситуация возникает, syslogd немедленно прекращает записывать какие-либо сообщения даже в локальный протокол. При этом, как показывает команда ps, он остается в памяти и даже сохраняет сообщения в каких-то буферах, поскольку, если указанную строку восстановить в файле /etc/services на клиенте, то, по крайней мере часть <пропавших> сообщений все же появляется в протоколе (после перезапуска syslogd). Во-вторых, при запуске демона syslogd на сервере должна быть указана опция -r, которая обеспечивает возможность приема сообщений из сети (по умолчанию демон syslogd ждет сообщения только от локального сокета). В-третьих, должны быть соответствующим образом исправлены настройки в файлах /etc/syslog.conf на обоих компьютерах. Например, если вы хотите все сообщения перенаправить на сервер протоколирования, необходимо на компьютере-клиенте прописать в файле /etc/syslog.conf строку вида:
*.* @hostname
Если в вашей сети несколько доменов, которые обслуживаются одним сервером протоколирования, то не удивляйтесь, что в протоколе на сервере будут указаны полные имена клиентов (с указанием домена). Правда, при запуске syslogd можно использовать опции -s список_доменов или -l список_хостов, которые обеспечивают замену в протоколе полных имен хостов на их краткие имена (без указания домена). Не забудьте после корректировки опций запуска и файла /etc/syslog.conf перезапустить демон, поскольку sysklogd не перечитывает конфигурационные файлы автоматически.
Запуск демона syslogd
Оба демона протоколирования запускаются на этапе инициализации системы посредством скрипта /etc/rc.d/init.d/syslog, однако для того, чтобы задать параметры запуска, нет необходимости корректировать этот скрипт - начиная с версии 7.2, в дистрибутиве Red Hat опции запуска обеих демонов считываются из отдельного конфигурационного файла /etc/sysconfig/syslog. Среди некоторых возможных параметров запуска демона syslogd можно назвать следующие:
- -d - отладочный режим. При этом демон не переходит в фоновый режим и выдает все сообщения на текущий терминал;
- -f имя-конфигурационного-файла. Задает имя альтернативного конфигурационного файла, который будет использоваться вместо заданного по умолчанию /etc/syslog.conf;
- -l список-хостов - задание списка хостов, имена которых не должны записываться с указанием полного доменного имени (FQDN - Full Qwalified Domain Name);
- -m минут - запущенный без этой опции sysklogd через каждые 20 минут записывает в протокол сообщения категории mark (временные отметки). С помощью опции -m можно либо изменить интервал между отметками, либо вовсе отменить выдачу таких сообщений;
- -p socket - задание альтернативного сокета UNIX (вместо прослушиваемого по умолчанию /dev/log);
- -r - разрешение принимать сообщения от удаленных хостов;
- -x - запрет определения имени хоста по его адресу для предотвращения зависания при работе на одном хосте с сервером DNS.
После запуска демона syslogd создается файл статуса /var/lock/subsys/syslog нулевой длины, и файл с идентификационным номером процесса /var/run/syslogd.pid.
С помощью команды
kill -SIGNAL `cat /var/run/syslogd.pid`
можно послать демону syslogd один из следующих сигналов: SIGHUP - перезапуск демона; SIGTERM - завершение работы; SIGUSR1 - включить/выключить режим отладки.
Другие файлы и команды
Файлы протоколов, упоминаемые в /etc/syslog.conf обычно располагаются в каталоге /var/log и его подкаталогах. Но, если заглянуть в этот каталог, то мы обнаружим там несколько файлов, которые в /etc/syslog.conf не упоминались.
Файл dmesg. Необходимо сказать, что в Linux имеется команда с таким же названием и если сравнить вывод этой команды (когда она запущена без параметров) с содержимым файла /var/log/dmesg, то обнаружится, что они очень похожи, хотя и не идентичны (направьте вывод команды в файл dmesg2 и сравните файлы dmesg и dmesg2). Точнее, файл /var/log/dmesg один в один совпадает с началом того вывода, который мы получим по команде dmesg. В ядре имеется кольцевой буфер, в который записываются сообщения демона протоколирования ядра - сообщения, которые записываются в этот буфер в процессе загрузки, и составляют содержание файла /var/log/dmesg. По-видимому, этот файл формируется по окончанию загрузки системы.
Все сообщения категории kern выдаются также и на консоль, где они быстро пробегают и вы вряд ли успеваете их прочитать и осмыслить, но зато они сохранены в файле /var/log/dmesg. После окончания процесса загрузки запись сообщений от ядра в кольцевой буфер продолжается и когда выполняется команда dmesg, то выдается текущее состояние буфера, поэтому вывод этой команды содержит больше сообщений, чем файл /var/log/dmesg.
Все сообщения из /var/log/dmesg можно обнаружити и в файле /var/log/messages, только там они чередуются с сообщениями от других программ. Имеется только одно существенное различие: в файле dmesg время и источник сообщения (имя хоста и категория сообщения) не указываются. Хост тут всегда <местный>, а начало отсчета времени определяется последней перезагрузкой компьютера.
Файлы lastlog и wtmp. Файл lastlog хранит информацию о последнем входе пользователя в систему, например:
Last login: Wed Oct 9 19:25:53 on tty1
Эта строка формируется утилитой login, которая после авторизации пользователя обращается к файлу /var/log/lastlog, извлекает оттуда информацию о предыдущем успешном входе, выдает ее на экран, а затем обновляет запись в файле lastlog. В отличие от файла /var/log/lastlog, который содержит записи о времени последнего входа в систему каждого пользователя, в файле /var/log/wtmp запоминаются все входы и выходы пользователей в систему с момента создания этого файла. Если же вы хотите узнать, кто из пользователей работает в системе в данный момент, надо обратиться к файлу /var/run/utmp. Между прочим, руководство man утверждает, что простые пользователи должны быть лишены права записи в файл utmp, так как многие системные программы (по каким-то необъяснимым причинам) зависят от его целостности. Вы рискуете нарушить работу системы, если предоставите любому пользователю возможность производить записи в файл utmp. Как и в файле lastlog, записи в /var/log/wtmp и /var/run/utmp делаются в двоичном формате, так что просматривать их можно только с помощью специальных команд.
Команда last выводит все записи из файла /var/log/wtmp, т. е. историю работы пользователей в системе. При этом указывается имя пользователя, терминал, время входа и выхода из системы, а также продолжительность сеанса работы. В случае, если работа пользователя прервалась из-за отключения самой системы, вместо времени выхода пользователя стоит слово . Время повторного запуска отображается отдельными строками, начинающимися словом . Команда lastb подобна last, но выводит информацию о неудачных попытках входа в систему (эта команда будет работать только в том случае, если существует файл /var/log/btmp). Впрочем, ни одна из рассматриваемых в этом разделе программ не создает файлов регистрации, поэтому если какой-то из них удален, то ведение записей заканчивается.
Команда lastlog форматирует и выводит содержание файла /var/log/lastlog: имя пользователя, имя терминала, время последнего входа в систему. По умолчанию (когда команда введена без параметров) элементы файла /var/log/lastlog будут выводиться в порядке номеров идентификаторов пользователей. Если указать параметр -u login-name, будет выведена только информация о времени последнего входа указанного пользователя. Указав параметр -t days, вы получите только записи за последние days дней. Если пользователь вообще пока не заходил в систему, то вместо имени терминала и времени последнего входа будет указана строка <**Never logged in**>.
Для вывода информации о том, кто работает в текущий момент в системе, используются команды w, who и users. Наибольшую информацию выводит команда w, которая кроме параметров системы выдает подробную информацию для каждого пользователя.
Ротация файлов протокола
Если система интенсивно используется, то файлы протоколов быстро растут, порождая проблему <укрощения> протоколов. В Red Hat это решается скриптом logrotate из каталога /etc/cron.daily ежедневно запускаемого демоном cron. Этот скрипт позволяет обрабатывать не только журналы системы syslog, но и любые другие программы. Скрипт обеспечивает так называемую ротацию этих файлов в случае, если они превысили указанный размер (или по истечению указанного временного интервала). Ротация - последовательное копирование предыдущих версий архивных файлов примерно следующим образом:
messages.1 -> messages.2
messages.0 -> messages.1
messages -> messages.0
и создание нового файла messages для записи последующих сообщений.
Перечень файлов для обработки скриптом logrotate и параметры этой обработки определяются конфигурационными файлами, которых может быть несколько. Имена конфигурационных файлов задаются в командной строке запуска скрипта. В Red Hat Linux по умолчанию в качестве конфигурационных файлов для logrotate используется файл /etc/logrotate.conf, который может иметь примерно такой вид:
weekly
rotate 4
create
compress
include /etc/logrotate.d
/var/log/wtmp /var/log/lastlog {
monthly
create 0664 root utmp
rotate 1
}
Этот файл, как и любой конфигурационный файл для скрипта logrotate, состоит из нескольких секций. Первая секция определяет глобальные параметры (по одному на строке), задающие параметры по умолчанию для всех журналов. Следующие секции определяют локальные параметры для серии файлов протоколов. Имена этих файлов перечисляются в первой строке секции, а затем в фигурных скобках задаются локальные параметры, действующие только при обработке указанных файлов (тоже по одному параметру в строке). Локальные параметры имеют приоритет над глобальными.
В приведенном примере конфигурационного файла сначала описываются глобальные параметры, а затем в отдельной секции - параметры обработки файлов /var/log/wtmp и /var/log/lastlog. Кроме того, среди глобальных параметров дается ссылка на каталог /etc/logrotate.d куда каждый пакет записывает локальные параметры для своих журналов. В секции глобальных параметров в первую очередь задается один из следующих параметров, определяющих критерий ротации файлов: daily - смена ежедневно, weekly - еженедельно, monthly - ежемесячно, size байт - смена версии происходит, если размер журнала превысил указанное число байт. Параметр rotate число может находиться как среди глобальных, так и среди локальных параметров и определяет, сколько старых версий надо хранить; если число равно 0, то архивные версии протокола не создаются.
Среди ключевых слов, встречающихся в конфигурационных файлах, надо особо отметить слова postrotate и prerotate, которые служат открывающими скобками для включения в конфигурационные файлы скриптов оболочки shell. Все строки конфигурационного файла от строки postrotate до строки endscript исполняются как команды shell после процесса смены версии файла протокола. Соответственно, все строки от строки prerotate до строки endscript исполняются до выполнения ротации файлов протокола. С помощью этих скриптов можно организовать различные процедуры обработки файлов протоколов в процессе ротации.
С помощью других параметров конфигурационного файла можно переопределить права доступа к файлам протоколов; задать опции сжатия архивных файлов; указать, кому посылать сообщения об ошибках функционирования системы протоколирования; послать архивную копию журнала указанному пользователю; задать каталог, в который будут перемещаться протоколы во время смены версий (каталог должен находиться на том же физическом устройстве, что и /var/log) или задать список суффиксов-исключений для директории include, но об этом вы должны будете узнать из man logrotate.
Виктор Костромин (kos@linux-ve.net) -независимый эксперт (Казань)
Полезные ссылки
Е. Горный, <Сага о Митнике>, http://www.zhurnal.ru/hack-zone/mitnick1.htm.
С. Богомолов, , http://www.bog.pp.ru/work/syslog.html.
<Логи в Linux>, http://www.infocity.kiev.ua/os/content/os195.phtml?id=2165
<Демон следит за системой>, http://www.softerra.ru/freeos/15618/.
Д. Колисниченко, <Протоколирование>, http://www.softerra.ru/freeos/17032.