我联系您是因为我在使用 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);
};