搭建集中式系统日志服务器系统指南

译文
运维 服务器运维
本文要介绍的不仅仅是如何搭建集中式syslog-ng(下一代系统日志工具)服务器,还要介绍为什么你要着手搭建这样一台服务器。

早在1997年本人担任Linux管理员时,搭建集中式系统日志服务器是最先要完成的真正的系统管理任务之一。我当时的上司想获取来自众多硬件设备的日志文件,要求我使用正则表达式(regexp),搜索日志文件寻找某些关键词。当年Linux还处于初期阶段,而我在空闲时一直在捣鼓Linux。于是,我不失时机地把Linux引入到了当时效力的那家公司。Linux行不行?当然行!本文要介绍的不仅仅是如何搭建集中式syslog-ng(下一代系统日志工具)服务器,还要介绍为什么你要着手搭建这样一台服务器。

那么,系统日志是什么东西?系统日志在Linux中用于将系统消息记入日志。下一代系统日志工具在1998年开发而成,只是对早期的系统日志工具作了改写。截至2010年,下一代系统日志工具仍由BalaBit IT Security公司在积极开发,拥有的功能特性要多得多,其中包括更好的TCP处理、对消息采取TLS加密以及将消息发送到数据库等等。一些Linux发行版允许你安装系统日志工具、rsyslog或者下一代系统日志工具。本文重点介绍下一代系统日志工具,因为这个工具更新颖;如果读者愿意,可以在之后选择拥有下一代系统日志工具软件的公司的企业版,以获得“支持”。

刚才简要介绍了下一代系统日志工具,接下来谈谈你为何要用集中式下一代系统日志工具服务器。我就说说两个主要的理由。第一个是出于安全目的。如果你的路由器、防火墙、交换机、Linux服务器及/或其他硬件指向一台安全可靠的集中式下一代系统日志工具服务器,要是有人的确企图攻击上述的其中一个设备,可以把日志文件安全地存放到让人放心的异地位置。如果系统日志文件存放在设备上,这无异于让攻击者能够抹掉痕迹。诚然,攻击者能够禁用将日志文件发送到外部下一代系统日志工具服务器的功能,但是在此之前的所有连接都将位于集中式系统日志服务器上。另一个理由是为了方便起见。比如说,如果你有一台服务器崩溃了,毫无反应,你就可以检查集中式系统日志服务器上的内核错误日志。如果你想检查在一段较长时间内不同日期之间的系统日志模式,只要使用正则表达式,搜索来自集中式系统日志服务器的日志文件。

那么,我平时怎么做的呢?实际上,这两种方法我在家里都用。我的设备和服务器不但把它们的所有系统日志文件转发到某个集中式位置,而且这个位置严加保护起来。所说的那台机器是一个虚拟机,只有1个端口开着(系统日志端口),只能从本地机器来访问,系统日志文件而放在外部驱动器上。这么做是不是过于小心谨慎?也许有点吧。但我的确知道,在我家这个环境中,如果外部驱动器装满了太多的系统日志文件,它不会导致虚拟机崩溃。要是虚拟机果真出现了什么岔子,主机操作系统也不会受到影响。如果有人果真可以访问我的其中一个设备,他也没有办法访问我的系统日志服务器。没错,要是我的主机操作系统遇到了什么问题,那么访客虚拟机就会有问题;但是我们总是无法做到事事都能防备。我得承认,这么做太过小心谨慎了;对大多数人来说,这么做可能有些过了。

开始入手之前,有必要先声明一下。首先,与我之前写的所有文章一样,这里的所有测试是用Debian来完成的。本文中,我针对Debian 6.0.1设置了虚拟机,因而你的情况可能不一样。另外,我不会深入探讨如何合理保护你的服务器、把系统日志文件放在哪里最合适,或者如何设置除下一代系统日志工具之外的一切。本文就介绍集中式下一代系统日志工具服务器的基本方面。

#p# 服务器端的安装和配置

安装下一代系统日志工具实际上并不难,如果从软件包来安装更是如此。如果是Debian,运行apt-get install syslog-ng;如果是红帽系统,运行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,即可安装该工具。接下来是下载、解包、配置、编译和安装。一旦安装好了下一代系统日志工具,我们就可以配置服务器端了。

全局选项

