Debian系统管理员面对三台以上服务器时,日志管理立刻从顺手的事变成棘手的问题。登录每台机器用grep翻找/var/log的日子必须终结。syslog协议诞生三十多年,至今仍是基础设施日志传输最可靠的方案,而rsyslog作为Debian默认安装的syslog守护进程,功能远比大多数人使用的要强大。把分散在各处的系统日志实时汇聚到一台中央服务器,不仅能省下大量排查时间,更关键的是日志一旦离开源主机就不可篡改,这是安全审计的基本要求。
理解rsyslog的传输模式rsyslog支持三种远程传输协议:UDP、TCP和RELP。UDP在514端口上跑,速度快但不可靠,网络抖动时日志会静默丢失。TCP同样用514端口,三次握手保证送达,但高负载时可能阻塞源主机的日志生成。RELP是rsyslog专为日志传输设计的可靠协议,在应用层确认机制下既保证送达又不阻塞,端口默认20514。生产环境里,内部网络用TCP就够了,跨机房或者日志量极大的场景才需要RELP。很多人不知道rsyslog还支持TLS加密传输,用gtls驱动给TCP套上证书,日志在网络上就是密文,等保合规场景下这是刚需。
中央日志服务器配置先搞定接收端。Debian 12上rsyslog默认已安装,但需要手动开启远程接收模块。编辑/etc/rsyslog.conf或者更规范的做法是在/etc/rsyslog.d/下创建新文件,比如remote-receiver.conf:
# 加载TCP和UDP监听模块 module(load="imtcp") module(load="imudp") # TCP监听在514端口,支持500个并发连接 input(type="imtcp" port="514" MaxSessions="500") # UDP监听在514端口 input(type="imudp" port="514")
这里有个容易被忽略的细节:MaxSessions参数默认只有200,客户端数量多时必须调大,否则新连接会被拒绝。改完配置后systemctl restart rsyslog,然后用ss -tlnp | grep 514确认端口已监听。防火墙别忘了放行,nftables规则加一条tcp dport 514 accept和udp dport 514 accept。
日志收进来后怎么存?直接用默认规则所有日志会混在一个文件里,查起来跟没集中差不多。需要按客户端IP或主机名自动分目录存放。在/etc/rsyslog.d/下创建存储模板文件:
# 定义日志存储模板:按主机IP分目录,按日期分文件
$template RemoteLogs,"/var/log/remote/%fromhost-ip%/%$year%-%$month%-%$day%.log"
# 来源IP为192.168.0.0/16的日志使用此模板
if $fromhost-ip startswith "192.168." then {
action(type="omfile" dynaFile="RemoteLogs")
stop
}
%fromhost-ip%变量取的是客户端真实IP,不会被NAT干扰。stop指令很重要,表示匹配后不再继续处理后续规则,避免日志重复写入。每天零点rsyslog会自动切换到新日期文件,不需要logrotate干预。但要注意/var/log/remote目录需要手动创建并赋予syslog用户写权限:mkdir -p /var/log/remote && chown syslog:adm /var/log/remote。
客户端推送配置客户端配置更简单。在Debian服务器上编辑/etc/rsyslog.d/forward.conf:
# 加载TCP转发模块
module(load="omfwd")
# 将所有设施、所有级别的日志通过TCP发送到中央服务器
*.* action(type="omfwd"
target="192.168.1.100"
port="514"
protocol="tcp"
action.resumeRetryCount="-1"
queue.type="linkedlist"
queue.filename="fwdqueue"
queue.saveonshutdown="on"
)
这个配置里有几个关键点。action.resumeRetryCount="-1"表示中央服务器宕机时无限重试,不会丢日志。queue.type="linkedlist"启用磁盘辅助队列,当网络中断或服务器不可达时,日志先在本地磁盘排队,恢复后自动补发。queue.filename指定队列文件名,queue.saveonshutdown确保rsyslog服务停止时队列不丢失。这套机制在生产环境中救过无数运维人员的命——半夜网络故障不会导致那段时间的日志出现空白。
如果只转发特定设施,把*.*改成auth.*;kern.*;mail.*这样的选择器即可。但建议全量转发,在服务器端再做过滤和分发,客户端保持简单。
TLS加密传输配置等保和密评场景下日志传输必须加密。rsyslog的TLS配置稍复杂但值得掌握。先在中央服务器上生成CA和证书,用openssl三步走:
# 生成CA私钥和证书 openssl genrsa -out ca-key.pem 4096 openssl req -new -x509 -days 3650 -key ca-key.pem -out ca.pem -subj "/CN=LogCA" # 生成服务器私钥和证书签名请求 openssl genrsa -out server-key.pem 2048 openssl req -new -key server-key.pem -out server.csr -subj "/CN=logserver.local" # 用CA签发服务器证书 openssl x509 -req -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -days 3650
把ca.pem、server-cert.pem、server-key.pem复制到/etc/rsyslog.d/certs/,服务器端配置改为:
module(load="imtcp" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.Authmode="x509/name")
input(type="imtcp" port="6514")
# TLS全局配置
global(DefaultNetstreamDriver="gtls"
DefaultNetstreamDriverCAFile="/etc/rsyslog.d/certs/ca.pem"
DefaultNetstreamDriverCertFile="/etc/rsyslog.d/certs/server-cert.pem"
DefaultNetstreamDriverKeyFile="/etc/rsyslog.d/certs/server-key.pem"
)
客户端把ca.pem复制过去,配置转发时指定StreamDriver:
action(type="omfwd"
target="192.168.1.100"
port="6514"
protocol="tcp"
StreamDriver="gtls"
StreamDriverMode="1"
StreamDriverAuthMode="x509/name"
StreamDriverPermittedPeer="logserver.local"
)
StreamDriverPermittedPeer必须与服务器证书的CN一致,这是防止中间人攻击的关键校验。配置完成后用openssl s_client -connect 192.168.1.100:6514测试TLS握手是否成功。
日志结构化与过滤分流日志全堆在文件里只是第一步,真正的中央化管理要做结构化处理。rsyslog的rainerscript脚本语言可以在接收端对日志实时解析、分类、告警。比如把所有认证失败日志单独抽取出来:
if $syslogfacility-text == "auth" and $msg contains "Failed password" then {
action(type="omfile" file="/var/log/remote/auth-failures.log")
}
更实用的场景是按应用拆分。如果多台Web服务器都把nginx日志通过syslog发过来,可以用来源IP加标签区分:
if $fromhost-ip == "192.168.1.10" and $programname == "nginx" then {
action(type="omfile" file="/var/log/remote/web1-nginx.log")
}
if $fromhost-ip == "192.168.1.11" and $programname == "nginx" then {
action(type="omfile" file="/var/log/remote/web2-nginx.log")
}
rsyslog 8.x版本还支持直接输出到MySQL或PostgreSQL数据库,适合需要做复杂查询的团队。ommysql模块配置好连接信息后,日志会按预设表结构入库,后续用SQL统计错误频率、生成报表都很方便。不过数据库写入性能远低于文件,日均日志量超过10GB的场景要谨慎评估。
日志轮转与保留策略中央服务器上的日志增长很快,必须配置轮转。用logrotate管理/var/log/remote下的文件:
/var/log/remote/*/*.log {
daily
rotate 30
missingok
notifempty
compress
delaycompress
sharedscripts
postrotate
/usr/lib/rsyslog/rsyslog-rotate
endscript
}
daily加rotate 30保留30天,compress压缩节省空间。注意postrotate里调用rsyslog-rotate通知rsyslog重新打开文件句柄,否则轮转后日志会继续写入已删除的文件。对于合规要求更长的保留期,可以在logrotate后加一个脚本把压缩包上传到对象存储,本地只留热数据。
监控与告警集成日志集中后,被动翻查只是初级用法。在rsyslog里嵌入条件判断可以实现实时告警。比如检测到root登录失败超过阈值时发送邮件:
$ModLoad ommail
if $msg contains "Failed password for root" then {
action(type="ommail"
server="smtp.internal.com"
port="25"
mailfrom="rsyslog@monitor.internal.com"
mailto="oncall@company.com"
subject="安全告警:root登录失败"
)
}
更专业的做法是把日志转发到Grafana Loki或Elasticsearch,配合Grafana做可视化看板。rsyslog通过omelasticsearch模块可以直接写ES,或者用omfwd转发到Logstash。一套完整的日志中台方案:rsyslog收集→Kafka缓冲→Logstash解析→Elasticsearch索引→Grafana展示,这套链路在日均百GB日志量的场景下依然稳定。
常见故障排查客户端日志发不出去,先检查网络连通性:telnet 192.168.1.100 514。如果端口通但日志不到,看客户端/var/log/syslog里rsyslog自身的报错。常见问题包括DNS解析超时导致rsyslog阻塞,解决方法是在forward配置里用IP不用域名。服务器端收不到特定客户端的日志,检查/etc/rsyslog.d/下的规则是否有stop指令过早截断了处理链。用rsyslog的调试模式定位问题:rsyslogd -dn运行在前台,日志流向一目了然。磁盘队列堆积说明网络或服务器端有问题,检查/var/spool/rsyslog目录下队列文件大小,正常应该接近零。
时间戳不一致是另一个常见坑。所有服务器必须配置NTP时间同步,否则日志按时间排序时会出现混乱。Debian下timedatectl set-ntp true一条命令启用systemd-timesyncd,配合chrony做精确同步。中央服务器接收日志时建议开启精确时间戳:$ActionFileDefaultTemplate RSYSLOG_FileFormat,这个模板记录的是客户端原始时间而非服务器接收时间,排查问题时才能还原真实时序。
这套基于rsyslog的日志中央化方案,从两台服务器到两百台都能平滑扩展。没有额外的代理进程,不依赖外部服务,Debian系统自带工具就能完成。配置一次,后续加机器只需复制客户端配置文件改个IP,维护成本极低。当审计要求出示过去六个月的登录记录时,你只需要在一台服务器上敲一条命令。
