108 lines
3.1 KiB
Go
108 lines
3.1 KiB
Go
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
|
|
}
|