ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

EvtSys+Rsyslog:Windows事件日志转发与180天留存

EvtSys+Rsyslog:Windows事件日志转发与180天留存 1. 方案选型为什么是 EvtSys 加 Rsyslog 这个组合Windows 下用 EvtSys 发送日志到 Rsyslog 服务器这套组合我在好几套内网环境里反复搭过也是最容易被低估的一套。原因很朴素Linux 那边一行 rsyslog 配置就能把日志收得服服帖帖Windows 这边却要靠事件查看器一个个翻服务器一重启、日志一滚动前面几天的记录就找不回来了。先说清楚这套东西解决什么问题。Windows 的事件日志天生是本地闭环的——Application、System、Security 三大日志分别躺在C:\Windows\System32\winevt\Logs\底下的.evtx文件里默认大小从 20MB 到 128MB 不等写满就按最旧的覆盖。真出事的时候你往往需要的是三台机器同一时间段发生了什么而不是这一台机器手头还剩什么。EvtSys 的作用就是把这几个.evtx里的新事件实时抠出来格式化成标准 syslog 文本甩给远端的 RsyslogRsyslog 负责接收、按来源分类落盘、滚动归档需要的时候还能二次转发到检索平台。适合看这篇内容的人大致三类一是手里有一堆 Windows 服务器、想用最低成本做日志集中收管的人二是做等保、内审、安全加固需要把审计日志留存到 180 天以上的人三是已经有一套 Linux 侧的 rsyslog 体系想把 Windows 也纳进来统一管理的人。不管你是第一次接触 syslog还是只想找个能直接抄的配置下面的内容都可以直接拿去用。1.1 EvtSys 到底是个什么东西EvtSys 是一个非常有年代感的 Windows 服务程序体积小得离谱通常就一个evtsys.exe加一个evtsys.dll加起来不到 200KB。它的工作逻辑很简单作为一个 Windows 服务常驻订阅本机的 Application、System、Security 三个事件日志通道每来一条新事件就调用 Windows 的事件 API 把事件的格式化描述文本就是你在地事件查看器常规标签里看到的那段中文说明取出来再拼成一条 syslog 报文发出去。它的优点和缺点同样鲜明。优点是零依赖、部署快、资源占用极低在一台内存 2GB 的老 Server 上跑也基本看不出负载不需要装 .NET 运行时不需要额外开端口很适合那种我只想让它把日志发走别给我装一堆东西的场景。缺点是它真的很老——不支持自定义 XPath 过滤、不支持结构化 JSON 输出、不支持磁盘缓存补发、对 IPv6 支持也很敷衍。你要是需要断网期间先落本地、恢复了自动补发这种能力它做不到得换 NXLog 或者 Winlogbeat。我的经验是EvtSys 适合日志量中等、网络稳定、只要原始文本的场景如果你所在的环境网络抖动频繁或者后面要做复杂的字段级检索趁早选别的工具别在这上面花时间。1.2 和其他几种做法的横向对比很多人第一反应是用 Windows 原生的 WEFWindows Event Forwarding或者第三方采集器我把常见的几条路摆在一起对比一下你自己判断。方案部署复杂度资源占用断点续传输出格式适用场景EvtSys Rsyslog极低极低不支持纯文本 syslog中小规模、内网稳定NXLog Rsyslog中低支持文本/JSON有过滤和补发需求Winlogbeat 检索平台中中支持JSON已有 ELK 体系原生 WEF中高低支持原生事件纯 Windows 域环境从表里能看出来EvtSys 的定位就是够用就好。它的部署成本低到夸张拷贝两个文件、跑一条安装命令、看一眼服务有没有起来五分钟搞定剩下的时间都花在 Rsyslog 那边的接收配置上。这也是我为什么在很多只需要把日志发出来就行的项目里第一选择还是它。1.3 整体数据流和端口规划整套链路是这样的Windows 主机上的 EvtSys 服务抓取事件通过 UDP 或 TCP 把 syslog 报文发到 Rsyslog 服务器的 514 端口Rsyslog 按来源主机拆文件写入本地磁盘logrotate 每天切割、压缩、保留 180 天需要的时候再由 Rsyslog 转发一份到别的平台。这里有个容易搞混的点syslog 的 514 端口UDP 和 TCP 是两套独立的东西不是同一个监听的两种协议。EvtSys 默认走 UDP因为 UDP 无连接、开销小但它不保证送达网络一拥塞就静默丢包。所以我更推荐在 Rsyslog 上把 UDP 和 TCP 都打开EvtSys 那边按实际情况选实在不放心就用 TCP。再补一个基础知识点后面排查问题会反复用到syslog 报文开头的尖括号数字叫 PRI 值计算公式是PRI Facility × 8 Severity。Facility 里 local0 到 local7 是留给自定义用途的分别对应数值 16 到 23Severity 从 0emerg到 7debug。举个例子你在服务器上抓包看到174那么 174 ÷ 8 21 余 6说明 Facility 是 21local5Severity 是 6info。这个换算在排查日志跑错文件了的时候特别有用。2. Windows 端实操EvtSys 的部署与避坑整个项目里最容易出问题的其实不是 Rsyslog而是 Windows 这一侧。原因也简单Windows 的权限体系、服务账户、防火墙策略都比 Linux 复杂而且 EvtSys 这个老工具对错误的提示非常不友好——参数写错了它既不报错也不写日志服务装上了但就是不发数据你得靠抓包才能看出端倪。2.1 文件准备与目录位置先把文件放到一个不会被误删的地方。我一般建C:\Tools\evtsys\把evtsys.exe和evtsys.dll两个文件一起丢进去。注意这两个文件必须放在同一个目录exe 启动时会去同目录找 dll分开放会直接报找不到组件。版本选择上32 位和 64 位两个版本我都用过在 64 位系统上装 32 位版本也能跑只是会在任务管理器里看到带*32标记的进程。如果你的环境对进程位数有审计要求就老老实实选 64 位版本。另外别把它放在桌面或者我的文档这种用户目录里——服务启动时用的是系统账户用户目录的权限它不一定能读到。有个坑我踩过一次把文件放在一个开着压缩属性的目录里结果服务启动时报权限错误。后来把文件挪到普通目录就正常了。NTFS 压缩属性偶尔会影响老程序的加载遇到莫名其妙的启动失败先排除这一类干扰。2.2 安装成服务并确认参数安装命令本身很简单用管理员权限打开 CMD 或 PowerShell切到工具目录执行cd C:\Tools\evtsys .\evtsys.exe -i -h 10.10.20.15 -p 514-i表示安装为服务-h后面跟 Rsyslog 服务器的 IP-p跟端口。执行完之后用下面的命令确认服务状态Get-Service | Where-Object {$_.Name -like *Eventlog*} | Format-List Name,DisplayName,Status,StartType正常情况下你会看到一个名字类似Eventlog to Syslog的服务状态是 Running启动类型是自动。如果状态是 Stopped先手动启一次看看Start-Service -Name Eventlog to Syslog启动失败的话用Get-EventLog -LogName Application -Newest 20看看有没有相关的错误记录或者直接到事件查看器里翻 Application 日志。这里必须提醒一句不同来源的 EvtSys 打包版本命令行参数是有差异的。你能拿到的版本可能还支持-l做级别过滤、-t切换 TCP、-f指定 facility 之类的开关。最稳妥的做法是先执行.\evtsys.exe -h或直接不带参数跑一次把帮助信息看完整再动手别照抄网上的命令就上生产环境。参数的含义搞清楚之后再看一下注册表里的实际配置很多版本会把服务参数写在这里Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\Eventlog to Syslog\Parameters如果帮助里说支持 facility 配置你会在这里看到对应的键值。改注册表之后记得重启服务才会生效光改键值不重启是没用的。2.3 权限让服务能读到安全日志这是整套流程里最关键、也最容易被忽略的一环。Application 和 System 两个日志普通用户权限就能读但 Security 日志不一样它受系统的审计策略保护读取它需要管理审核和安全日志这个特权。EvtSys 服务默认运行在 LocalSystem 账户下这个账户本身就带这个特权所以开箱即用是没问题的。但如果你所在的环境有安全基线要求把服务账户改成了 NetworkService 或者某个自建的低权限账户那 Security 日志就一条都发不出来——而且它不会报错只是安静地什么都不发。检查方法Get-CimInstance Win32_Service -Filter Name like %Eventlog% | Select-Object Name,StartName,State如果StartName是LocalSystem权限这块基本可以放心。要是被改成了别的账户要么改回去要么用secpol.msc打开本地安全策略在本地策略 - 用户权限分配里把那个账户加进管理审核和安全日志。实操心得我遇到过一种更隐蔽的情况——服务账户有特权但 Windows 的 UAC 或者某个第三方安全软件拦截了服务对事件日志的访问。表现同样是服务在跑但不发数据。这种时候最有效的排查手段就是临时换一个全新的、干净的测试机跑一遍同样的配置用排除法定位是环境问题还是配置问题。2.4 用抓包确认日志真的发出去了配置完别急着去 Rsyslog 那边等先在 Windows 上确认数据出得去。最直接的办法是用 Rsyslog 服务器抓包tcpdump -i any -nn udp port 514 -c 20 -A如果能看到类似134Feb 10 14:32:11 WIN-DC01 EvtSys[1234]: ...这样的输出说明链路是通的可以进入下一步。抓不到就说明问题在 Windows 侧。Windows 本地也可以用 PowerShell 做一次简单的出站探测确认网络可达Test-NetConnection -ComputerName 10.10.20.15 -Port 514 -InformationLevel Detailed注意 UDP 端口用Test-NetConnection测不出通不通——UDP 没有握手它只会告诉你连接尝试已发出。想真正验证还是得靠对端抓包。另外一个很实用的技巧是临时把服务停掉手工前台跑一次Stop-Service -Name Eventlog to Syslog .\evtsys.exe -d -h 10.10.20.15 -p 514很多版本支持-d调试模式会直接在当前窗口打印发送情况能一眼看出是没抓到事件还是发送失败。看完按 CtrlC 退出再把服务启回来。3. Rsyslog 端接收、分类、落盘Windows 那边装完只是完成了一半真正决定这套体系好不好用的是 Rsyslog 这边的配置。我见过太多人只写了一个 UDP 监听就完事结果日志乱成一锅粥所有机器的日志混在一个文件里、中文全是问号、时间戳对不上、日志量一大就丢包。下面按顺序说。3.1 打开 UDP/TCP 监听并放行本机防火墙Rsyslog 的现代写法是模块化配置把下面这段放进/etc/rsyslog.d/10-win.confmodule(loadimudp) input(typeimudp port514 threads2) module(loadimtcp) input(typeimtcp port514)threads2的意思是开两个 UDP 接收线程日志量大的时候能明显减少丢包。另外UDP 输入默认带一个限速超过 200 条/秒的部分会被直接丢弃这几乎是把日志量大的环境坑了一遍。关掉它的方法是指定rateLimit.interval0input(typeimudp port514 threads4 rateLimit.interval0)写完之后检查配置语法再重启sudo rsyslogd -N1 sudo systemctl restart rsyslog sudo ss -lunp | grep 514 sudo systemctl status rsyslog --no-pager系统防火墙也要放行。如果你用的是 firewalldsudo firewall-cmd --permanent --add-port514/udp sudo firewall-cmd --permanent --add-port514/tcp sudo firewall-cmd --reload这一步经常被漏掉尤其是在已经习惯关掉防火墙的测试机上配好换到生产环境就死活收不到最后发现是防火墙没开。注意514 是特权端口小于 1024Rsyslog 虽然以 root 启动但很多发行版会降权运行。如果重启后ss看不到监听先确认是不是端口绑定失败日志里会有 cannot bind 之类的提示。3.2 按来源 IP 拆文件顺手关掉重复消息抑制所有 Windows 机器的日志堆在一个文件里是没法用的。按来源 IP 或者主机名分目录是最常见的做法template(nameWinRaw typestring string/var/log/windows/%FROMHOST-IP%/%$YEAR%-%$MONTH%-%$DAY%.log) if ($fromhost-ip startswith 10.10.) then { action(typeomfile dynaFileWinRaw fileCreateMode0640 dirCreateMode0750) stop }这里有几个细节值得说。%FROMHOST-IP%用的是报文源 IP比%hostname%可靠——EvtSys 发出来的主机名有时候是短名、有时候带域名后缀不统一。dynaFile是动态文件名Rsyslog 会按模板实时算出路径。stop表示这条日志处理到这里就结束不再往下走其他规则避免被系统默认规则再写一份。还有一个必须关掉的开关$RepeatedMsgReduction。Rsyslog 默认会把连续重复的相同消息合并成 last message repeated N times本意是省空间但对审计日志来说是灾难——你需要的是每一条原始记录不是被压缩过的统计。关掉$RepeatedMsgReduction off同理$PreserveFQDN建议设置为on让主机名保留完整域名后期做资产关联的时候好认。3.3 中文乱码与时间戳格式的处理Windows 事件日志的描述文本是中文的而 EvtSys 这个老工具在编码处理上比较随意输出很可能不是 UTF-8。表现出来就是 Rsyslog 落盘的文件里中文变成一串问号或者方块。这个问题没有一行命令解决的银弹得从两端配合处理。先确认现象file /var/log/windows/10.10.20.31/2025-02-10.log如果file命令识别成 ISO-8859 或者 unknown-8bit说明确实不是 UTF-8。这时候有两种思路一是换一个明确支持 UTF-8 输出的采集工具二是保留原样在检索层面按 GBK 解码。生产环境我更倾向第一种编码问题拖到后面处理成本只会更高。时间戳是另一个高频问题。EvtSys 发出来的 syslog 头用的是 Windows 本机时间而且不带时区信息Rsyslog 收到之后又会在内部记录一个接收时间。这两个时间如果服务器时区没统一就会出现日志显示的时间比实际早八小时这种闹心事。我的做法是在所有服务器上统一用 UTC 时间Rsyslog 侧用%timereported:::date-rfc3339%输出带时区的 ISO 格式显示的时候由前端按本地时区转换。这样一来跨时区、跨机房的日志排序才不会乱。3.4 把原始文本转成结构化 JSON纯文本日志后续检索很难做字段过滤如果你们的平台支持 JSON可以在落盘的同时输出一份结构化版本template(nameWinJSON typestring string{\ts\:\%timereported:::date-rfc3339%\,\host\:\%hostname%\,\ip\:\%fromhost-ip%\,\facility\:\%syslogfacility%\,\severity\:\%syslogseverity%\,\tag\:\%syslogtag:::json%\,\msg\:\%msg:::json%\}\n)这里:::后面跟的是属性替换选项json会对内容做 JSON 转义jsonf则会连引号一起加上。很多人写模板的时候忘了转义结果消息体里一旦出现引号或者反斜杠整行 JSON 就废了。加上:::json就能避开这个问题。配置完可以这样验证格式是否正确tail -n 20 /var/log/windows/10.10.20.31/2025-02-10.json | python3 -m json.tool --no-ensure-ascii能正常解析说明格式没问题。4. 日志留存 180 天滚动、压缩与容量估算很多合规场景都要求审计日志留存 180 天以上这个要求听起来简单真正落地的时候最容易翻车的是磁盘容量。日志这种东西有个特点量不会稳定某天出了故障或者被扫描单日日志量可能是平时的十倍。4.1 logrotate 配置与 Rsyslog 重载先看 Rsyslog 自己的队列配置防止磁盘压力大的时候丢数据$WorkDirectory /var/spool/rsyslog $ActionQueueType LinkedList $ActionQueueFileName winq $ActionQueueMaxDiskSpace 2g $ActionQueueSaveOnShutdown on $ActionResumeRetryCount -1然后写 logrotatesudo tee /etc/logrotate.d/windows-rsyslog /dev/null EOF /var/log/windows/*/*.log { daily rotate 180 missingok notifempty compress delaycompress dateext dateformat -%Y%m%d create 0640 syslog adm sharedscripts postrotate /usr/bin/systemctl kill -s HUP rsyslog.service /dev/null 21 || true endscript } EOFrotate 180配合daily就是保留 180 天的日切日志。delaycompress表示最新一份不压缩方便你实时 tail。dateext让文件名带上日期比默认的数字编号直观得多。手动测一次别等第二天sudo logrotate -d /etc/logrotate.d/windows-rsyslog sudo logrotate -f /etc/logrotate.d/windows-rsyslog ls -lh /var/log/windows/10.10.20.31/-d是 dry-run只打印不执行-f是强制执行用来验证配置有没有语法问题。这两个参数我每次配完都会用一遍能省下大量第二天才发现没生效的时间。4.2 磁盘容量怎么估算估算这件事没什么玄学就是拿真实数据乘一乘。先在业务高峰期抽一段样本ls -l --block-size1 /var/log/windows/10.10.20.31/2025-02-10.log wc -l /var/log/windows/10.10.20.31/2025-02-10.log比如一天 150 万条事件文件 1.1GB压缩后大约 150MB 左右文本日志压缩比通常能到 7:1 甚至更高。那么 180 天单机就是压缩前1.1GB × 180 ≈ 198GB压缩后150MB × 180 ≈ 27GB看起来压缩后不大但问题是压缩是延迟的——最近一天的日志还是原始大小而且高峰期的量可能远超平均值。安全一点的做法是按下估算值的 2.5 到 3 倍预留磁盘空间。日志类型单条平均大小日均条数参考压缩后月占用普通应用服务器400-600 字节5 万-30 万200MB-1GB文件服务器500-700 字节30 万-100 万1-3GB域控安全日志600-900 字节100 万-300 万3-10GB如果磁盘实在紧张可以按来源分级保留域控和安全相关的主机留 180 天普通应用服务器留 90 天用不同的 logrotate 配置段管理就行。4.3 Windows 本地日志也要留一手远端留存做好了本地也不能完全不管。原因很简单网络断了、Rsyslog 挂了、EvtSys 服务被误停了这段时间的日志只能靠本地.evtx兜着。默认 20MB 的安全日志在域控上可能半天就滚完了等于没有。把安全日志的最大尺寸调大wevtutil sl Security /ms:1073741824 wevtutil gl Security1073741824就是 1GB。wevtutil gl用来确认是否生效输出里会显示maximumSize字段。如果机器多别一台台改用组策略统一推计算机配置 → 管理模板 → Windows 组件 → 事件日志服务 → 安全把指定最大日志文件大小设为 1048576单位是 KB即 1GB。域环境下推下去比手工改快得多也不容易漏。提醒一下把安全日志调到 1GB 会占一定磁盘空间系统盘吃紧的机器要斟酌。我的经验是系统盘留 40GB 以上的机器可以直接调到 1GB小于 30GB 的调到 512MB 更稳妥。5. 常见故障速查与实战心得这套体系搭起来不难难的是出问题的时候定位。因为链路跨越 Windows 和 Linux 两端中间还夹着一个不报错的 UDP 传输问题往往表现得很模糊。下面这几类故障是我遇到最多的。5.1 服务在跑但一条日志都收不到这是最高频的问题排查顺序我固定成四步。第一步在 Rsyslog 服务器上抓包tcpdump -i any -nn udp port 514。有包进来说明问题在 Rsyslog 配置或防火墙之外的接收环节没包进来直接跳到第三步。第二步检查 Rsyslog 是否在监听ss -lunp | grep 514。如果没监听多半是配置文件语法错误导致启动失败看journalctl -u rsyslog -n 50的输出。第三步回到 Windows 上确认服务状态和账户Get-Service看服务是否 RunningGet-CimInstance Win32_Service看启动账户是不是 LocalSystem。第四步检查 Windows 防火墙的出站规则。家用和默认配置下 Windows 出站是全放的但域环境里如果通过组策略限制了出站UDP 514 会被静默拦掉表现就是完全没有包出去。用Test-NetConnection -Port 514先确认基本可达性。5.2 日志收不全、重复或者顺序乱了日志量一大三种现象会同时出现丢几条、重复几条、顺序错乱。这是 UDP 的天然特性——不保证送达、不保证去重、不保证顺序。要彻底解决只有上 TCP代价是稍微增加一点开销在千兆内网里基本可以忽略。如果坚持用 UDP至少把这几个开关检查一遍UDP 限速是否关闭rateLimit.interval0接收线程数是否够threads调到 4磁盘写入队列是否足够大$ActionQueueMaxDiskSpace重复消息抑制是否已关闭$RepeatedMsgReduction off另外要排查一个容易被忽略的点如果一台机器上同时装了 EvtSys 和别的采集工具两条链路各发一份看起来就像日志重复。所以配置之前先摸清楚这台机器上还有没有别的日志转发程序。5.3 重启之后就不发了Windows 重启后服务没起来或者起来了但不工作通常是两个原因。一是服务启动类型被改成了手动重启后自然不启动二是服务依赖的事件日志服务启动顺序有问题服务早早起来但订阅不上事件通道。修复方法很简单Set-Service -Name Eventlog to Syslog -StartupType Automatic然后重启一次服务看能不能正常发数据。如果你的环境里 EvtSys 服务偶尔会自己退出可以再加一层保险用任务计划程序配一个开机后延迟 2 分钟触发的脚本检测服务状态并拉起。我自己踩过的一个坑某台机器的 EvtSys 服务运行正常抓包也有数据出去但 Rsyslog 侧就是收不到。折腾了半天发现是中间的一台交换机做了 UDP 广播抑制把跨网段的 UDP 514 给拦了。后来改成 TCP 就通了。这件事的教训是网络设备的中转策略也要纳入排查范围别只盯着两端。5.4 排查速查表把上面这些整理成一张表出问题的时候对着过一遍效率能高不少。现象可能原因快速验证处理方式完全没有日志服务未启动Get-Service启动服务并设为自动完全没有日志防火墙拦截tcpdump无包放行 514/udp完全没有日志未监听端口ss -lunp | grep 514修配置后重启 rsyslog只有 Application 和 System服务账户权限不足检查StartName改回 LocalSystem 或授权日志量明显偏少UDP 限速丢包看 rsyslog 日志提示关闭 rateLimit中文显示为问号编码不匹配file查看编码换 UTF-8 输出工具时间对不上时区未统一比对两端date统一 UTC 或统一时区大量重复日志双采集器重复发送检查已装软件停掉其中一个重启后中断启动类型为手动Get-Service改为 Automatic最后再分享一个我用下来最省事的排查套路先在 Rsyslog 服务器上挂一个tcpdump常驻窗口再回 Windows 上重启 EvtSys 服务观察有没有报文进来。这一步能立刻把是发送端的问题还是接收端的问题劈成两半省掉大量来回猜测的时间。我这些年排查日志链路问题一半以上的时间都省在这一招上。
返回列表