你要做的头一件事就是找到下一代系统日志工具的配置文件。默认安装文件(针对Debian变种版本)是/etc/syslog-ng/syslog-ng.conf。在编辑任何配置文件之前,进行变更之前先拷贝一份原始配置文件是个好方法。这完全是为了以免出现问题,你需要找回原始配置文件。我往往把自己的原始配置文件标以.orig(这里是syslog-ng.conf.orig)。你已备份好了配置文件,现在就用自己喜欢的编辑器打开它,可以入手了。

long_hostnames(默认值:off)——我在本文中使用下一代系统日志工具OSE版本3.1,我其实在全局配置指南中找不到long_hostname。我会使用默认值为off的long hostnames(长主机名),使用完全符合标准的域名。

flush_lines(默认值:0)——设置一次向目的地发送几行消息。如果设成0,一收到消息就发送,但是要牢记:如果这个值设得偏高,会增加消息延迟。这个选项在下一代系统日志工具的客户端上很有用。在发送到目的地之前,你要将XX条消息保留在客户端上,那样即使收到来自服务器的众多流量,也不至于拥塞那台主要的下一代系统日志工具服务器。

use_dns(默认值:no)——选项包括:yes、no和persist_only。这个选项的选择取决于你和你的环境。如果你的下一代系统日志工具在防火墙后面,无法访问外界,那么选择‘yes’很合适。如果可以访问外界,就设置成‘no’,以便阻止可能出现的拒绝服务(DoS)攻击。 我将该选项设成了‘persist_only’,因而会检查我那台下一代系统日志工具服务器上的/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$)——含有不该作为hostnames来处理的主机名的正则表达式,本文中是gconfd。如果你有好多台服务器,我会建议hostnames,当然除非你记得域中的每一个IP地址。
这些是“默认”的全局配置选项,但你还可以使用其他众多选项。我还使用下列选项:
normalize_hostnames(yes)——该选项把所有主机名转换成小写。我的一些设备使用大写主机名,有时候我会迷上某个新主机,并把主机名的第一个字母转换成大写。该选项可以把所有字符转换成小写,以便阅读。
keep_hostname(yes)——如果要进行转发或透过外部服务器传送,该选项就会保留主机名,那样主机最终到达中央服务器后,主机名会一并到达,而不是依赖DNS(或/etc/hosts)。如果你使用$HOST宏指令,应该启用该选项。

在更大、更重要的环境(不是小型办公环境)下,我会设置stats_freq(600)和stats_level(2),以便从服务器获取统计消息。在大多数小型办公环境下,你可能搜索来自三五个设备的系统日志数据;这种情况下,实际丢失数据的可能性相当小。在更庞大的企业环境下,可能有几百个设备向中央系统日志服务器报告,启用统计功能让系统管理员能够检查统计消息和可能丢失的消息。

你的全局配置选项看起来如下:
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);
};

#p# 设置监听器

为下一代系统日志工具设置监听器实际上只需要在配置文件中添加几行。典型的监听器行看起来像这样:

