无法过滤 syslog-ng 中格式错误的消息

无法过滤 syslog-ng 中格式错误的消息

我联系您是因为我在使用 syslog-NG 时遇到的一个问题。我们的某些设备(主要是 HP 交换机和 SAN)发送的系统日志消息似乎不符合 syslog RFC 5424。

举几个例子:

如果我嗅探服务器的网络接口,我们可以看到类似的这些“错误”消息(正如您所看到的,在 PRI 之后,我们可以看到 PROGRAM,然后是时区和用逗号分隔的字段。简而言之,混合字段、缺少字段等,不是标准的系统日志消息):

<190>raslogd: 2017/03/08-16:03:20, [SEC-1203], 53642, WWN 10:00:50:eb:1a:6c:21:38 | FID 128, INFO, cswc-mo8x-SAN01, Login information: Login successful via TELNET/SSH/RSH. IP Addr: 1.2.3.4

因此,我目前无法过滤这些消息。我尝试定义一个常规过滤器并尝试打印 MSGHDR、MSG、PRI 等字段。但什么也看不到。

过滤此消息的唯一方法是定义外部接口和文件作为输出,而无需任何模板。

例如如果我做一个这样的过滤器:

destination d_INCOMING_ALL   { file("/app/syslog-ng/logs/incoming_all.log"); };

log {
  source(s_EXTERNAL);
  destination(d_INCOMING_ALL);
};

我可以在日志文件中看到消息,但是它们被格式化了(我猜 syslog-NG 重新格式化了它们):

[root@xxxxxxxxxxxx logs]# grep -i cswc incoming_all.log
Mar  9 09:44:20 cswc-mo8x-hpsan01 raslogd: 2017/03/09-08:34:50, [SEC-1203], 53647, WWN 10:00:50:eb:1a:6c:21:38 | FID 128, INFO, cswc-mo8x-SAN01, Login information: Login successful via TELNET/SSH/RSH. IP Addr: 1.2.3.4
[root@xm1p1034vmo logs]#

问题是我无法像那样过滤这些消息(我们收到来自 1000 多个设备的日志),我需要过滤来自这些设备的消息!而我唯一能做到的方法是使用主机名(cswc-)或程序名称(raslogd

因此我尝试通过向该文件添加模板来显示字段,例如:

destination d_test { 
    file ("/app/syslog-ng/logs/test_olivier.log" 
    template("pri=${priority} date=${ISODATE} host=${HOST} program=${PROGRAM} message=${MSG}\n") 
    ); 
};

但什么都没起作用,什么都没显示。我试过所有字段,MSG、MESSAGE、MSGHDR 等。无法显示任何内容。唯一有效的是没有过滤器或模板的解析。

当然,如果我尝试所有类型的过滤器,如下所示,它不起作用(因为字段混合):

filter f_is_SAN     {
    host("cswc.*" flags(ignore-case));
};

相同:

filter f_is_SAN     {
    match(".*cswc.*" flags(ignore-case));
};

关于如何为来自这些设备(在主机名或程序名上)的消息创建过滤器的任何提示?

感谢和问候,

答案1

实际上,syslog-ng 并没有重新格式化它们,而是添加了一个适当的 syslog 标头:

3 月 9 日 09:44:20 cswc-mo8x-hpsan01 raslogd:2017/03/09-08:34:50,[SEC-1203],53647,WWN 10:00:50:eb:1a:6c:21:38 | FID 128,INFO,cswc-mo8x-SAN01,登录信息:通过 TELNET/SSH/RSH 登录成功。IP 地址:1.2.3.4

以下内容由 syslog 添加:

3 月 9 日 09:44:20 cswc-mo8x-hpsan01

其余内容为原始消息:

raslogd:2017/03/09-08:34:50,[SEC-1203],53647,WWN 10:00:50:eb:1a:6c:21:38 | FID 128,INFO,cswc-mo8x-SAN01,登录信息:通过 TELNET/SSH/RSH 登录成功。IP 地址:1.2.3.4

因此 syslog-ng 同意您的说法,这些消息不符合 RFC 标准。

在设置过滤器方面,这意味着您没有太多可玩的东西。

我个人更习惯于 rsyslog(您可以在其中使用正则表达式检查消息,例如查找raslogd- 尽管这不一定有效)。

但是,syslog-ng 能够添加的标头可以让你继续进行以下几件事:

  • syslog-ng 似乎能够报告主机名,我倾向于假设主机名是从源 IP 解析的。因此,您至少可以使用以下任一方法过滤源 IP:主持人或者网络掩码

    filter hp_hosts { (host(192.168.0.25)) };

  • 您当前的主机过滤器失败,因为消息中没有 HOST 字段 -host过滤器状态的文档:

    也就是说,syslog-ng OSE 会将过滤表达式与 ${HOST} 宏的内容进行比较。

  • 但是,您在消息中有一个主机名(至少在您的示例中),因此您可以考虑使用信息筛选。

话虽如此 - 对我来说,如果有可能获得所有这些设备的源 IP 列表(并且我只能希望为了您的利益这是可能的),那么我会使用网络掩码过滤器 - 它似乎比其他选项更有效。

答案2

嗯,我找到了一个似乎有效的解决方案

我正在重新使用“本地副本”目标作为源

例如:

我有一个常规日志过滤器,保存所有内容的副本:

destination d_INCOMING_ALL       { file("/app/syslog-ng/logs/incoming_all.log"); };
log {
  source(s_EXTERNAL);
  destination(d_INCOMING_ALL); 
};

消息保存在被重新格式化的“本地副本”中。然后我可以从源中重新读取此文件并对其应用过滤器。这很脏,但它有效:

source s_NON_RFC_COMPLIANT {   # new source
    file("/app/syslog-ng/logs/incoming_all.log" follow-freq(10));
};

....

destination d_INCOMING_ALL {
    file("/app/syslog-ng/logs/incoming_all.log");    # old destination where we keep a local copy of EVERYTHING
};

....

log {      # local copy of everything
  source(s_EXTERNAL);
  destination(d_INCOMING_ALL);
};

....

other filters here

....

filter f_is_Network     {
  host("cswc.*" flags(ignore-case))       # we want to filter on hosts called cswc-something or program raslogd
  or program("raslogd" flags(ignore-case));
};

log {    # new source for HP stuff here
  source(s_NON_RFC_COMPLIANT);
  filter(f_is_Network);              # add the filters you need
  destination(<your_final_destination_here>);
  flags(final);
};

相关内容