Фильтры Rsyslog на службе OSSIM

Казалось бы, подключение источников, передающих журналы событий по протоколу Syslog и поддержка которых была объявлена производителем системы «из коробки» должна происходить что называется «в пару кликов». Вроде включил плагин соответствующего источника через веб-интерфейс или через консоль и все должно «завестись». Логично?

Да, но не всегда… Дело в том, что напрямую принимать syslog поток ни OSSIM ни USM не могут. Плагины OSSIM читают текстовые файлы, которые в свою очередь пишет для них rsyslog, работающий в составе системы. Rsyslog же должен быть настроен таким образом, чтобы перенаправлять весь поток получаемых по протоколу syslog данных в разные файлы в зависимости от типа источника, присылающего данные. Как же rsyslog понимает какие данные из потока принадлежат какому источнику? По ряду признаков. Это и адрес отправителя, и особые значения в полях syslog сообщения, например имя процесса, или какое-то кодовое слово, ну и, конечно же, значения facility и severity с которыми приходит сообщение. Фильтры, настраиваемые в конфигурации rsyslog, позволяют перенаправлять поток syslog в разные файлы в зависимости от значений перечисленных выше полей сообщения.

Для наглядности, схема обработки syslog приведена на рисунке ниже.

Рисунок 1 -Syslog фильтрация

Дальше кратко рассмотрим состав syslog сообщения из спецификаций RFC 3164 и 5424. Это нужно для того, чтобы лучше понять принцип фильтрации, используемый в rsyslog, т.к. он (rsyslog) для фильтрации использует части сообщения syslog, описанные в вышеупомянутых RFC.

1. В двух словах о формате сообщения syslog из RFC 3164

Согласно RFC 3164, сообщение syslog состоит из трех основных частей – PRI, HEADER и MESSAGE.

PRI – представляет собой значение syslog facility и syslog severity в численном представлении, заключенное в скобки <>. PRI вы не увидите в файлах, которые пишет, например, rsyslog на файловую систему, однако сможете увидеть, перехватив пакет syslog, передаваемый по сети.

Код       Значение Facility

0             kernel messages

1             user-level messages

2             mail system

3             system daemons

4             security/authorization messages (note 1)

5             messages generated internally by syslogd

6             line printer subsystem

7             network news subsystem

8             UUCP subsystem

9             clock daemon (note 2)

10             security/authorization messages (note 1)

11             FTP daemon

12             NTP subsystem

13             log audit (note 1)

14             log alert (note 1)

15             clock daemon (note 2)

16             local use 0  (local0)

17             local use 1  (local1)

18             local use 2  (local2)

19             local use 3  (local3)

20             local use 4  (local4)

21             local use 5  (local5)

22             local use 6  (local6)

23             local use 7  (local7)

Код         Значение Severity

0       Emergency: system is unusable

1       Alert: action must be taken immediately

2       Critical: critical conditions

3       Error: error conditions

4       Warning: warning conditions

5       Notice: normal but significant condition

6       Informational: informational messages

7       Debug: debug-level messages

HEADER = TIMESTAMP + HOSTNAME разделенные ОДНИМ пробелом.

TIMESTAMP – метка времени в формате «Mmm dd   hh:mm:ss»

HOSTNANE – имя хоста (такое, под которым себя знает сам отправивший сообщение по syslog хост), или IP адрес, в случае отсутствия имени хоста.

MESSAGE – вся остальная часть сообщения. Поле MESSAGE состоит из двух частей — TAG и CONTENT.

В поле TAG содержится имя программы или процесса, сгенерировавшего сообщение. Данное поле состоит представляет собой комбинацию букв и цифр. Пробел или любой спецсимвол сигнализирует о начале поля CONTENT. В поле CONTENT содержится информационное сообщение.

Пример выделения частей из syslog сообщения приведен на риснке ниже.

Рисунок 2 — Syslog сообщение по RFC 3164

2. Кратко о формате сообщения syslog по RFC 5424

RFC 5424 является развитием стандартного BSD syslog, описанного в RFC 3164. Некоторыми из отличий от предшественника является, например, увеличенный размер самого сообщения и новые поля, выделяемые в syslog сообщении. О них и поговорим дальше.