source s_net { tcp((ip(127.0.0.1) port(1000) max-connections 5000)); udp (); };
source s_net = Network listener,表示网络监听器
tcp(ip(127.0.0.1) = Listen on localhost,表示监听本地主机。如果你有多块网卡,或者想指定某个IP地址与某块网卡进行绑定,将127.0.0.1更改成那块特定网卡的IP地址。
port (1000) = Listen to TCP port 1000,表示监听TCP端口1000。
max connections = Allow 5000 simultaneous connections (stops the dreaded 'run away server' syndrome) ,表示允许5000个同时连接(杜绝可怕的‘失控服务器’综合征)
udp () = Some devices send their syslog messages via udp,表示一些设备通过udp发送系统日志消息,所以如果你无法指定TCP和端口号,就请启用udp。
encrypt(allow) = This could be an entire blog post in itself,表示这本身可能是整篇博文。下一代系统日志工具允许对系统日志消息采用加密(基于TLS/证书)。
示例看起来像这样:
# Listen on TCP Port 1000 and UDP Port 514, Max 500
Connections source s_net {
tcp(port(1000) max-connections(500)); udp(););
目的地——有发就有收。在这里,发出去的必须在某个地方接收。一旦收到来自下一代系统日志工具服务器的消息,它就要发送到某地。因而syslog-ng.conf文件就有目的地这个部分。正如你所见,默认值包括本地机器上服务器消息的*nix目的地。但是入站消息又如何呢?它们发送到哪里?问得好!默认情况下,入站消息会将系统日志消息发送到在下一代系统日志工具指定的子系统。比如说,如果这个消息被归类成验证消息(/var/log/auth),那么它会把消息转储到下一代系统日志工具的/var/log/auth.log文件中,附有相关信息(主机名和日期/时间等)。

如果这实际上是你想要实现的,一堆服务器转储到与主服务器同一个文件上,那么我想任务完成了。但是下一代系统日志工具的功能绝不仅仅局限于此。目的地可能是平面文件、进入其他应用程序的管道、SQL数据库(mysql、MS SQL和Oracle等)、远程日志服务器和Terminal Windows。我将着重探讨平面文件,假设你现在用的也是平面文件。

我搭建集中式系统日志服务器的方式可能与你的搭建方式不一样。我有一个文件夹含有每个主机名,来自主机名的系统日志位于该文件夹中。比如:/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"); };

从理论上来说,现在下一代系统日志工具服务器应该可以创建存放文件所必需的目录了(在全局策略中已有指定),但有时我会遇到问题:目录无法顺利创建,下一代系统日志工具中的错误却在/var/log/errors中报告。为了以后减少麻烦和痛苦,我往往顺便创建好主机和日志文件,我丢失的任何信息会最后出现在/var/log/errors中。

如果你是资深的下一代系统日志工具用户,可能会想:我为何把本地主机目的地和远程(异地客户端)目的地分开来,而从理论上来说我本该创建d_auth,把常用本地主机过滤器也放入到文件夹中。这么做的原因是,我想把本地主机系统日志流量与远程流量分开来——虽然配置行更多了,但对我来说更省事了。另外,当Linux子系统寻找把常用日志文件放在何处,就不会受到干扰。

过滤——下一代系统日志工具能够过滤消息,而这项功能标志着系统日志工具是否成熟。过滤功能让下一代系统日志工具与众不同。有了过滤功能,我就可以做下列事:过滤防火墙日志可以寻找某些关键词(比如端口扫描),转储到单单一个文件夹,将分布式拒绝服务(DDOS)攻击过滤到另一个文件夹中。我的VOIP适配器发送系统日志事件,我根据那些消息过滤到了每一个文件,而不是过滤到单个文件。过滤还让你可以指定根据哪几个主机进行过滤,过滤到多个目的地。不仅如此,你还可以在过滤时使用正则表达式。

可以像这样来创建过滤表达式: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的入站系统日志消息,消息为‘Denial of Service’(拒绝服务攻击)。为了完成过滤器,你需要一个日志语句:
log firewall_ddos_filter { source(s_net); filter
(firewall_ddos_filter);
destination(d_net_firewall_ddos); };

在上述目的地中,我为防火墙DDOS攻击、端口扫描等添加目的地。这样一来,把日志文件与不使用标准*nix日志功能的服务器/设备分离开来,或者让统管理员更容易过滤从防火墙出来的日志(或者把许多防火墙过滤到一个日志)。

如果你想使用多个‘firewall’主机(如示例),就不要添加它们,使用布尔操作符‘and’来创建日志/过滤器规则。这不管用。而是应该使用‘or’布尔操作符,就像这样:

filter firewall_ddos_filter { host("10.1.1.1") or host
("10.1.1.2") and match("Denial of Service" value("MESSAGE")
((; };
我的‘Default’过滤命令看起来像这样:
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); };

#p# 统计消息

没有什么比一些详细的统计消息更让我高兴的了。只要运行任何服务器或服务,无论在家里还是在办公室,我都想看看服务器一段时间内在处理什么。从版本3.1开始,下一代系统日志工具现在有了一个syslog-ng-ctl统计实用程序,它大大简化了获取日志文件的任务。版本3.1之前,想获取统计文件,你就得运行echo STATS | nc -U /var/run/syslog-ng.ctl。

由于我喜欢用正则表达式,对于syslog-ng-ctl统计消息的输出结果中的分号习以为常,因而我运行syslog-ng-ctl stats | sed 's|;|\t|g',以清理输出。

你输入上述命令行后有6列:SourceName、SourceID、SourceInstance、State、Type和 Number。

SourceName——来源的名称,比如:目的地、来源、全局或中央。
SourceID——你为来源赋予的识别号(之前的例子是firewall_ddos_filter,其他例子会是d_mail和d_net_user等)
SourceInstance——来源实例的目的地,如文件名;或者程序来源(sql)或目的地的应用程序名称。
State——对象的状态:a(活动—目前处于活动状态,接收数据),d(动态—目前没有持续可用),或o(曾经活动,但停止接收孤立对象等消息)。
Type——统计消息的类型,比如:Processed,表示到达目的地的消息数量;Dropped,指丢失消息的数量;Stored,指存储在等待发送到目的地的消息列队中的消息数量;Suppressed(not sent),指被抑制消息的数量;Stamp,指上一个发送消息的时间戳。下一代系统日志工具服务重置后,这些统计类型也被重置。
Number——消息数量。

日志轮询,日志轮询,日志轮询

该日志消息对你来说是不是够清楚?从长远来看,轮询消息日志可以让你避免麻烦。如果你不对日志轮询,日志磁盘空间只会越来越挤,最后把整个硬盘都塞满。日志轮询不但可以节省空间,还会使得搜索特定日期的日志文件更容易;如果你把没有设成日志轮询的50MB日志文件调出来,搜索特定日期的内容,就会很麻烦。logrotate位于/etc/logrotate.conf,具体要看使用的Linux发行版。因为本文不是介绍logrotate,最终配置是啥样因人而宜,下面给出的例子表明我怎样轮询日志文件:

/var/log/remote/*/ { rotate 5 weekly missingok create }

这会每个星期检查/var/log/remote/*/,轮询日志。日志轮询1个月;1个月后,我会使用cronjob实用工具,对旧日志进行TAR压缩,把它们转移到备份位置;旧日志会在那里再保存一个月,之后轮换掉。当然在公司环境下,按照管理或法规要求,日志会保存相应的很长时间;但是对于家庭环境而言,我觉得日志保存2个月够长了,足以为在此期间可能出现的任何问题排错。

#p# 系统日志客户端

由于每个服务器和设备的情况不一样,我不会过于深入地探讨这方面。系统日志经由UDP端口514来通信,但是我在前面提到,我还为其他设备设置了主系统日志服务器,经由TCP端口1000通信。这让下一代系统日志工具服务器可以监听两个端口:514 UDP用于无法更改其端口的设备,TCP 1000则用于指定了端口号的服务器。为何我设置TCP 1000,而不设置TCP 514?因为Linux使用tcp 514 用于rsh(远程外壳),这会导致我(及别人)的主机系统出现一些问题。如果你打算面向外界运行下一代系统日志工具(假设你已设置了验证,并使用TLS加密),那么设置不常见的TCP端口将是最稳妥的。

1. 针对设备,你要做的就是让设备指向主机名,并确保UDP 514或TCP 1000是目的地。
2. 针对rsyslog客户端,添加下面这一行:
如果是TCP:*.* @@ipaddress:1000
如果是UDP:*.* @ipaddress:514
3. 针对下一代系统日志工具客户端,添加下面这一行:
*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)}; };

