Add network activity map overlay and configurable monitoring filters
This commit is contained in:
107
traffic_network_map.go
Normal file
107
traffic_network_map.go
Normal file
@@ -0,0 +1,107 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type NetworkMapPoint struct {
|
||||
Country string `json:"country"`
|
||||
Protocol string `json:"protocol"`
|
||||
Direction string `json:"direction"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
type NetworkMapView struct {
|
||||
At int64 `json:"at"`
|
||||
ReceivedAt int64 `json:"receivedAt"`
|
||||
TCP int `json:"tcp"`
|
||||
UDP int `json:"udp"`
|
||||
ICMP int `json:"icmp"`
|
||||
Unmapped int `json:"unmapped"`
|
||||
MonitoringHidden int `json:"monitoringHidden"`
|
||||
Limited bool `json:"limited"`
|
||||
Error string `json:"error,omitempty"`
|
||||
Points []NetworkMapPoint `json:"points"`
|
||||
}
|
||||
|
||||
func (s *Store) ReadNetworkSnapshot(agent string, rules []MonitoringRule, hide bool) (NetworkSnapshot, error) {
|
||||
var raw, name string
|
||||
err := s.db.QueryRow(`SELECT n.snapshot,a.name FROM network_sources n JOIN agents a ON a.id=n.agent WHERE n.agent=?`, agent).Scan(&raw, &name)
|
||||
if err == sql.ErrNoRows {
|
||||
return NetworkSnapshot{Flows: []NetworkFlow{}, Error: "Ожидание агента v0.21.0 или новее"}, nil
|
||||
}
|
||||
if err != nil {
|
||||
return NetworkSnapshot{}, err
|
||||
}
|
||||
var snapshot NetworkSnapshot
|
||||
if err = json.Unmarshal([]byte(raw), &snapshot); err != nil {
|
||||
return snapshot, err
|
||||
}
|
||||
snapshot.AgentName = name
|
||||
flows := make([]NetworkFlow, 0, len(snapshot.Flows))
|
||||
for _, f := range snapshot.Flows {
|
||||
f.Monitoring = isMonitoringFlow(f, rules)
|
||||
if hide && f.Monitoring {
|
||||
snapshot.MonitoringHidden++
|
||||
continue
|
||||
}
|
||||
flows = append(flows, f)
|
||||
}
|
||||
snapshot.Flows = flows
|
||||
return snapshot, nil
|
||||
}
|
||||
func makeNetworkMap(snapshot NetworkSnapshot, external bool) NetworkMapView {
|
||||
v := NetworkMapView{At: snapshot.At, ReceivedAt: snapshot.ReceivedAt, Limited: snapshot.Limited, Error: snapshot.Error, MonitoringHidden: snapshot.MonitoringHidden, Points: []NetworkMapPoint{}}
|
||||
if snapshot.ParseErrors > 0 {
|
||||
v.Error += fmt.Sprintf(" Нераспознанных строк: %d", snapshot.ParseErrors)
|
||||
}
|
||||
points := map[string]*NetworkMapPoint{}
|
||||
for _, f := range snapshot.Flows {
|
||||
if external && !f.External {
|
||||
continue
|
||||
}
|
||||
protocol := f.Protocol
|
||||
if protocol == "icmpv6" {
|
||||
protocol = "icmp"
|
||||
}
|
||||
switch protocol {
|
||||
case "tcp":
|
||||
v.TCP++
|
||||
case "udp":
|
||||
v.UDP++
|
||||
case "icmp":
|
||||
v.ICMP++
|
||||
}
|
||||
country, direction := f.Country, "in"
|
||||
if !networkExternalIP(f.Source) {
|
||||
if networkExternalIP(f.Destination) {
|
||||
country, direction = f.DestinationCountry, "out"
|
||||
} else {
|
||||
v.Unmapped++
|
||||
continue
|
||||
}
|
||||
}
|
||||
if country == "" || country == "LAN" {
|
||||
v.Unmapped++
|
||||
continue
|
||||
}
|
||||
key := country + "/" + protocol + "/" + direction
|
||||
if points[key] == nil {
|
||||
points[key] = &NetworkMapPoint{Country: country, Protocol: protocol, Direction: direction}
|
||||
}
|
||||
points[key].Count++
|
||||
}
|
||||
for _, p := range points {
|
||||
v.Points = append(v.Points, *p)
|
||||
}
|
||||
sort.Slice(v.Points, func(i, j int) bool {
|
||||
a, b := v.Points[i], v.Points[j]
|
||||
if a.Count != b.Count {
|
||||
return a.Count > b.Count
|
||||
}
|
||||
return a.Country+a.Protocol+a.Direction < b.Country+b.Protocol+b.Direction
|
||||
})
|
||||
return v
|
||||
}
|
||||
Reference in New Issue
Block a user