创建集中式 Syslog 服务器
集中式 syslog 服务器是我在 1997 年作为 Linux 管理员接到的首批真正的系统管理任务之一。当时我的老板希望从各种设备中提取日志文件,并让我使用正则表达式搜索其中的某些关键字。那时 Linux 仍处于起步阶段,而我只是在业余时间涉足它。因此,我抓住机会向我当时工作的公司介绍 Linux。它成功了吗?当然成功了!这篇文章将要介绍的不仅是如何设置集中式 syslog-ng 服务器,而且还包括为什么要首先设置一个。
那么什么是 syslog 呢?Syslog 在 Linux 中用于记录系统消息(嗯,又是一个容易猜到的名字)。Syslog-ng 只是对最初的 syslog 的重写,最初的 syslog 开发于 1998 年。Syslog-ng 仍在由 BalaBit IT Security 积极开发(截至 2010 年),并附带了更多功能,包括更好的 TCP 处理、消息的 TLS 加密以及将消息发送到数据库等。某些发行版允许您安装 syslog、rsyslog 或 syslog-ng。在本文中,我将重点介绍 syslog-ng,因为它更先进,而且如果读者愿意,可以通过购买其企业版在以后获得拥有 syslog-ng 软件的公司的“支持”。
现在您已经对 syslog-ng 有了一个概览,让我们来谈谈为什么要使用集中式 syslog-ng 服务器。我相信原因不止我将要提出的两个,但我至少可以想到最直接的两个。第一个是出于安全目的。如果您让您的路由器、防火墙、交换机、Linux 服务器和/或其他硬件指向一台安全的集中式 syslog-ng 服务器,那么当有人尝试攻击上述设备之一时,日志文件可以安全地异地保存在安全的位置。如果 syslog 文件保存在设备上,这会让攻击者能够清除他们的踪迹。诚然,他们可以禁用将日志文件发送到外部 syslog-ng 服务器的功能,但是在此之前的所有连接都将位于集中式 syslog 服务器上。另一个原因是方便。例如,如果您的服务器崩溃且无响应,您可以检查集中式 syslog 服务器上的内核错误日志。如果您想检查一段时间内不同日期之间的 syslog 模式,可以使用正则表达式搜索集中式 syslog 服务器的日志文件。
那么我是怎么做的呢?实际上我在家两种方法都用。我的设备和服务器不仅将其所有 syslog 文件转发到一个集中的位置,而且该位置是锁定的。有问题的机器是一台虚拟机,只打开了 1 个端口(syslog),并且只能从本地机器访问,syslog 文件保存在外部驱动器上。这是偏执吗?可能有点。但我确实知道,在我的家庭环境中,如果我的外部驱动器因 syslog 文件过多而填满,它不会使我的虚拟机崩溃。如果我的虚拟机发生任何问题,我的主机操作系统都不会受到影响,如果有人确实获得了对我其中一台设备的访问权限,那么他们也无法获得对我 syslog 服务器的访问权限。诚然,如果我的主机操作系统发生任何问题,那么我的访客虚拟机也会出现问题,但是我们不可能总是为一切做好准备。好吧,我承认这是最高级别的偏执,对于大多数人来说,这可能太过分了。
在我们开始之前,这里有一个快速免责声明。首先,与我之前的所有帖子一样,我所有的博文测试都在 Debian 中完成。在本例中,我设置了一个用于 Debian 6.0.1 的虚拟机,因此您的结果可能会有所不同。此外,我不会深入探讨如何正确保护您的服务器、syslog 文件的最佳放置位置,或者如何设置除 syslog-ng 之外的任何内容。我将这些留给读者。这篇博文只涵盖集中式 syslog-ng 服务器的基础知识。
安装和配置 - 服务器端安装 syslog-ng 并不像看起来那么难,特别是如果您是从软件包安装的话。对于 Debian:apt-get install syslog-ng,对于 Redhat:yum install syslog-ng。对于那些喜欢源码安装的人:http://www.balabit.com/downloads/files?path=/syslog-ng/sources/3.2.4/source/syslog-ng_3.2.4.tar.gz 下载,解包,配置,make & make install。一旦您安装了 syslog-ng,我们就可以开始配置服务器端了。
全局选项
您需要做的第一件事是找到您的 syslog-ng 配置文件。默认安装(对于 Debian 变体)是“/etc/syslog-ng/syslog-ng.conf”。在编辑任何配置文件之前,最佳实践是在进行任何更改之前制作原始配置文件的副本。这只是为了以防万一发生某些事情,您需要返回到原始配置文件。我倾向于用 .orig 标记我的原始配置文件(在本例中:syslog-ng.conf.orig)。现在您已经制作了配置文件的副本,让我们用您选择的编辑器打开它并开始吧。
long_hostnames(默认值:off)- 对于这篇文章,我使用的是 syslong-ng OSE 版本 3.1,实际上我在在线的全局配置指南中找不到 long_hostnames。我将使用长主机名作为默认值 off,即完全限定域名。
flush_lines(默认值:0)- 设置一次刷新到目标的行数。设置为 0 会在收到消息时立即发送消息,但请记住,将此数字设置得更高可能会增加消息延迟。这在 syslog-ng 的客户端非常有用。您可以在客户端保留 xx 条消息,然后再刷新到目标,这样如果您有来自服务器的大量流量,就不会使主 syslog-ng 服务器过载。
use_dns(默认值:no)- 选项:yes、no、persist_only。这取决于您和您的环境。如果您的 syslog-ng 位于防火墙后面,并且无法从外部世界访问,那么“yes”将是合适的。如果可以从外部世界访问,则设置为“no”,以阻止可能的 DoS 攻击。我将我的设置为“persist_only”,它会检查我的 syslog-ng 服务器上的 /etc/hosts 文件以解析主机名,而无需依赖 dns 服务器。
use_fqdn(默认值:no)- 设置完全限定域名,您的选择。作为家庭网络,我只有一个内部域名。所以我的默认值为“no”。设置为“yes”将使您的客户端主机名显示为:“hostA.domain.com”而不是“hostA”
owner(默认值:root)- 输出文件的所有者
group(默认值:adm)- 输出文件的组
perm(默认值:0640)- 输出文件的权限。默认为 640 - 所有者读写,组读,其他无。
stats_freq(默认值:0)- 两次 STATS(关于丢弃的日志消息的统计消息)消息之间的时间(以秒为单位)。0 禁用 STATS 消息。
bad_hostname(默认值:^gconfd$)- 包含不应作为主机名处理的主机名的正则表达式……在本例中为 gconfd。如果您有超过少数几台服务器,那么我建议使用主机名,除非您记得域中的每个 ip 地址……如果您记得,我向您致敬。
现在这就是“默认”全局配置选项的全部内容,但还有更多您可以使用的选项。我还使用以下选项
normalize_hostnames(yes) - 这会将所有主机名转换为小写。我的一些设备有大写主机名,有时我会被一个新的主机冲昏头脑,并将主机名的第一个字母大写。这将只是将所有字符小写,以便于阅读。
keep_hostname(yes) - 如果通过中继或外部服务器运行,则保留主机名,以便当主机最终到达中央服务器时,主机名会随之而来,而不是依赖 DNS(或 /etc/hosts)。如果您正在使用 $HOST 宏,则应启用此选项。
在一个更大更重要的环境(阅读:非 soho)中,我将设置 stats_freq(600) 和 stats_level(2) 以便从服务器检索统计消息。在大多数 soho 环境中,您可能正在从 3-5 个设备收集 syslog 数据,此时实际丢失数据的可能性非常小。在拥有数百台设备向中央 syslog 服务器报告的大型企业环境中,启用统计信息使系统管理员能够检查统计信息和可能丢失的消息。
您的全局配置选项(如果您希望它与我的配置选项相同)将如下所示
options {(off);
flush_lines(0);
use_dns(persist_only);
use_fqdn(no);
owner("root");
group("adm");
perm(0640);
stats_freq(0);
bad_hostname("^gconfd$");
normalize_hostnames(yes);
keep_hostname(yes);
};
设置监听器
设置 syslog-ng 的监听器实际上只需要配置文件中的几行。典型的监听器行如下所示
source s_net { tcp((ip(127.0.0.1) port(1000) max-connections 5000)); udp (); };
source s_net = 网络监听器
tcp(ip(127.0.0.1) = 监听 localhost。如果您有多个 NIC,或者想要指定要绑定到的 ip,请将 127.0.0.1 更改为该特定网卡的 ip 地址
port (1000) = 监听 TCP 端口 1000
max connections = 允许 5000 个并发连接(阻止可怕的“失控服务器”综合征)
udp () = 某些设备通过 udp 发送其 syslog 消息,因此如果您无法指定 tcp 和端口号,请启用 udp。
encrypt(allow) = 这本身可能就是一篇完整的博文。Syslog-ng 允许加密(基于 TLS、证书)的 syslog 消息
例如,我的看起来像这样
# Listen on TCP Port 1000 and UDP Port 514, Max 500 Connections source s_net {
tcp(port(1000) max-connections(500)); udp(););
目标 - 有起必有落。在这种情况下,发送出去的东西必须放在某个地方。一旦从 syslog-ng 服务器收到消息,它就必须去某个地方。因此,syslog-ng.conf 文件的目标部分。正如您所看到的,默认值涵盖了您的 *nix 目标,用于本地计算机上的服务器消息。但是传入消息呢?它们会去哪里?好问题,默认情况下,它们会将 syslog 消息发送到 syslog-ng 中指定的子系统。例如,如果消息被归类为身份验证消息 (/var/log/auth),那么它会将消息转储到 syslog-ng 的 /var/log/auth.log 文件中,并附加信息(主机名、日期/时间等)。
如果这实际上是您想要完成的任务,即让大量服务器转储到与您的主服务器相同的文件中,那么我想任务就完成了。但是 syslog-ng 可以做更多的事情。如果我在服务器端配置方面做得更多,我担心这最终会成为书中的一章。目标可以是平面文件、管道到其他应用程序、SQL 数据库(mysql、MS SQL、Oracle 等)、远程日志服务器和终端窗口。我将专注于平面文件,并假设您现在也是这样做的。
现在我设置集中式 syslog 服务器的方式可能与您设置的方式不同。在我的情况下,我有一个文件夹,其中包含每个主机名,并且来自主机名的 syslog 位于该文件夹中。例如:/mount/syslog/macha、/mount/syslog/beag 等等。Logrotate 负责压缩、删除(旧文件备份到远程服务器以防万一)和清理日志文件。
我的目标指令如下所示
destination d_net_auth {
file("/var/log/syslog/remote/$HOSTNAME/auth.log"); }; destination d_net_cron {
file("/var/log/syslog/remote/$HOSTNAME/cron.log"); }; destination d_net_daemon
{ file("/var/log/syslog/remote/$HOSTNAME/daemon.log"); }; destination
d_net_kern { file("/var/log/syslog/remote/$HOSTNAME/kern.log"); }; destination
d_net_lpr { file("/var/log/syslog/remote/$HOSTNAME/lpr.log"); }; destination
d_net_mail { file("/var/log/syslog/remote/$HOSTNAME/mail.log"); }; destination
d_net_syslog { file("/var/log/syslog/remote/$HOSTNAME/syslog.log"); };
destination d_net_user { file("/var/log/syslog/remote/$HOSTNAME/user.log"); };
destination d_net_user { file("/var/log/syslog/remote/$HOSTNAME/uucp.log"); };
destination d_net_debug { file("/var/log/syslog/remote/$HOSTNAME/debug"); };
destination d_net_error { file("/var/log/syslog/remote/$HOSTNAME/error"); };
destination d_net_messages { file("/var/log/syslog/remote/$HOSTNAME/messages");
}; destination d_net_mailinfo {
file("/var/log/syslog/remote/$HOSTNAME/mail/mail.info"); }; destination
d_net_mailwarn { file("/var/log/syslog/remote/$HOSTNAME/mail/mail.warn"); };
destination d_net_mailerr {
file("/var/log/syslog/remote/$HOSTNAME/mail/mail.err"); };
现在从理论上讲,syslog-ng 服务器应该创建文件要放入的必要目录(如全局策略中所指定的那样),但有时我会遇到目录未正确创建的问题,并且 /var/log/errors 中报告了 syslog-ng 中的错误。为了减轻未来的痛苦和折磨,我倾向于在进行过程中创建主机和日志文件,我遗漏的任何内容都将最终出现在 /var/log/errors 中,我可以稍后创建它们。
对于那些经验丰富的 syslog-ng 用户,您可能想知道为什么我拆分了我的 localhost 目标和我的远程(场外客户端)目标,而理论上我可以创建一个 d_auth 并让我的常规 localhost 过滤到一个文件夹中。这背后的原因是我想将我的 localhost syslog 流量与远程流量分开 - 更多的配置行,但对我来说更容易。此外,当 Linux 子系统查找常规日志文件的放置位置时,我不会干扰它。
过滤 - Syslog-NG 过滤消息的能力真正将 syslog 战斗中的“男人与男孩”区分开来。过滤才是真正让 syslog-ng 与众不同的地方。诚然,我将我的主机分隔在 $HOST 变量中定义的文件夹中,但过滤才是真正的核心内容。通过过滤,我可以(并且确实)执行以下操作:过滤防火墙日志,查找某些关键字,例如端口扫描,这些关键字被转储到一个文件夹中,DDOS 攻击被过滤到另一个文件夹中。我的 voip 适配器发送 syslog 事件,我根据这些消息过滤到单独的文件中,而不是单个文件中。过滤还允许您指定多个主机进行过滤,并指定多个目标。不仅如此,您还可以在过滤中使用正则表达式。
过滤表达式的创建方式如下:filter <identifier> { expression; };
<identifier> 是您为过滤器指定的名称。<expression> 包含函数和布尔运算符(and、or、not)。
我的防火墙的示例将是
filter firewall_ddos_filter { host("10.1.1.1") and match("Denial of Service"
value("MESSAGE")); };
此过滤器称为“firewall_ddos_filter”,它侦听来自 10.1.1.1 的传入 syslog 消息,消息内容为“Denial of Service”。要完成过滤器,您需要一个日志语句
log firewall_ddos_filter { source(s_net); filter(firewall_ddos_filter); destination(d_net_firewall_ddos); };
在上面的目标中,我将为防火墙 DDOS 攻击、端口扫描等添加一个目标。这使得从不使用标准 *nix 日志记录工具的服务器/设备中分离日志文件变得更容易,或者系统管理员更容易过滤来自防火墙(或过滤到一个日志中的多个防火墙)的日志。
如果您想使用多个“防火墙”主机(作为示例),请不要仅仅将它们添加进来并使用“and”的布尔运算符创建一个日志/过滤器规则。它不会工作,并且您会为此撞墙数小时。相反,请使用“or”布尔运算符,如下所示
filter firewall_ddos_filter { host("10.1.1.1") or host ("10.1.1.2") and match("Denial of Service" value("MESSAGE")((; };
我的“默认”过滤指令如下所示(为了这篇文章而美化,但只要每个案例之间用分号分隔,它们就可以以“段落”形式排列)
filter f_dbg { level(debug); };
filter f_info { level(info); };
filter f_notice{ level(notice); };
filter f_warn { level(warn); };
filter f_err { level(err); };
filter f_crit { level(crit .. emerg); };
filter f_debug { level(debug) and not facility(auth, authpriv, news, mail); };
filter f_error { level(err .. emerg) ; };
filter f_messages { level(info,notice,warn) and not facility(auth,authpriv,cron,daemon,mail,news);
};
filter f_auth { facility(auth, authpriv) and not filter(f_debug); };
filter f_cron { facility(cron) and not filter(f_debug); };
filter f_daemon { facility(daemon) and not filter(f_debug); };
filter f_kern { facility(kern) and not filter(f_debug); };
filter f_lpr { facility(lpr) and not filter(f_debug);};
filter f_local { facility(local0, local1, local3, local4, local5, local6, local7) and not filter(f_debug); };
filter f_mail { facility(mail) and not filter(f_debug); };
filter f_news { facility(news) and not filter(f_debug); };
filter f_syslog3 { not facility(auth, authpriv, mail) and not filter(f_debug); };
filter f_user { facility(user) and not filter(f_debug); }; filter f_uucp { facility(uucp) and not filter(f_debug); };
filter f_cnews { level(notice, err, crit) and facility(news); };
filter f_cother { level(debug, info, notice, warn) or facility(daemon, mail); };
filter f_ppp { facility(local2) and not filter(f_debug); };
filter f_console { level(warn .. emerg); };
统计
没有什么比一些好的统计数据更让我喜欢的了。当我运行任何服务器或服务时,无论是在家里还是在工作中,我都想看看我的服务器在一段时间内处理了什么。从 3.1 版本开始,syslog-ng 现在有一个 syslog-ng-ctl stats 实用程序,它大大简化了抓取日志文件。在 3.1 之前,要获取统计文件,您需要运行:echo STATS | nc -U /var/run/syslog-ng.ctl。
因为我是一个正则表达式极客,所以我对 syslog-ng-ctl stats 输出中的分号不满意,因此我运行:syslog-ng-ctl stats | sed 's|;|\t|g' 来清理输出。
当您键入上述命令时,您将得到 6 列:SourceName、SourceID、SourceInstance、State、Type 和 Number。
SourceName - 源的名称,例如:destination、source、global、center
SourceID - 您给源指定的 ID(之前的示例是 firewall_ddos_filter,其他示例将是:d_mail、d_net_user 等)
SourceInstance - 源实例的目标,例如文件名,或程序源(sql)或目标的应用程序名称
State: - 对象的状态:a (Active - 当前活动且正在接收数据)、d (Dynamic - 非持续可用) o (Once active but stopped receiving messages such as an orphaned object - 曾经活动但已停止接收消息,例如孤立对象)
Type - 统计信息的类型,例如:Processed: 已到达其目的地的消息数 Dropped: 丢弃的消息数 Stored: 存储在消息队列中等待发送到目的地的消息数 Suppressed (not sent): 抑制(未发送)的消息数 Stamp: 上次发送消息的时间戳。当 syslog-ng 服务重置时,这些统计信息将被重置。
Number: 消息数
日志轮换,日志轮换,日志轮换
这个信息对您来说够清楚了吗?轮换您的消息日志将在长期运行中拯救您的屁股。如果不轮换您的日志,您的日志磁盘空间将继续增长,最终填满您的硬盘驱动器。日志轮换不仅可以节省空间,而且可以更轻松地搜索特定日期的日志文件,而不是调出一个 50MB 的未设置为日志轮换的日志文件并搜索特定日期。根据您的发行版,logrotate 位于 /etc/logrotate.conf 中。由于这不是一篇关于 logrotate 的博文,我将您的配置留给您的想象力,并给您一个关于我如何轮换日志文件的示例
/var/log/remote/*/ { rotate 5 weekly missingok create }
这每周都会遍历 /var/log/remote/*/ 并轮换我的日志。日志轮换 1 个月,届时我有一个 cronjob,它会将我的旧日志 tar-zip 压缩,并将它们移到备份位置,在那里它们再保存一个月,然后再轮换掉。在商业环境中,当然日志会根据管理层和法律的规定保留多长时间,但对于家庭环境,我认为 2 个月的日志足以排除可能在那段时间内出现的任何问题。
Syslog 客户端由于每个服务器和设备的设置都不同,因此我不会深入探讨这一点。Syslog 在 UDP 端口 514 上通信,但正如我之前所说,我还将主 syslog 服务器设置为在 TCP 端口 1000 上与其他设备通信。这允许 syslog-ng 服务器在两个端口上侦听,端口 514 UDP 用于无法更改其端口的设备,端口 TCP 1000 用于您可以指定端口号的服务器。我为什么要使用 TCP 1000 而不是 TCP 514?因为 Linux 使用 tcp 514 用于 rsh(远程 shell),这会给我的(以及其他人的)主机系统带来一些问题。如果您计划在外部世界运行 syslog-ng(并且我假设您正在设置身份验证并使用 TLS 加密),那么设置一个非典型的 TCP 端口将是您的最佳选择。
1. 对于设备,您应该只需要告诉设备指向主机名,并确保 UDP 514 或 TCP 1000 是目标
2. 对于 rsyslog 客户端,添加以下行
For TCP: *.* @@ipaddress:1000 For UDP: *.* @ipaddress:514
3. 对于 syslog-ng 客户端,添加以下行
*New syslog Protocol* syslog(host tranport [options]; *old syslog protocol* destination d_tcp { syslog(ip("remoteip") transport("tcp") port(1000) localport(999)}; }; destination d_udp { syslog(ip("remoteip") transport("udp") port(514) localport(999)}; };结论
好了,这就是 syslog-ng 的鸟瞰图。关于 syslog-ng,您还可以学习更多内容,因为我只是介绍了入门的基础知识。从这里您可以深入了解宏、增强的过滤以及 syslog 消息的 TLS/基于证书的加密(我可能会在以后的博文中介绍)。通过将您的 syslog 消息发送到集中式 syslog 服务器并备份所述 syslog 服务器,您可以放心,您的系统消息是安全的,并且在您需要时易于访问。
正如之前承诺的那样,这里有一些链接可以帮助您开始使用 syslog-ng
syslog-ng 开源版 3.1 管理员指南(HTML) http://www.balabit.com/sites/default/files/documents/syslog-ng-ose-v3.1-guide-admin-en.html/bk01-toc.html
syslog-ng 开源版 3.1 管理员指南(PDF) http://www.balabit.com/support/documentation/syslog-ng-pe-v3.2-guide-admin-en_1.pdf