@
AI辅助运维:开源一个内网日志监控工具
一、背景:内网安全的隐形防线
做运维的朋友有没有过这样的经历:
- 服务器被人登录了,过了一周才发现
- 想查谁什么时候登录过,只能去翻事件查看器,效率极低
- 买了一堆昂贵的安全产品,配置复杂,小团队根本用不起
- 开源方案要么太重(ELK 一套下来几个 G),要么太难用
有没有一个轻量、简单、开箱即用的方案?
这就是我做 LanMonitor 的初衷------一个只有几 MB 的小工具,就能让你实时掌握内网所有机器的登录动态。
二、方案选型:为什么是 Winlogbeat + C# WinForms?
2.1 事件采集:为什么选 Winlogbeat?
Windows 自带的安全日志其实非常强大,4624(登录成功)、4625(登录失败)这些事件 ID 记录了所有登录行为。
但问题是:怎么把这些日志实时收集起来?
我对比了几种方案:
| 方案 | 优点 | 缺点 |
|---|---|---|
| 自己写服务读 EventLog | 简单可控 | 性能差、断点续传麻烦、兼容性差 |
| WMI 远程查询 | 不用装客户端 | 延迟高、不安全、容易断 |
| Winlogbeat | 官方出品、性能好、断点续传、稳定可靠 | 需要装客户端 |
最终选择了 Winlogbeat------Elastic 官方出品的 Windows 日志采集器,经过无数生产环境验证,稳定性有保障。
2.2 服务端:为什么用 C# WinForms?
既然用了 Winlogbeat,它的输出目标一般是 Elasticsearch。但我们只是要个告警,没必要搭一套 ELK 吧?
思路一转:能不能直接模拟 Elasticsearch 的 Bulk API,接收 Winlogbeat 的数据?
完全可以!
Winlogbeat 发的就是标准的 HTTP POST 请求,body 是 NDJSON 格式。我们只要用 HttpListener 监听端口,解析请求,弹窗告警就行了。
为什么用 C# WinForms?
- 原生 Windows 体验:桌面程序、系统托盘、弹窗告警,体验最好
- 开发效率高:WinForms 拖拖控件(或者手写代码)就能出界面
- 部署简单:单 exe,.NET 8 自包含发布,不用装运行时
- SQLite 本地存储:零配置,一个文件搞定数据库
三、核心原理:300 行代码模拟 Elasticsearch
3.1 整体架构
┌─────────────────┐ HTTP /_bulk ┌─────────────────┐
│ 被监控服务器 │ ──────────────────> │ 监控端电脑 │
│ Winlogbeat │ NDJSON 格式 │ LanMonitor │
│ (采集安全日志) │ │ (弹窗告警) │
└─────────────────┘ └─────────────────┘
原理非常简单:
- 被监控端装 Winlogbeat,配置 output.elasticsearch 指向监控端
- 监控端用 HttpListener 监听 9200 端口,模拟 Elasticsearch
- 收到登录事件后,解析数据,右下角弹窗告警
- 数据存 SQLite,方便历史查询
3.2 模拟 ES Bulk API 有多简单?
核心代码其实只有几十行:
csharp
private async Task ListenLoop(CancellationToken token)
{
while (!token.IsCancellationRequested && _listener.IsListening)
{
var context = await _listener.GetContextAsync();
if (path.EndsWith("/_bulk"))
{
// 解析 NDJSON 格式的批量数据
using var reader = new StreamReader(context.Request.InputStream);
var content = await reader.ReadToEndAsync();
var lines = content.Split('\n');
// 第 1 行是 index 元数据,第 2 行是事件数据
for (int i = 0; i < lines.Length - 1; i += 2)
{
var eventJson = lines[i + 1];
var evt = JsonSerializer.Deserialize<WinlogbeatEvent>(eventJson);
OnLoginEvent?.Invoke(evt); // 触发事件,弹窗告警
}
}
// 返回 ES 标准响应格式
context.Response.StatusCode = 200;
var response = "{\"took\":1,\"errors\":false,\"items\":[]}";
await context.Response.OutputStream.WriteAsync(Encoding.UTF8.GetBytes(response));
context.Response.Close();
}
}
就这么简单!Winlogbeat 以为数据写入了 Elasticsearch,实际上被我们截胡了。
四、功能展示:麻雀虽小,五脏俱全
4.1 实时弹窗告警
有人登录时,右下角立刻弹出告警窗口:
- 红色:登录失败(有人在暴力破解?)
- 橙色:RDP 远程桌面登录
- 蓝色:普通网络登录
弹窗支持置顶、闪烁、声音提醒,想忽略都难。
4.2 多维度搜索筛选
积累了一定数据后,可以按各种维度筛选:
| 筛选维度 | 选项 |
|---|---|
| 关键词 | 主机名 / 用户名 / 来源 IP 模糊搜索 |
| 时间 | 今天 / 昨天 / 近 7 天 / 近 30 天 |
| 事件类型 | 全部 / 登录成功 / 登录失败 |
| 登录类型 | 全部 / RDP / 网络登录 / 其他 |
| 严重程度 | 全部 / 普通 / 警告 / 严重 |
| 读取状态 | 全部 / 未读 / 已读 / 已处理 / 已忽略 |
再也不用去事件查看器里一条条翻了。
4.3 安全加固
企业内网用,安全肯定要考虑:
Token 鉴权:支持 X-Auth-Token 和 Authorization Bearer 两种格式,没有 Token 的请求直接 401 拒绝。
IP 白名单:支持精确 IP、CIDR 网段、通配符三种格式,只允许信任的机器推送数据。
两层防护,足够应对一般的内网场景。
4.4 其他贴心功能
- 配置界面化:5 个 Tab 页,可视化配置所有参数,不用改代码
- 开机自启:注册表实现,开机自动运行
- 数据自动清理:每小时自动清理过期数据,不用担心数据库越来越大
- 告警去重:短时间内相同的告警自动去重,不会被弹窗淹没
- 全局异常捕获:程序出错也不会崩,记录日志继续运行
- 系统托盘:最小化到托盘,不占任务栏空间
五、部署指南:5 分钟搞定
监控端(你的电脑)
- 下载 LanMonitor 程序,直接运行
- 右键托盘 → 设置,配置 Token 和 IP 白名单
- 防火墙放行 9200 端口
被监控端(服务器)
- 下载 Winlogbeat(官方免费)
- 编辑
winlogbeat.yml:
yaml
winlogbeat.event_logs:
- name: Security
event_id: 4624, 4625 # 只采集登录成功/失败事件
ignore_older: 24h # 忽略 24 小时前的历史
output.elasticsearch:
hosts: ["http://监控端IP:9200"]
headers:
X-Auth-Token: "你的Token"
- 安装服务,启动

