Пришла задача организовать сбор логов на почтовом сервере Postfix, который развёрнут на Ubuntu Server. Заказчика интересуют логи отправки писем в виде JSON. Он хочет, чтобы почтовый сервер на каждую отправку письма отчитывался — передавал по curl данные из лога. Поможет нам в этом непростом деле NXLog.
NXLog — это высокопроизводительное многоплатформенное решение для управления логами.https://nxlog.co
Решение существует как в бесплатном исполнении Community Edition, так и в платном — Enterprise Edition. Сравнение редакций:
https://nxlog.co/community-edition-vs-enterprise-edition
Бесплатная редакция полностью удовлетворяет всем требованиям нашей задачи:
- получение данных из файла и отправка в файл: модуль Files (im_file, om_file)
- преобразование данных в JSON: модуль JSON (xm_json)
- получение и отправка данных по HTTP: модуль HTTP (im_http, om_http)
Функции NXLog
- Непрерывный сбор событий операционной системы, брандмауэров, коммутаторов, маршрутизаторов, модемов, бизнес-систем и пр.
- Настраиваемая пересылка событий на другие Syslog сервера.
- Удаление, фильтрация выбранных или ненужных событий.
- Поиск, сортировка и настраиваемый фильтр событий.
Установка NXLog
У нас почтовый сервер Postfix работает на ОС Ubuntu 16.04.
Мануал по установке на Debian нам подойдёт:
https://docs.nxlog.co/userguide/deploy/debian.html
В списке можно найти нужную для нашей ОС версию дистрибутива. Однако, нам она не очень интересна, потому что не Community Edition.
Переходим на страничку загрузки пакетов для CE:
https://nxlog.co/downloads/nxlog-ce#nxlog-community-edition
Выбираем пакет для нашей операционной системы и скачиваем.
No thanks, just start my download.
Загружаем пакет на сервер и пробуем установить:
dpkg -i nxlog-ce_3.1.2319_ubuntu16_amd64.deb
И у нас ничего не устанавливается!
Есть проблемы зависимостей. Удаляем пакет:
apt-get remove nxlog-ce
Смотрим в документацию и видим волшебную надпись:
If dpkg returned errors about uninstalled dependencies, use apt-get to install them and complete the NXLog installation.
Ну ладно, ставим зависимости:
apt-get install libapr1
apt-get -f install
Повторно устанавливаем пакет NXLog:
dpkg -i nxlog-ce_3.1.2319_ubuntu16_amd64.deb
И у нас всё устанавливается!
Автоматически запускается служба nxlog. Конфигурационный файл находится по адресу:
/etc/nxlog/nxlog.conf
И там сейчас находится пример конфигурации.
Данный пример нам не нужен, стираем всё, будем настраивать обработку логов Postfix.
Отправка логов Postfix в файл
Для начала просто убедимся в том, что nxlog работает. Для этого организуем запись логов в файл: /var/log/smtp.log. А данные будем брать из логов Postfix: /var/log/mail.log.
- Мы будем преобразовывать данные в формат JSON, в конфиге будет модуль xm_json.
- Для получения данных из файла /var/log/mail.log используем модуль im_file.
- Для записи данных в файл /var/log/smtp.log используем модуль om_file.
Получаем:
User nxlog
Group nxlog
include /etc/nxlog/nxlog.d/*.conf
LogFile /var/log/nxlog/nxlog.log
LogLevel INFO
<Extension _json>
Module xm_json
</Extension>
<Input postfix>
Module im_file
File "/var/log/mail.log" <Exec>
if $raw_event =~ /(?x)^(\S+\ +\d+\ \d+:\d+:\d+)\ (\S+)
\ postfix\/(\S+)\[(\d+)\]:\ (.+)$/
{
$EventTime = parsedate($1);
$HostName = $2;
$SourceName = "postfix";
$Component = $3;
$ProcessID = $4;
$Message = $5;
if $Component == "smtpd" and
$Message =~ /(\w+): client=(\S+)\[([\d.]+)\]/
{
$QueueID = $1;
$ClientHostname = $2;
$ClientIP = $3;
}
if $Component == "cleanup" and
$Message =~ /(\w+): message-id=(<\S+@\S+>)/
{
$QueueID = $1;
$MessageID = $2;
}
if $Component == "qmgr" and
$Message =~/(\w+): from=(<\S+@\S+>), size=(\d+), nrcpt=(\w+)/
{
$QueueID = $1;
$Sender = $2;
$Size = $3;
$Nrcpt = $4;
}
if $Component == "smtp" and
$Message =~ /(?x)(\w+):\ to=(<\S+@\S+>),\ relay=([\w.]+)\[([\d.]+)\],
\ delay=(\d+),\ status=(\w+)\ \((\d+)\ \w+:\ queued\ as
\ (\w+)\)/
{
$QueueID = $1;
$Recipient = $2;
$RelayHostname = $3;
$RelayIP = $4;
$Delay = $5;
$Status = $6;
$SMTPCode = $7;
$QueueIDDelivered = $8;
}
}
</Exec>
</Input>
<Output out>
Module om_file
File "/var/log/smtp.log" <Exec>
if $Component != "smtp" drop();
to_json();
</Exec>
</Output>
<Route postfix>
Path postfix => out
</Route>
Перезапускаем службу и смотрим что у нас в логе NXLog.
service nxlog restart
LogFile /var/log/nxlog/nxlog.log
А у нас не хватает прав на чтение файла /var/log/mail.log. Дадим права. Я пока тестирую, делаю совсем просто, добавляю пользователя nxlog в группу администраторов:
usermod -a -G amd nxlog
Перезапускаем службу и смотрим что у нас в логе NXLog.
service nxlog restart
Нет доступа к файлу /var/log/smtp.log. Да у нас просто нет такого файла, создадим.
cd /var/log
touch smtp.log
chown nxlog\: ./smtp.log
Перезапускаем службу.
service nxlog restart
И у нас всё заработало.
Логи Postfix считываются из файла /var/log/mail.log, преобразуются в JSON и записываются в файл /var/log/smtp.log.
Отправка логов Postfix по HTTP
Модифицируем конфигурацию для отправки логов по HTTP на адрес:
http://test.example.local/api/v1/stats/email
User nxlog
Group nxlog
include /etc/nxlog/nxlog.d/*.conf
LogFile /var/log/nxlog/nxlog.log
LogLevel INFO
<Extension _json>
Module xm_json
</Extension>
<Input postfix>
Module im_file
File "/var/log/mail.log" <Exec>
if $raw_event =~ /(?x)^(\S+\ +\d+\ \d+:\d+:\d+)\ (\S+)
\ postfix\/(\S+)\[(\d+)\]:\ (.+)$/
{
$EventTime = parsedate($1);
$HostName = $2;
$SourceName = "postfix";
$Component = $3;
$ProcessID = $4;
$Message = $5;
if $Component == "smtpd" and
$Message =~ /(\w+): client=(\S+)\[([\d.]+)\]/
{
$QueueID = $1;
$ClientHostname = $2;
$ClientIP = $3;
}
if $Component == "cleanup" and
$Message =~ /(\w+): message-id=(<\S+@\S+>)/
{
$QueueID = $1;
$MessageID = $2;
}
if $Component == "qmgr" and
$Message =~/(\w+): from=(<\S+@\S+>), size=(\d+), nrcpt=(\w+)/
{
$QueueID = $1;
$Sender = $2;
$Size = $3;
$Nrcpt = $4;
}
if $Component == "smtp" and
$Message =~ /(?x)(\w+):\ to=(<\S+@\S+>),\ relay=([\w.]+)\[([\d.]+)\],
\ delay=(\d+),\ status=(\w+)\ \((\d+)\ \w+:\ queued\ as
\ (\w+)\)/
{
$QueueID = $1;
$Recipient = $2;
$RelayHostname = $3;
$RelayIP = $4;
$Delay = $5;
$Status = $6;
$SMTPCode = $7;
$QueueIDDelivered = $8;
}
}
</Exec>
</Input>
<Output http>
Module om_http
URL http://test.example.local/api/v1/stats/email
ContentType text/plain
<Exec>
if $Component != "smtp" drop();
to_json();
</Exec>
</Output>
<Route postfix>
Path postfix => http
</Route>
Источник:
Если вам понравилась статья, то ставьте 👍🏻 каналу.
Пишите комментарии, задавайте вопросы, подписывайтесь.