Files
ProxmoxDash/traffic_monitoring.go

77 lines
2.3 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 main
import (
"fmt"
"net"
"strings"
)
// Domain/path restrictions describe HTTP probes only. An IP-only rule also
// matches conntrack initiators; a destination match never hides other clients.
type MonitoringRule struct {
IP string `json:"ip"`
Domain string `json:"domain,omitempty"`
PathPrefix string `json:"pathPrefix,omitempty"`
}
func validateMonitoringRules(rules []MonitoringRule) ([]MonitoringRule, error) {
if len(rules) > 32 {
return nil, fmt.Errorf("Не более 32 правил мониторинга")
}
result := make([]MonitoringRule, 0, len(rules))
for i, r := range rules {
ip := net.ParseIP(strings.TrimSpace(r.IP))
if ip == nil {
return nil, fmt.Errorf("Правило %d: нужен точный IPv4/IPv6-адрес", i+1)
}
r.IP = ip.String()
r.Domain = strings.ToLower(strings.TrimSpace(r.Domain))
r.PathPrefix = strings.TrimSpace(r.PathPrefix)
if len(r.Domain) > 253 || strings.ContainsAny(r.Domain, " /|\t\r\n") || len(r.PathPrefix) > 256 || strings.ContainsAny(r.PathPrefix, "|\r\n") || (r.PathPrefix != "" && !strings.HasPrefix(r.PathPrefix, "/")) {
return nil, fmt.Errorf("Правило %d: проверьте домен и префикс пути (начинается с /)", i+1)
}
result = append(result, r)
}
return result, nil
}
func isMonitoringRequest(e TrafficEvent, rules []MonitoringRule) bool {
if e.Kind != "request" {
return false
}
for _, r := range rules {
if e.IP == r.IP && (r.Domain == "" || strings.EqualFold(e.Domain, r.Domain)) && strings.HasPrefix(e.Path, r.PathPrefix) {
return true
}
}
return false
}
func isMonitoringFlow(f NetworkFlow, rules []MonitoringRule) bool {
for _, r := range rules {
if net.ParseIP(f.Source).Equal(net.ParseIP(r.IP)) && r.Domain == "" && r.PathPrefix == "" {
return true
}
}
return false
}
func monitoringSQL(rules []MonitoringRule) (string, []any) {
var parts []string
var args []any
for _, r := range rules {
p := "(ip=?"
args = append(args, r.IP)
if r.Domain != "" {
p += " AND lower(domain)=?"
args = append(args, r.Domain)
}
if r.PathPrefix != "" {
p += " AND substr(path,1,length(?))=?"
args = append(args, r.PathPrefix, r.PathPrefix)
}
parts = append(parts, p+")")
}
if len(parts) == 0 {
return "", nil
}
return " AND NOT (kind='request' AND (" + strings.Join(parts, " OR ") + "))", args
}