结论

上面概要介绍了下一代系统日志工具。下一代系统日志工具方面还有许多东西要了解,我只是介绍了基本的方面。你可以在此基础上了解宏指令、更严格的过滤以及对系统日志消息采用基于TLS/证书的加密。如果你把系统日志消息发送到集中式系统日志服务器,并且备份该系统日志服务器,就大可放心:你需要系统消息时,可以安全而轻松地获取这些消息。

原文链接:http://www.linuxjournal.com/content/creating-centralized-syslog-server

责任编辑:张玉 来源: 51CTO
相关推荐

2012-02-23 23:33:37

开源memcached

2021-08-12 10:25:33

SVN服务器VisualSVN s

2012-02-21 09:59:52

2023-08-22 14:20:21

2015-07-28 09:44:38

集中式云数据加密安全漏洞

2014-08-29 16:39:27

华为

2017-06-27 10:21:12

vRealize LoNSX日志管理

2009-07-20 11:11:34

分光器FTTP

2019-11-07 11:21:21

安全软件IT

2022-03-29 14:28:03

架构安全设计

2009-07-02 19:24:50

安全管理Windows审计

2020-08-19 17:56:46

缓存Redis集中式

2014-08-05 09:15:14

SDN

2024-01-22 13:55:00

2022-06-06 07:32:44

数据库系统分布式

2022-02-09 10:52:27

智能汽车网联

2010-11-09 13:53:33

2011-11-21 15:44:46

管理服务器日志

2013-04-24 10:58:24

系统安全IMAVxWorks

2010-03-31 15:45:45

CentOS系统
点赞
收藏

51CTO技术栈公众号