From 622cd80380ec6b2c7e662d148b8a4082e17e1972 Mon Sep 17 00:00:00 2001 From: wuko233 Date: Mon, 16 Feb 2026 23:05:13 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=87=8D=E6=9E=84=E4=B8=BB=E5=87=BD?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/sysmonitord/main.go | 272 ++++++++++++++++++++-------------------- 1 file changed, 137 insertions(+), 135 deletions(-) diff --git a/cmd/sysmonitord/main.go b/cmd/sysmonitord/main.go index 3c029ff..95d4f0d 100644 --- a/cmd/sysmonitord/main.go +++ b/cmd/sysmonitord/main.go @@ -4,153 +4,155 @@ import ( "io" "log" "os" + "os/signal" + "syscall" "time" "github.com/wuko233/sysmonitord/internal/config" "github.com/wuko233/sysmonitord/internal/monitor" + "github.com/wuko233/sysmonitord/internal/network" + "github.com/wuko233/sysmonitord/internal/scanner" + "github.com/wuko233/sysmonitord/internal/whitelist" "gopkg.in/natefinch/lumberjack.v2" ) +const ( + OfficialConfigURL = "http://localhost:8080/api/configs/official.json" + UserConfigURL = "http://localhost:8080/api/configs/user.json" + CenterServerURL = "ws://localhost:8080/ws/monitor" +) + func main() { - // 设置日志输出到文件和控制台 + + initLogger() + log.Println("==========================================") + log.Print(` + _ _ _ + (_) | | | + ___ _ _ ___ _ __ ___ ___ _ __ _| |_ ___ _ __ __| | +/ __| | | / __| '_ ` + "`" + ` _ \ / _ \| '_ \| | __/ _ \| '__/ _` + "`" + ` | +\__ \ |_| \__ \ | | | | | (_) | | | | | || (_) | | | (_| | +|___/\__, |___/_| |_| |_|\___/|_| |_|_|\__\___/|_| \__,_| + __/ | + |___/ +`) + log.Println("==========================================") + + // 加载配置 + log.Println("[启动流程] 1/6: 下载远程安全策略配置...") + cfgLoader := network.NewConfigLoader() + + officialCfg, userCfg, err := cfgLoader.LoadConfigs(network.ConfigUrls{ + OfficialConfigUrl: OfficialConfigURL, + UserConfigUrl: UserConfigURL, + }) + + if err != nil { + log.Fatalf("[启动错误]下载配置失败: %v", err) + log.Println("[启动降级] 继续使用默认空配置...") + // os.Exit(1) + } + + log.Println("[启动流程] 2/6: 初始化白名单判定引擎...") + wlManager := whitelist.NewManager() + wlManager.UpdateConfig(officialCfg, userCfg) + + log.Println("[启动流程] 3/6: 启动中心服务器连接...") + centerClient := network.NewWSClient(network.ClientConfig{ + ServerURL: CenterServerURL, + SendInterval: 1 * time.Second, + BufferSize: 1000, + }) + centerClient.Start() + + auditUrl := wlManager.GetAuditServerUrl() + if auditUrl == "" { + auditUrl = CenterServerURL + } + auditClient := network.NewWSClient(network.ClientConfig{ + ServerURL: auditUrl, + SendInterval: 1 * time.Second, + BufferSize: 1000, + }) + auditClient.Start() + + log.Println("[启动流程] 4/6: 启动文件完整性防护...") + + // 扫盘器 + sysScanner := scanner.NewScanner(wlManager, centerClient) + sysScanner.Start() + + // 监控器 + sysWatcher, err := scanner.NewWatcher(wlManager, centerClient) + if err != nil { + log.Fatalf("[启动错误] 初始化监控器失败: %v", err) + } else { + sysWatcher.Start() + } + + log.Println("[启动流程] 5/6: 启动系统行为监控...") + + // SSH监控 + sshAlertChan := make(chan monitor.Alert, 100) + sshMon := monitor.NewSSHMonitor(&config.SSHMonitor{ + Enabled: true, + AlertOnRootLogin: true, + DisplayOnShell: true, + }, sshAlertChan) + + go func() { + for alert := range sshAlertChan { + packet := network.NewPactet("SSH_ALERT", alert) + auditClient.SendQueue(packet) + } + }() + + go func() { + if err := sshMon.Start(); err != nil { + log.Printf("[监控错误] SSH监控遇到错误: %v", err) + } + }() + + // 状态监控 + metricsChan := make(chan monitor.ServerMetrics, 100) + infoMon := monitor.NewInfoMonitor(nil, metricsChan) + + go func() { + for metrics := range metricsChan { + packet := network.NewPactet("STATUS_UPDATE", metrics) + centerClient.SendQueue(packet) + } + }() + + go infoMon.Start() + + log.Println("[启动流程] 6/6: 系统监控守护进程启动完成!") + + stopChan := make(chan os.Signal, 1) + signal.Notify(stopChan, os.Interrupt, syscall.SIGTERM) + <-stopChan + log.Println("[守护进程] 接收到停止信号,正在关闭...") + + if sysWatcher != nil { + sysWatcher.Stop() + } + sysScanner.Stop() + sshMon.Stop() + infoMon.Stop() + centerClient.Stop() + auditClient.Stop() + log.Println("[守护进程] 已成功停止,安全退出程序。") +} + +func initLogger() { log.SetOutput(os.Stdout) fileLogger := &lumberjack.Logger{ Filename: "/var/log/sysmonitord/sysmonitord.log", - MaxSize: 10, // MB - MaxBackups: 5, - MaxAge: 28, // days + MaxSize: 100, // MB + MaxBackups: 7, + MaxAge: 30, // 天 Compress: true, } + log.SetOutput(io.MultiWriter(os.Stdout, fileLogger)) - - log.Println("启动sysmonitord...") - - // SSH监控配置 - sshCfg := &config.SSHMonitor{ - Enabled: true, - DisplayOnShell: true, - AlertOnRootLogin: true, - } - - // 信息监控配置 - infoCfg := &monitor.InfoMonitorConfig{ - Enabled: true, - Interval: 30 * time.Second, // 每30秒采集一次 - LogFilePath: "/var/log/sysmonitord/info_monitor.log", - MaxLogSize: 100 * 1024 * 1024, // 100MB - LogRetention: 30, // 保留30天 - ProcessLimit: 10, // 显示10个进程 - CollectNetwork: true, - CollectProcess: true, - } - - alertChan := make(chan monitor.Alert, 100) - metricsChan := make(chan monitor.ServerMetrics, 100) - - log.Println("初始化监控器...") - - // 创建SSH监控器 - sshMonitor := monitor.NewSSHMonitor(sshCfg, alertChan) - - // 创建信息监控器 - infoMonitor := monitor.NewInfoMonitor(infoCfg, metricsChan) - - // 启动告警处理 - log.Println("启动告警处理...") - go handleAlerts(alertChan) - - // 启动指标处理 - log.Println("启动指标处理...") - go handleMetrics(metricsChan) - - // 启动SSH监控器 - go func() { - log.Println("启动SSH监控器...") - if err := sshMonitor.Start(); err != nil { - log.Fatalf("启动SSH监控器失败: %v", err) - } - }() - - // 启动信息监控器 - go func() { - log.Println("启动信息监控器...") - if err := infoMonitor.Start(); err != nil { - log.Fatalf("启动信息监控器失败: %v", err) - } - }() - - time.Sleep(3 * time.Second) - - log.Println("sysmonitord监控系统已启动.") - log.Println("按Ctrl+C退出...") - - stopChan := make(chan os.Signal, 1) - - <-stopChan - - log.Println("正在停止监控器...") - - // 停止信息监控器 - if err := infoMonitor.Stop(); err != nil { - log.Printf("停止信息监控器失败: %v", err) - } - - // 停止SSH监控器 - if err := sshMonitor.Stop(); err != nil { - log.Printf("停止SSH监控器失败: %v", err) - } - - time.Sleep(1 * time.Second) - - log.Println("sysmonitord已退出.") -} - -func handleAlerts(alertChan <-chan monitor.Alert) { - for alert := range alertChan { - log.Printf("[告警] 类型: %s | 级别: %s | 时间: %s | 消息: %s | 数据: %+v\n", - alert.Type, alert.Level, alert.Timestamp.Format(time.RFC3339), alert.Message, alert.Data) - - switch alert.Type { - case "SSH_ROOT_LOGIN": - log.Println("ROOT用户登入警告!") - // Todo: 接入发信接口 - } - } -} - -func handleMetrics(metricsChan <-chan monitor.ServerMetrics) { - for metrics := range metricsChan { - // 这里可以处理指标数据,比如: - // 1. 存储到数据库 - // 2. 发送到监控系统 - // 3. 生成告警 - - // 示例:检查指标并生成告警 - checkMetrics(&metrics) - } -} - -func checkMetrics(metrics *monitor.ServerMetrics) { - // 检查CPU使用率 - if metrics.CPU.UsagePercent > 90 { - log.Printf("[警告] CPU使用率过高: %.2f%%\n", metrics.CPU.UsagePercent) - } - - // 检查内存使用率 - if metrics.Memory.UsedPercent > 90 { - log.Printf("[警告] 内存使用率过高: %.2f%%\n", metrics.Memory.UsedPercent) - } - - // 检查磁盘使用率 - for _, disk := range metrics.Disk { - if disk.UsedPercent > 90 { - log.Printf("[警告] 磁盘%s使用率过高: %.2f%%\n", - disk.Mountpoint, disk.UsedPercent) - } - } - - // 检查负载 - if metrics.Load.RelativeLoad1 > 3.0 { - log.Printf("[警告] 系统负载过高: %.2f\n", metrics.Load.Load1) - } }