简介:这份主机安全态势感知系统毕业设计资源,面向计算机相关专业的学生或需要搭建安全监控原型的开发者,围绕实时监控、异常检测与威胁预警展开,帮助理解从数据采集到AI分析落地的完整流程。压缩包共662个文件,大小35.17MB,主体为619个JavaScript文件,用于前端可视化与交互界面,另有15个Python脚本和14个pyc文件对应数据处理、模型训练或后端逻辑,并包含HTML、CSS、JSON及GeoIP等辅助文件,适合直接运行或二次开发。资源中涉及brute_analyse、http_analyse、ssh_analyse等分析模块,结合ECharts图表库可展示主机安全态势,已有145人学习下载。整体来看,这份资源提供了系统源码、分析模块与前端展示框架,可支撑毕业设计中的需求分析、模块设计与功能实现,对希望快速落地安全态势感知项目的读者颇有参考价值。
1. 毕业设计里,主机安全态势感知系统到底要交付什么
主机安全态势感知这个标题,几乎每年都出现在毕业设计选题库里,但真正把压缩包解开之后,能跑的往往只有一张大屏。反直觉的结论是:态势感知系统的核心从来不是可视化,而是数据管线是否完整——从主机上哪一层日志被采集,到日志如何被清洗成统一字段,再到规则引擎如何把孤立告警拼成一条攻击链。这套链路在毕设答辩时可以被拆成几分钟演示,但拆完之后如果接不上真实主机环境,代码就只是静态资源。
这篇文章的服务对象是两类人:一类是拿这个题目写毕设、需要交付一个可运行系统的在校生;另一类是刚接手公司主机安全运营、想用开源组件自建轻量感知平台的运维或安全工程师。下面按数据架构、最小实现、参数调优、验证手法四个层次展开,不依赖任何商业产品,所有命令和代码都按能在一台 8G 内存的机器上复现来设计。
2. 主机安全态势感知的数据架构:从主机日志到攻击场景
2.1 主机层与网络层采集的边界
主机安全态势感知和传统网络安全态势感知的差别在于数据来源。网络层看的是 NetFlow、DNS 解析记录、HTTP 会话,而主机层关注的是进程创建、账号登录、注册表变更、文件系统写入、PowerShell 操作日志。这些数据天然带有“谁在什么时间在哪个主机上干了什么”的上下文,单条日志就足够定位到具体资产。
常见做法是优先覆盖 Windows 和 Linux 两种操作系统的系统日志通道。Windows 侧最低限度要采集 Security 事件日志(登录成功 4624、登录失败 4625、账号枚举 4625 的批量出现)、System 日志以及 PowerShell 的 Operational 日志;Linux 侧至少要覆盖/var/log/secure、/var/log/auth.log、auditd的ausearch结果。在毕设场景里,很多人直接用 SSH 登录日志作为演示数据,这在真实环境里只会暴露出“只有登录分析,没有行为分析”的空洞。
2.1.1 造成“有采集、无感知”的三个设计错误
第一个错误是把所有日志一股脑塞进同一个索引,不区分安全事件日志与应用日志。这会让检索变慢,也会让规则匹配时收到大量噪声。第二个错误是采集频率和存储策略没有设计,日志量大的机器一天产生数 GB 数据,不加冷热分层,Elasticsearch 磁盘很快被打满。第三个错误是忽略日志时间戳的时区差异,Windows 事件日志默认是本地时间,ES 统一按 UTC 存储,如果不在采集端做转换,时间序列分析永远对不上号。
这三类问题的修正方式在后面的实现章节会对应给出。你只要记住一个原则:态势感知系统的第一性原理是“让日志可以被人和规则解释”,而不是“把日志存起来”。
2.2 核心组件选型:Elasticsearch + Logstash + Kafka 的取舍
主机态势感知的数据链路通常可以拆成四层:采集层、传输层、存储检索层、分析展示层。开源方案里最成熟的一套是 Elastic 技术栈,只是中间是否引入 Kafka 取决于规模。毕设或中小规模场景,直接 Filebeat/Winlogbeat 采集后送入 Logstash 做解析,再写入 Elasticsearch,用 Kibana 展示,链路最短,排错最简单;如果主机数量超过 200 台,或者有多个采集端需要缓冲,再加 Kafka 做削峰。
有人问为什么不直接用 ClickHouse 替代 Elasticsearch。ClickHouse 的写入性能和压缩比确实优于 ES,但它的擅长场景是固定维度的大规模聚合统计,对安全分析里高频执行的“按时间窗口 join 多条日志”这类检索需求支持较弱。安全事件关联分析里,日志检索的灵活性比吞吐量更关键。
2.2.1 数据归一化:把不同日志源拉进同一套字段模型
采集层到存储层之间,最容易被忽略的是字段归一化。Windows 安全日志里登录失败的字段名是EventData TargetUserName,Linuxauth.log里同一含义的字段是user。不统一字段名,规则引擎就无法跨源分析,态势感知也就退化成单日志源查询。
业内目前默认的归一化模型是 Elastic Common Schema,也就是 ECS。在实践里不必追求完整规范,只要把几类关键字段对齐即可:user.name、source.ip、host.name、event.category、event.outcome、process.executable、file.path。在 Logstash 的 filter 阶段做字段映射,宁可多写几个 if 分支,也不要放行无结构的原始日志。
3. 用最小代码跑通“采集-存储-检测-展示”闭环
3.1 用 Winlogbeat 把 Windows 安全日志送进 Elasticsearch
在 Windows 主机上部署 Winlogbeat 是采集安全日志的关键步骤。解压压缩包后使用winlogbeat.yml作为配置文件。下面是一个最小可用的采集配置,适用于单机实验环境:
winlogbeat.event_logs: - name: Security ignore_older: 72h event_id: 4624,4625,4634,4672,4720,4728,4732 - name: System ignore_older: 72h output.elasticsearch: hosts: ["192.168.1.10:9200"] index: "win-security-%{+yyyy.MM.dd}" setup.template.name: "win-security" setup.template.pattern: "win-security-*"上述配置只采集了安全日志中的登录成功、登录失败、账号变更事件,并限制只保留最近 72 小时的数据。其中event_id参数决定了哪些日志能进入存储,而不是全量收进来。按照这个配置,单台 Windows 主机的 ES 日均写入量可以控制在 100MB 以内,适合毕设环境的磁盘容量。
参数说明:ignore_older控制忽略超过 3 天的旧日志,避免首次启动时把历史日志全部灌入 ES;setup.template.pattern指定索引模板的匹配规则,后续 ILM 生命周期策略要跟这个 pattern 对应。启动命令是.\winlogbeat.exe -c winlogbeat.yml -e,如果采集端与 ES 之间网络不通,错误信息会直接打印在标准输出上,先排查 hosts 地址与防火墙策略。
3.2 用 Python 对 ES 数据做攻击链规则匹配
日志落在 ES 之后,下一步是从原始登录事件中提取攻击意图。一个经典的暴力破解场景是“短时间内多次登录失败,随后偶发一次登录成功”。直接用 ES Query DSL 也能实现,但把规则写在 Python 里更容易调试和扩展。使用 Elasticsearch 官方客户端库写一个基于滑动窗口的检测器:
from elasticsearch import Elasticsearch from datetime import datetime, timedelta es = Elasticsearch(["http://192.168.1.10:9200"]) window_minutes = 5 fail_threshold = 5 query = { "query": { "bool": { "filter": [ {"range": {"@timestamp": { "gte": f"now-{window_minutes}m"}}}, {"term": {"event.code": "4625"}} ] } }, "aggs": { "by_source": { "terms": {"field": "source.ip", "size": 20}, "aggs": { "success_after": { "filter": {"term": {"event.code": "4624"}} } } } } } result = es.search(index="win-security-*", body=query) for bucket in result["aggregations"]["by_source"]["buckets"]: if bucket["doc_count"] >= fail_threshold: print(f"检测到疑似暴力破解: {bucket['key']} 失败次数 {bucket['doc_count']}")这段代码的逻辑是:先聚合最近 5 分钟内所有登录失败事件,按来源 IP 分组;然后嵌套一个过滤聚合,统计同一来源 IP 是否在同一时间产生了登录成功事件。如果失败次数达到阈值,直接把来源 IP 和大致时间范围打印出来。event.code是 Winlogbeat 写入 ES 时的默认字段名,如果自己用 Logstash 解析原始消息,需要先确认字段名是否一致再套用这段代码。
3.3 用 Grafana 查询语句呈现态势面板
展示层仍然沿用 ELK 生态的 Kibana 也行,但 Grafana 对时序数据的可视化更灵活。在 Grafana 里添加 Elasticsearch 数据源后,用以下查询语句可以画出攻击来源地理分布或趋势图:
{ "bucket_aggregation": "terms", "field": "source.ip", "size": 10, "time_field": "@timestamp" }这段配置对应 Grafana 可视化面板中的 Bucket 聚合设置,按source.ip分组统计。注意 Grafana 的 ES 数据源不推荐在查询语句里写死索引名,而是通过 Index Settings 里的win-security-*模式自动匹配每天的新索引。这样展示出来的趋势图才会按天滚动。
在实现最小闭环时,先不要追求复杂的关联规则。把采集、存储、单条检索、按 IP 聚合这四个动作跑通,就已经完成了整个系统 60% 的工作量。
4. 部署调优:5 个关键参数与主机痕迹排查路径
4.1 影响检测准确率的 5 个核心参数
推动系统上线时,最影响检测效果的是以下 5 个参数,它们分布在 ES 配置和规则引擎两层。下表给出推荐值和调整理由:
| 参数 | 推荐值 | 调整理由 |
|---|---|---|
indices.query.bool.max_clause_count | 2048 | 规则数量增多时,ES 默认 1024 的限制会导致查询报错 |
xpack.monitoring.collection.enabled | true | 不开启监控,ES 本身的 CPU 和磁盘异常无法预先发现 |
| 暴力破解失败次数阈值 | 5 次/5 分钟 | 阈值设太低会产生大量误报,设太高则漏报明显 |
| 日志保留周期 | 30 天 | 超过 30 天的历史数据对实时感知无意义,建议冷存 |
| 告警去重窗口 | 10 分钟 | 同一个来源 IP 触发多条规则时,只发送一次告警 |
indices.query.bool.max_clause_count这个参数需要配置在 ES 的elasticsearch.yml文件里,修改后要重启节点。毕设环境往往不重视这个参数,但当你在 Python 里写下包含几十个 should 条件的大查询时,ES 会直接返回 400 错误,报错信息里会明确提示 clause 数超限。
4.2 安全事件处置中的主机痕迹排查路径
当检测规则命中主机后,需要进入安全事件处置阶段。这个阶段在 Windows 主机上排查痕迹时,有几个固定路径必须检查:Windows 事件日志的Microsoft-Windows-PowerShell/Operational路径,记录了所有 PowerShell 命令的历史;C:\Windows\Prefetch目录下能看到程序运行痕迹;用户目录下的AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt保存了交互式命令历史。
直接用命令行查看关键日志:
wevtutil qe Microsoft-Windows-PowerShell/Operational /c:50 /rd:true /f:text这条命令读取最近 50 条 PowerShell 操作日志,/rd:true表示按时间倒序排列。wevtutil比 PowerShell 的Get-WinEvent更快,适合在事件响应时快速拉取。
除了系统日志,还要检查主机上可疑的压缩包文件。攻击者往往会把窃取的数据打包后外传,所以排查阶段要看最近修改时间在攻击时间窗口内的.zip文件:
where /R C:\Users\*.zip /T /Q这条命令递归显示对应用户目录下所有 zip 文件的路径、修改时间和只读属性。遇到加密的 zip 包,直接记录文件名和哈希即可,不要浪费时间做密码恢复。取证的第一原则是保证证据不被破坏,而不是解出内容。
4.3 感知系统自身的访问控制
部署 ES 的机器往往会被当成“后台服务器”随意开放端口。这里要强调,ES 的 9200 端口一旦对公网开放,等于把检测系统的规则和数据源全部暴露。最有效的控制手段是在防火墙只允许 Grafana 所在内网 IP 访问 9200 端口,同时开启 ES 自带的xpack.security.enabled: true配置:
xpack.security.enabled: true xpack.security.transport.ssl.enabled: true开启后需要执行elasticsearch-setup-passwords interactive为内置账号设置密码。毕设环境可能觉得这步麻烦,但在真实业务场景中,未授权访问 ES 并删除索引仍然是排名靠前的安全事件。写入侧如果使用 Logstash 采集主机日志,需要在输出配置里增加user => "elastic"和password => "..."参数,否则采集端在认证开启后无法连接。
5. 用攻击回放验证系统不是“演示即废”
5.1 用脚本模拟真实攻击序列,验证检测命中
搭建完整个系统后,最有效的验证方式是主动回放攻击。在一台测试主机上用 Python 循环伪造登录失败日志:
import win32security import win32api import time for i in range(10): try: win32security.LogonUser("admin", None, "WrongPass123", win32security.LOGON32_LOGON_INTERACTIVE, win32security.LOGON32_PROVIDER_DEFAULT) except Exception as e: pass time.sleep(1)这段代码用错误密码连续尝试登录 10 次,每次间隔 1 秒。如果前面实现的检测器正常工作,应当在这 10 次失败之后的 1 分钟内查询到告警。验证时要注意测试机器不能加入真实域,否则会触发域控账号锁定策略,影响同网段其他用户。
5.2 三个最容易翻车的点与对应排查命令
第一个翻车点是采集端时区不一致导致告警时间漂移。排查命令是在 ES 里直接执行:
GET win-security-*/_search { "sort": [{"@timestamp": "desc"}], "size": 1 }如果最新一条日志的@timestamp与当前时间相差超过 8 小时,说明 Winlogbeat 没有正确设置时区,需要在配置文件的processor阶段显式指定timezone: Asia/Shanghai。
第二个问题是磁盘水印策略导致 ES 写入阻塞。默认在磁盘使用率超过 85% 时会停止分配分片,表现为日志索引不再增长。解决办法是执行:
curl -X PUT "localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d '{"transient":{"cluster.routing.allocation.disk.watermark.flood_stage":"95%"}}'第三个问题是规则引擎的误报全被当成真实攻击。排查方式是先以 24 小时为粒度回看告警数量,如果告警量超过 200 条,优先检查event.code: 4625是否来自同一个服务账号的周期性探测。建议先把来自内网监控系统的 IP 段加入白名单,再逐步收敛规则。
5.3 把单条告警升级为影响面分析的技巧
常规检测器输出的是“某 IP 对某主机发起暴力破解”,但答辩或真实处置时,更有价值的是“该攻击者触达了哪些主机”。可以在 ES 里按source.ip聚合去重后的host.name数量:
{ "aggs": { "affected_hosts": { "cardinality": {"field": "host.name"} } } }这段查询返回受影响的独立主机数,把单条告警从“点”升维到“面”。把这个指标直接放到态势感知大屏的顶部位置,比显示日志总量更能体现“感知”两个字的意义。
本文还有配套的精品资源,点击获取