You've already forked caddy-opnsense-blocker
Build initial caddy-opnsense-blocker daemon
This commit is contained in:
69
internal/engine/evaluator.go
Normal file
69
internal/engine/evaluator.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"git.dern.ovh/infrastructure/caddy-opnsense-blocker/internal/config"
|
||||
"git.dern.ovh/infrastructure/caddy-opnsense-blocker/internal/model"
|
||||
)
|
||||
|
||||
type Evaluator struct{}
|
||||
|
||||
func NewEvaluator() *Evaluator {
|
||||
return &Evaluator{}
|
||||
}
|
||||
|
||||
func (e *Evaluator) Evaluate(record model.AccessLogRecord, profile config.ProfileConfig, override model.ManualOverride) model.Decision {
|
||||
switch override {
|
||||
case model.ManualOverrideForceAllow:
|
||||
return model.Decision{Action: model.DecisionActionAllow, Reasons: []string{"manual_override_force_allow"}}
|
||||
case model.ManualOverrideForceBlock:
|
||||
return model.Decision{Action: model.DecisionActionBlock, Reasons: []string{"manual_override_force_block"}}
|
||||
}
|
||||
|
||||
if record.Status < profile.MinStatus || record.Status > profile.MaxStatus {
|
||||
return model.Decision{Action: model.DecisionActionNone}
|
||||
}
|
||||
|
||||
ip := net.ParseIP(record.ClientIP)
|
||||
if ip == nil {
|
||||
return model.Decision{Action: model.DecisionActionReview, Reasons: []string{"invalid_client_ip"}}
|
||||
}
|
||||
if profile.IsExcluded(ip) {
|
||||
return model.Decision{Action: model.DecisionActionAllow, Reasons: []string{"excluded_cidr"}}
|
||||
}
|
||||
if rule, ok := profile.MatchKnownAgent(ip, record.UserAgent); ok {
|
||||
if rule.Decision == "allow" {
|
||||
return model.Decision{Action: model.DecisionActionAllow, Reasons: []string{fmt.Sprintf("known_agent_allow:%s", rule.Name)}}
|
||||
}
|
||||
return blockDecision(profile.AutoBlock, []string{fmt.Sprintf("known_agent_deny:%s", rule.Name)})
|
||||
}
|
||||
|
||||
blockReasons := make([]string, 0, 3)
|
||||
for _, prefix := range profile.SuspiciousPrefixes() {
|
||||
if strings.HasPrefix(record.Path, prefix) {
|
||||
blockReasons = append(blockReasons, fmt.Sprintf("suspicious_path_prefix:%s", prefix))
|
||||
break
|
||||
}
|
||||
}
|
||||
if profile.BlockUnexpectedPosts && strings.EqualFold(record.Method, "POST") && !profile.IsAllowedPostPath(record.Path) {
|
||||
blockReasons = append(blockReasons, "unexpected_post")
|
||||
}
|
||||
if profile.BlockPHPPaths && strings.HasSuffix(record.Path, ".php") {
|
||||
blockReasons = append(blockReasons, "php_path")
|
||||
}
|
||||
|
||||
return blockDecision(profile.AutoBlock, blockReasons)
|
||||
}
|
||||
|
||||
func blockDecision(autoBlock bool, reasons []string) model.Decision {
|
||||
if len(reasons) == 0 {
|
||||
return model.Decision{Action: model.DecisionActionNone}
|
||||
}
|
||||
if autoBlock {
|
||||
return model.Decision{Action: model.DecisionActionBlock, Reasons: reasons}
|
||||
}
|
||||
return model.Decision{Action: model.DecisionActionReview, Reasons: reasons}
|
||||
}
|
||||
Reference in New Issue
Block a user