六、扩展方向:不止是登录监控
现在只做了登录事件监控,但 Winlogbeat 能采集的远不止这些:
安全相关:
- 账户创建/删除/锁定(4720/4726/4740)
- 密码修改(4723/4724)
- 进程创建(4688)------ 可以做进程白名单
- 服务安装(4697)------ 检测恶意服务
- 防火墙规则变更(4946/4947/4948)
- 日志清除(1102)------ 有人删日志?立刻告警
系统相关:
- 系统启动/关闭(6005/6006)
- 服务状态变化(7036)
- Windows 更新(19/20)
进阶玩法:
- 暴力破解检测(1 分钟内失败 N 次告警)
- 异常登录时间检测(凌晨 3 点登录?)
- 异地登录检测(来源 IP 不在白名单)
- Sysmon 集成(更强大的进程/网络/文件监控)
想象空间很大,这只是一个开始。
七、写在最后
做这个项目最大的感受是:很多时候,解决问题不需要复杂的方案,简单的工具反而最实用。
- 不需要 Elasticsearch,不需要 Kafka,不需要各种高大上的中间件
- 一个 几 MB 的 WinForms 程序,加一个官方的 Winlogbeat
- 就能解决内网登录监控这个实实在在的痛点
技术不在于多复杂,而在于能不能解决问题。
如果你也有类似的需求,不妨试试这个工具。也欢迎提 Issue、PR,一起完善它。
项目地址:https://gitee.com/Alexander360/lan-monitor
如果觉得有用,点个 Star 支持一下吧~