sysmonitord/internal/scanner/scanner.go
2026-02-17 10:13:39 +08:00

134 lines
2.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package scanner
import (
"log"
"os"
"path/filepath"
"time"
"github.com/shirou/gopsutil/v4/cpu"
"github.com/wuko233/sysmonitord/internal/network"
"github.com/wuko233/sysmonitord/internal/whitelist"
)
type Scanner struct {
wlManager *whitelist.Manager
client *network.WSClient
cpuLimit float64
scanPaths []string
stopChan chan struct{}
}
func NewScanner(wl *whitelist.Manager, client *network.WSClient) *Scanner {
return &Scanner{
wlManager: wl,
client: client,
cpuLimit: 50.0,
scanPaths: []string{"/bin", "/sbin", "/usr/bin", "/usr/sbin", "/etc", "/tmp", "/home"},
stopChan: make(chan struct{}),
}
}
func (s *Scanner) Start() {
log.Println("[扫描器] 启动文件完整性扫描...")
go s.scanLoop()
}
func (s *Scanner) scanLoop() {
ticker := time.NewTicker(10 * time.Minute)
defer ticker.Stop()
for {
select {
case <-s.stopChan:
return
case <-ticker.C:
s.performScan()
}
}
}
func (s *Scanner) performScan() {
log.Println("[扫描器] 开始新一轮全盘扫描")
fileCount := 0
for _, root := range s.scanPaths {
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
select {
case <-s.stopChan:
return filepath.SkipDir
default:
}
if err != nil {
log.Printf("[扫描器] 访问错误: %v", err)
return nil
}
fileCount++
if fileCount%100 == 0 {
s.checkCPUAndSleep()
}
if info.IsDir() {
if s.wlManager.IsPathIgnored(path) {
return filepath.SkipDir
}
return nil
}
isWhitelisted, isHashMatch, err := s.wlManager.CheckFileStatus(path)
if err != nil {
log.Printf("[扫描器] 检查文件状态失败: %v", err)
return nil
}
if !isWhitelisted {
log.Printf("[扫描器] 发现未在白名单文件: %s", path)
s.reportFile(path, "NON_WHITELISTED_FILE")
} else if !isHashMatch {
log.Printf("[扫描器] 警告文件Hash不匹配(可能被篡改): %s", path)
s.reportFile(path, "FILE_HASH_MISMATCH")
}
return nil
})
if err != nil {
log.Printf("[扫描器] 扫描目录 %s 出错: %v", root, err)
}
}
}
func (s *Scanner) checkCPUAndSleep() {
percent, err := cpu.Percent(200*time.Millisecond, false)
if err != nil || len(percent) == 0 {
log.Printf("[扫描器] 获取CPU使用率失败: %v", err)
return
}
if percent[0] > s.cpuLimit {
log.Printf("[扫描器] CPU使用率过高 (%.2f%%)暂停扫描5秒", percent[0])
time.Sleep(5 * time.Second)
}
time.Sleep(10 * time.Millisecond)
}
func (s *Scanner) reportFile(path string, alertType string) {
payload := map[string]interface{}{
"filepath": path,
"status": "detected",
}
packet := network.NewPactet(alertType, payload)
s.client.SendQueue(packet)
}
func (s *Scanner) Stop() {
log.Println("[扫描器] 停止文件完整性扫描...")
close(s.stopChan)
}