简介:这份毕业设计资源聚焦主机安全态势感知系统的完整实现,面向网络安全、计算机相关专业的学生及课程设计开发者,帮助解决从数据采集到威胁响应的全流程落地问题。压缩包共662个文件,约35.19MB,以619个JavaScript文件为主,配合15个Python脚本、14个pyc编译文件及少量txt、html、json、css等,另有mmdb地理库与brute_analyse、http_analyse、ssh_analyse等分析模块,整体呈现前端可视化与后端分析并重的结构。项目围绕数据收集、数据分析、威胁检测、可视化展示与响应策略五个环节展开,Python侧可借助Pandas、Scikit-learn等完成异常检测与行为建模,前端则通过ECharts等图表库呈现安全态势仪表盘。已有282人学习关注,适合需要完整毕设方案、模块划分参考与排错思路的读者,可据此快速理解系统架构并复现关键功能。
1. 主机安全态势感知系统拆包:从日志到世界地图的完整链路
拿到一个名为“毕业设计 主机安全态势感知系统.zip”的压缩包,多数人的第一反应是“能不能跑起来、跑起来长什么样”。我拆过不少同类毕设,这个包的结构有点意思:brute_analyse、http_analyse两个分析脚本,scb.css和base.html撑起前端骨架,echarts.min.js、echarts-gl.min.js负责图表渲染,再加上Russia.js、Canada.js、jiang1_xi1_gan4_zhou1.js这几个地名脚本——基本可以断定,这是一个把主机日志里的攻击源投射到世界地图和国内省份地图上的可视化系统。它解决的核心问题是:把零散的 SSH 爆破、HTTP 异常请求日志,变成一眼能看懂的地理分布态势。适合正在做网络安全方向毕设、课程设计,或者想快速搭一个安全监控原型的同学。你不需要从零写 ECharts 配置,也不用纠结地图 JSON 怎么注册,这套代码已经把“日志解析→攻击源统计→地图渲染”的链路串好了。
2. 日志解析与攻击源提取:brute_analyse 和 http_analyse 怎么改
2.1 两个分析脚本的分工与输入格式
brute_analyse和http_analyse是整个系统的数据入口。从命名看,前者处理暴力破解类日志,后者处理 HTTP 请求日志。常见做法是:brute_analyse读取类似/var/log/auth.log或/var/log/secure的 SSH 登录失败记录,用正则提取 IP、时间戳、尝试用户名;http_analyse则解析 Nginx 或 Apache 的access.log,抓取状态码、请求路径、User-Agent,识别扫描器或异常高频访问。
我一般会先确认脚本里的正则能不能匹配你手头的日志格式。不同发行版的 auth.log 差异很大,Ubuntu 的Failed password for invalid user admin from 1.2.3.4和 CentOS 的Failed password for root from 1.2.3.4 port 22 ssh2提取逻辑就不一样。打开brute_analyse,找到类似下面的正则:
import re # 匹配 SSH 失败登录,提取 IP 和用户名 pattern = r'Failed password for (?:invalid user )?(\S+) from (\d+\.\d+\.\d+\.\d+)' with open('/var/log/auth.log', 'r', encoding='utf-8', errors='ignore') as f: for line in f: match = re.search(pattern, line) if match: username, ip = match.groups() # 后续写入统计字典或数据库这段代码的逻辑很直白:逐行扫描日志,用非捕获组(?:invalid user )?兼容“无效用户”和“有效用户”两种失败提示,最终拿到用户名和 IP。参数上唯一需要动的是文件路径和正则本身。如果你的日志里 IP 出现在from之前,或者有 IPv6,就得改\d+\.\d+\.\d+\.\d+这段。http_analyse同理,重点看它提取的是$remote_addr还是$http_x_forwarded_for,后者在套了 CDN 的场景下更准,但容易被伪造。
2.2 把分析结果转成地图能吃的 JSON
ECharts 地图系列需要的数据格式是[{name: 'Russia', value: 123}, ...]。Russia.js、Canada.js这些文件大概率是地图的 GeoJSON 注册脚本,而jiang1_xi1_gan4_zhou1.js看拼音是“江西赣州”,说明系统还做了国内省市下钻。分析脚本跑完后,不能直接扔给前端,中间得有一次聚合。
常见做法是在brute_analyse末尾加一段聚合逻辑,按国家或省份统计攻击次数,输出 JSON 文件供前端fetch或直接写成 JS 变量。比如:
import json from collections import Counter # 假设 ip_count 是 {ip: 次数} 的字典 # 这里需要 IP 转国家的库,常见用 geoip2 或纯真 IP 库 import geoip2.database reader = geoip2.database.Reader('GeoLite2-Country.mmdb') country_counter = Counter() for ip, count in ip_count.items(): try: response = reader.country(ip) country = response.country.name country_counter[country] += count except Exception: country_counter['Unknown'] += count # 输出成 ECharts 地图需要的格式 result = [{'name': k, 'value': v} for k, v in country_counter.items()] with open('static/attack_map.json', 'w') as f: json.dump(result, f)这段代码的关键参数是GeoLite2-Country.mmdb的路径,MaxMind 的免费库需要自己下载并定期更新,否则新 IP 段会落到 Unknown。另一个坑是国家名称必须和Russia.js里注册的name完全一致,比如“United States”不能写成“USA”,否则地图上不会着色。如果你不想引入 geoip2,也可以用在线 API,但毕设环境通常离线,本地库更稳。
2.3 前端如何消费这些数据
base.html里应该有一个<div id="map">容器,echarts.init之后通过series的map类型加载。echarts-gl.min.js的存在说明可能还做了 3D 地球或立体柱状图。你需要在base.html里确认地图注册的顺序:先加载Russia.js这类地理数据脚本,再执行echarts.registerMap('Russia', geoJson),最后setOption。如果顺序反了,控制台会报Map russia not exists。数据更新频率取决于你的日志量,毕设演示时手动跑一次分析脚本、刷新页面即可;想做得像实时系统,可以加个setInterval每 30 秒重新拉取 JSON,但要注意浏览器缓存,加时间戳参数最省事。
3. 可视化地图与 ECharts 配置:地名脚本和 3D 渲染的配合
3.1 Russia.js、Canada.js 与 echarts-gl 的加载顺序
Russia.js和Canada.js不是普通的工具库,它们内部通常是echarts.registerMap('Russia', {...})的调用。这意味着它们必须在echarts.min.js之后加载,否则echarts全局变量还不存在。我见过不少毕设把顺序写反,结果地图一片空白,控制台只报一句echarts is not defined,排查半天。
正确的<script>顺序是:
<script src="static/js/echarts.min.js"></script> <script src="static/js/echarts-gl.min.js"></script> <script src="static/js/Russia.js"></script> <script src="static/js/Canada.js"></script> <script src="static/js/jiang1_xi1_gan4_zhou1.js"></script> <script src="static/js/main.js"></script>echarts-gl要在echarts之后、地图脚本之前,因为它扩展了echarts的 3D 系列类型。main.js是你自己写的初始化逻辑,放最后。如果你只做 2D 地图,echarts-gl可以去掉,但既然包里带了,大概率有 3D 柱状图或地球模式,去掉会报series-globe not found。
3.2 地图 series 的核心参数怎么调
ECharts 地图的series配置里,map字段决定用哪张地图,data是前面聚合好的数组。常见配置如下:
option = { tooltip: { trigger: 'item', formatter: '{b}: {c} 次攻击' }, visualMap: { min: 0, max: 100, left: 'left', top: 'bottom', text: ['高', '低'], calculable: true, inRange: { color: ['#e0f3f8', '#ffffbf', '#fee090', '#fdae61', '#f46d43', '#d73027'] } }, series: [{ name: '攻击来源', type: 'map', map: 'Russia', roam: true, emphasis: { label: { show: true } }, data: attackData }] };visualMap的max要根据你的实际攻击次数调整。如果最大攻击次数是 5000,max还写 100,那所有国家都会显示成最深红色,失去区分度。我一般会先跑一遍分析脚本,看value的最大值,再动态设置max。roam: true允许鼠标缩放拖拽,演示时比较方便。emphasis.label.show控制悬停是否显示国家名,如果地图太密可以关掉,靠 tooltip 就够了。
3.3 国内省份下钻:jiang1_xi1_gan4_zhou1.js 的用法
jiang1_xi1_gan4_zhou1.js这个文件名很直白:江西赣州。说明系统支持从全国地图点进去看某个市的数据。实现方式通常是监听地图的click事件,拿到省份名后动态加载对应的市级别 GeoJSON,再registerMap一次。
myChart.on('click', function (params) { if (params.name === '江西') { // 加载赣州市地图数据 fetch('static/js/jiang1_xi1_gan4_zhou1.js') .then(response => response.text()) .then(text => { // 假设文件内容是 echarts.registerMap('赣州', {...}) eval(text); myChart.setOption({ series: [{ map: '赣州', data: cityData }] }); }); } });这里用eval是因为jiang1_xi1_gan4_zhou1.js本身就是一段可执行脚本,直接eval最省事。但生产环境不建议这么干,毕设演示无所谓。注意cityData需要你提前按赣州的区县聚合好,否则下钻后地图没颜色。如果点击其他省份没反应,检查params.name是否和registerMap时的名称一致,ECharts 对中文名称很敏感,“江西”和“江西省”是两个不同的 key。
4. 避坑与排查:日志格式、地图空白、跨域与性能
4.1 日志格式不匹配导致分析结果为空
现象:跑完brute_analyse,输出的 JSON 是空数组,地图上没有任何颜色。原因:脚本里的正则只匹配了某一种日志格式,而你手头的/var/log/auth.log来自不同发行版或不同 SSH 配置。比如日志里写的是Failed password for root from 192.168.1.1,但正则要求from后面必须跟port,就会漏掉。解决:先head -20 /var/log/auth.log看实际格式,再改正则。建议把正则写成可配置的,或者用grep -oP先手动验证一遍。另一个常见原因是日志文件权限不够,Python 脚本读不到,加sudo或把用户加入adm组。
4.2 地图空白但控制台无报错
现象:页面其他图表正常,只有地图区域是空白,控制台没有红色错误。原因:地图注册的名称和series.map的值不一致。比如Russia.js里注册的是echarts.registerMap('russia', ...),小写 r,而series.map写的是'Russia',ECharts 找不到就静默失败。解决:打开Russia.js,搜索registerMap,看第一个参数的确切字符串。然后统一series.map的大小写。国内地图同理,'china'和'China'不通用。
4.3 跨域请求 JSON 被浏览器拦截
现象:用fetch('static/attack_map.json')时控制台报CORS policy: Cross origin requests are only supported for protocol schemes: http, data, ...。原因:直接双击打开base.html,浏览器用的是file://协议,fetch本地文件会被安全策略拦截。解决:起一个本地 HTTP 服务,Python 自带的最方便:python -m http.server 8000,然后访问http://localhost:8000/base.html。Flask 项目的话直接flask run就行。别用file://调试,这是血泪经验。
4.4 攻击次数过多导致地图渲染卡顿
现象:日志量大了之后,地图加载要好几秒,鼠标悬停卡顿。原因:data数组里包含了大量value为 0 的国家,ECharts 仍然会遍历渲染。或者visualMap的max设得过大,颜色计算开销增加。解决:在 Python 聚合阶段过滤掉value == 0的条目,只保留有攻击记录的国家。visualMap.max用实际最大值,不要拍脑袋写 10000。如果还卡,把roam关掉,减少交互计算。
4.5 3D 地球模式在低配电脑上崩溃
现象:启用echarts-gl的globe系列后,页面直接白屏或浏览器提示“网页无响应”。原因:3D 渲染依赖 WebGL,部分集成显卡或旧驱动不支持,或者显存不足。解决:在main.js里加一个 WebGL 检测,不支持就降级到 2D 地图。检测代码很简单:
function hasWebGL() { try { var canvas = document.createElement('canvas'); return !!(window.WebGLRenderingContext && (canvas.getContext('webgl') || canvas.getContext('experimental-webgl'))); } catch (e) { return false; } }如果hasWebGL()返回 false,就只初始化 2D 的map系列,别碰globe。毕设答辩的电脑不一定是你自己的,这个降级逻辑能救场。
5. 从毕设到可演示系统:数据刷新、地图下钻与答辩技巧
把系统跑起来只是第一步,答辩时老师大概率会问“数据是实时的吗”“能不能看某个省的细节”“攻击次数怎么统计的”。这一章说几个能让演示效果上一个台阶的具体技巧。
数据刷新不用真做实时,但要有刷新入口。在页面右上角加一个“重新分析”按钮,点击后触发后端重新跑brute_analyse和http_analyse,然后前端重新fetchJSON。后端可以用 Flask 写一个/refresh路由:
from flask import Flask, jsonify import subprocess app = Flask(__name__) @app.route('/refresh') def refresh(): # 依次执行两个分析脚本 subprocess.run(['python', 'brute_analyse.py'], check=True) subprocess.run(['python', 'http_analyse.py'], check=True) return jsonify({'status': 'ok'})前端按钮绑定fetch('/refresh').then(() => location.reload())。这样演示时你点一下按钮,地图颜色变了,老师会觉得“有交互”。注意subprocess.run的check=True会在脚本报错时抛异常,最好加try/except返回错误信息,别让页面直接 500。
地图下钻不要只做一个市。jiang1_xi1_gan4_zhou1.js只有赣州,但你可以用同样的方式补几个热门省份的市级地图。ECharts 官方地图数据或者阿里云 DataV 都能下载到各省的 GeoJSON,转成registerMap脚本就行。下钻的交互逻辑参考第 3 章的click事件,但记得加一个“返回全国”的按钮,否则用户点进去出不来。返回时重新setOption把map切回'china'或'Russia',数据用全国聚合的那份。
攻击次数统计要能解释清楚。老师问“这个 500 次是怎么算的”,你得答上来:是 SSH 失败登录次数,还是 HTTP 404 次数,还是两者相加。建议在brute_analyse和http_analyse里分别输出两个 JSON,前端用两个地图或一个地图两种颜色叠加。如果混在一起,至少要在 tooltip 里区分brute和http的数值。我一般会在聚合时保留一个detail字段:
result = [{'name': country, 'value': total, 'brute': brute_count, 'http': http_count}]ECharts 的 tooltipformatter可以写成'{b}: 总计 {c} 次(爆破 {d0},HTTP {d1})',但d0、d1需要series里额外配置,简单点直接用params.data.brute拼字符串。
答辩前强制走一遍完整流程。从那以后我每次交付这类系统,都会在答辩前一天做一次“冷启动测试”:清空所有生成的 JSON,重启服务,从日志文件开始跑分析脚本,再打开页面看地图是否正常渲染。这一步能暴露 90% 的路径问题和权限问题。另外,把GeoLite2-Country.mmdb和地图 JS 文件一起打包进 zip,别让老师自己下载,离线环境你没法解释。
希望帮到你。
本文还有配套的精品资源,点击获取