В добавок к описанным в RFC 3164 полям PRI, TIMESTAMP, HOSTNAME rsyslog умеет работать с полями VERSION, STRUCTURED-DATA, APP-NAME, PROCID, MSGID, описанными в RFC5424.

VERSION – определяет версию протокола syslog, представляет собой число и следует сразу за PRI.

STRUCTURED-DATA – представляет собой структурированные данные в формате [<тип данных> <параметр 1>=”<значение 1>”….<параметр N>=”<значение N>”]. Поле может включать в себя несколько конструкций []. Все допустимые «типы данных» регулируются IANA и описаны в RFC 5424.

APP-NAME – название приложения, сгенерировавшего сообщение.

PROCID – идентификатор процесса.

MSGID – идентификатор сообщения.

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

Рисунок 3 — Syslog сообщение по RFC 5424

3. Фильтрация сообщений с помощью Rsyslog

Как уже говорил раньше, rsyslog для фильтрации сообщений использует значения полей, выделяемые из исходных сообщений. Выделение полей rsyslog выполняет в соответствие с RFC, но вот названия полей rsyslog использует несколько измененные. Соответствие полей из RFC 3164 и RFC 5424 значениям, используемым при фильтрации rsyslog приведено в таблице ниже.

RFC 3164 RFC 5424 Rsyslog Комментарий
APP-NAME app-name
fromhost Имя хоста, от которого было получено сообщение.
fromhost-ip IP адрес хоста, от которого было получено сообщение.
HOSTNAME hostname
inputname Имя модуля, сгенерировавшего событие
jsonmesg поле msg, представленное в флрмате json строки (начиная с версии 8.3.0)
MESSAGE msg
MSGID msg-id
PRI pri
pri-text тоже самое, что PRI, но в текстовом виде, например local0.err
PROCID procid
часть TAG до символа “[“ programname
VERSION protocol-version
PRI+HEADER+MESSAGE rawmsg
HEADER+MESSAGE rawmsg-after-pri
HOSTNAME source
STRUCTURED-DATA structured-data
syslogfacility значение facility в численном виде
syslogfacility-text значение facility в текстовом виде
syslogpriority = syslogseverity
syslogpriority-text = syslogseverity-text
syslogseverity значение severity в численном виде
syslogseverity-text значение severity в текстовом виде
TAG syslogtag см. комментарии ниже таблицы
timegenerated Метка времени когда сообщение было получено
TIMESTAMP timereported Метка времени из самого сообщения
TIMESTAMP timestamp = timereported

4.Пояснения и комментарии

fromhost — Имя хоста, от которого было получено сообщение. Может отличаться от hostname в случае, если оригинальное сообщение пересылалось через syslog relay. Тогда в fromhost будет имя хоста последнего syslog relay, а в hostname – имя хоста, фактически сгенерировавшего событие. Справедливо для тех случаев, когда syslog relay не перезаписывает HOSTNAME в оригинальном сообщении.

В отношении полей TAG по RFC 3164 и syslogtag как его понимает rsyslog необхлжимо уточнить следующее. По RFC 3164 поле TAG заканчивается символом “[” или пробелом. Согласно документации rsyslog поле syslogtag = TAG. Однако, опытным путем доказано (проверено на стенде), что в rsyslog в поле syslogtag помещает <имя процесса>[<идентиыикатор_процесса>], т.е. для сообщения:

<191> Dec 12 12:00:05 server.com process[1234] ….

  • Поле TAG по RFC 3164 будет – «process»
  • Поле rsyslogtag по rsyslog будет «process[1234]»
  • Поле programname по rsyslog будет «process»

5.Настройка фильтров

Все фильтры должны размещаться в фале rsyslog.conf или в файлах *.conf внутри папки rsyslog.d.

Rsyslog допускает написание фильтров в двух форматах «Property-Based» и «Script-Based».

Property-based фильтры имеют вид:

:<переменная>, <оператор сравнения>, “<значение>” <назначение>

Например:

:programname, isequal, “sendmail” /var/log/mail.log

Означает, что все события, в которых в поле programname находится значение «sndmail» отправлять в файл «/var/log/maillog»

:msg, startswith, “pam_unix” /var/log/auth.log

Означает, что все события, поле msg в которых начинается с «pam_unix» отправлять в файл «/var/log/auth.log»

Внимание. Property-based фильтры НЕ РАБОТАЮТ в версии Rsyslog 8.24.0 и, скорее всего, в более новых.

Возможность использовать более простую, но и менее гибкую конструкцию, фильтрующую только по значениям PRI, осталась. Например:

local0.*    /var/log/boot.log

Т.е. события всех уровней из facility local0 отправлять в /var/log/boot.log.

*.info     /var/log/messages

Все события уровня info и выше отправлять в /var/log/messages

Script-based фильтры основаны на Rainer-script и имеют следующий формат:

IF <условие> THEN <действие> [ELSE <действие>]

<действие> может в себя также включать вложенные «IF» условия, например, так:

IF <условие> THEN <действие>

ELSE IF <условие> THEN <действие>

ELSE <действие>

Условие может быть единичным, а также целым списком условийб если выхотите очень точно ограничить объем собираемых событий. Условия в списке могут объединяться операторами OR, AND, NOT. Например, вот так:

if $syslogtag contains 'super_program' and not ($msg contains 'some text' or $msg contains 'some_text_2')

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

<действие> может быть как единичным, например, отправить событие по сети или в файл, так и списком действий или даже дополниетельных вложенных конструкций IF-THEN-ELSE.

Пример перечня действий:

{ action(type="omfwd" Target="10.10.10.10" Port="514" Protocol="udp" Device="eth0" template="OnlyMsg") and action(type="omfile" file="/var/log/temp.log" template="OnlyMsg") stop}

В данном случае выполняется целых 3 действия: отправка по сети на 10.10.10.10, отправка в файл /var/log/temp.log и наконец «stop» — что говорит о том, что данное сообщение далее не обрабатывается. Сделано это для того, чтобы данное сообщение не попадало в «catch all» логи типа /var/log/messages.

Целиком конструкция выглядит так:

if $msg contains 'codeword' then { action(type="omfwd" Target="10.10.10.10" Port="514" Protocol="udp" Device="eth0" template="OnlyMsg") and action(type="omfile" file="/var/log/temp.log" template="OnlyMsg") stop}

Обратите внимание на параметр  template=»OnlyMsg». Это шаблон согласно которому будет отформатировано сообщение перед отправкой. Очень полезная штука, например, если вы хотите вырезать «мусор» из сообщения или просто удалить заголовки syslog, проставленные при передаче сообщения от одного syslog сервера другому.

Пример описания template может быть включен в конфигурационный файл прямо перед конструкцией IF-THEN-ELSE в которой он используется и выглядеть может примерно так:

template(name=»OnlyMsg» type=»string» string=»%msg:::drop-last-lf%\n»)

6.Rsyslog и плагины OSSIM

Итак, как же нам помогут фильтры rsyslog при работе с OSSIM?

А вот как. В каждом конфигурационном файле плагина (/etc/ossim/agent/plugins/*) есть параметр location, который указывает на лог-файл, который будет читать данный плагин.

Таким образом, например, плагин для разбора логов от  LDAP будет искать логи в файле /var/log/openldap/slapd.log.

А rsyslog мы будем использовать как раз для того, чтобы перенаправить поток событий от LDAP, приходящих на IP адрес OSSIM на 514 порт в нужный файл — /var/log/openldap/slapd.log. Тоже самое справедливо и для других источников.

Конфигурацию rsyslog для решения данной задачи для удобства мы запишем в отделный файл, скажем “slapd.conf”, который поместим в папку “/etc/rsyslog.d”

Вот содержимое slapd.conf:

if  $programname contains 'slapd' then -/var/log/openldap/slapd.log

& ~

Строка & ~ сообщает rsyslog, что обработки данных логов после помещения в файл /var/log/openldap/slapd.log прекращается. Если эту строчку не написать, то логи могут попасть кроме нужного нам файла еще и в «catchall» лог файлы, например, в /var/log/syslog или /var/log/messages.

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