Initial commit
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
package analyzer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"dip-ids/internal/config"
|
||||
"dip-ids/internal/storage"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
)
|
||||
|
||||
// arpSpoofDetector обнаруживает ARP-спуфинг.
|
||||
// Алгоритм: ведёт таблицу соответствия IP→MAC; при обнаружении
|
||||
// нового MAC для уже известного IP генерирует алерт.
|
||||
type arpSpoofDetector struct {
|
||||
mu sync.Mutex
|
||||
cfg config.ARPSpoofConfig
|
||||
ipToMAC map[string]string // IP -> MAC
|
||||
alerted map[string]time.Time
|
||||
}
|
||||
|
||||
func NewARPSpoofDetector(cfg config.ARPSpoofConfig) Detector {
|
||||
return &arpSpoofDetector{
|
||||
cfg: cfg,
|
||||
ipToMAC: make(map[string]string),
|
||||
alerted: make(map[string]time.Time),
|
||||
}
|
||||
}
|
||||
|
||||
func (d *arpSpoofDetector) Name() string { return "arp_spoof" }
|
||||
|
||||
func (d *arpSpoofDetector) Analyze(pkt gopacket.Packet) []storage.Alert {
|
||||
if !d.cfg.Enabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
arpLayer := pkt.Layer(layers.LayerTypeARP)
|
||||
if arpLayer == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
arp := arpLayer.(*layers.ARP)
|
||||
// Обрабатываем только ARP Reply (op=2) и Gratuitous ARP
|
||||
if arp.Operation != layers.ARPReply {
|
||||
return nil
|
||||
}
|
||||
|
||||
srcIP := fmt.Sprintf("%d.%d.%d.%d", arp.SourceProtAddress[0], arp.SourceProtAddress[1],
|
||||
arp.SourceProtAddress[2], arp.SourceProtAddress[3])
|
||||
srcMAC := fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
arp.SourceHwAddress[0], arp.SourceHwAddress[1], arp.SourceHwAddress[2],
|
||||
arp.SourceHwAddress[3], arp.SourceHwAddress[4], arp.SourceHwAddress[5])
|
||||
|
||||
now := pkt.Metadata().Timestamp
|
||||
if now.IsZero() {
|
||||
now = time.Now()
|
||||
}
|
||||
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
knownMAC, exists := d.ipToMAC[srcIP]
|
||||
if !exists {
|
||||
d.ipToMAC[srcIP] = srcMAC
|
||||
return nil
|
||||
}
|
||||
|
||||
if knownMAC == srcMAC {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MAC изменился — ARP спуфинг
|
||||
key := srcIP
|
||||
if last, ok := d.alerted[key]; ok && now.Sub(last) < 60*time.Second {
|
||||
return nil
|
||||
}
|
||||
d.alerted[key] = now
|
||||
|
||||
// Обновляем таблицу
|
||||
d.ipToMAC[srcIP] = srcMAC
|
||||
|
||||
return []storage.Alert{{
|
||||
CreatedAt: now,
|
||||
Type: "arp_spoof",
|
||||
Severity: d.cfg.Severity,
|
||||
SrcIP: srcIP,
|
||||
Protocol: "ARP",
|
||||
Description: fmt.Sprintf("ARP spoofing: IP %s changed MAC from %s to %s", srcIP, knownMAC, srcMAC),
|
||||
Count: 1,
|
||||
}}
|
||||
}
|
||||
|
||||
func (d *arpSpoofDetector) Reset() {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
d.ipToMAC = make(map[string]string)
|
||||
d.alerted = make(map[string]time.Time)
|
||||
}
|
||||
Reference in New Issue
Block a user