platform: modularize api/gui, add docs-tests-web foundation, and refresh root config
This commit is contained in:
89
selective-vpn-api/app/traffic_audit_checks.go
Normal file
89
selective-vpn-api/app/traffic_audit_checks.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func auditNftAppMarks(state []appMarkItem) (issues []string, summary map[string]any) {
|
||||
summary = map[string]any{
|
||||
"output_jump_ok": false,
|
||||
"output_apps_ok": false,
|
||||
"state_items": len(state),
|
||||
"nft_rules": 0,
|
||||
"missing_rules": 0,
|
||||
"orphan_rules": 0,
|
||||
"missing_rule_ids": []string{},
|
||||
"orphan_rule_ids": []string{},
|
||||
}
|
||||
|
||||
// Check output -> jump output_apps.
|
||||
outOutput, _, codeOut, errOut := runCommandTimeout(3*time.Second, "nft", "list", "chain", "inet", appMarksTable, "output")
|
||||
if errOut != nil || codeOut != 0 {
|
||||
issues = append(issues, "nft_error: failed to read chain output")
|
||||
} else {
|
||||
ok := strings.Contains(outOutput, "jump "+appMarksChain)
|
||||
summary["output_jump_ok"] = ok
|
||||
if !ok {
|
||||
issues = append(issues, "nft_missing_jump: output -> output_apps")
|
||||
}
|
||||
}
|
||||
|
||||
outApps, _, codeApps, errApps := runCommandTimeout(3*time.Second, "nft", "-a", "list", "chain", "inet", appMarksTable, appMarksChain)
|
||||
if errApps != nil || codeApps != 0 {
|
||||
issues = append(issues, "nft_error: failed to read chain output_apps")
|
||||
return issues, summary
|
||||
}
|
||||
summary["output_apps_ok"] = true
|
||||
|
||||
rules := parseAppMarkRules(outApps)
|
||||
summary["nft_rules"] = len(rules)
|
||||
|
||||
stateIDs := map[string]struct{}{}
|
||||
for _, it := range state {
|
||||
tgt := strings.ToLower(strings.TrimSpace(it.Target))
|
||||
if tgt != "vpn" && tgt != "direct" {
|
||||
continue
|
||||
}
|
||||
if it.ID == 0 {
|
||||
continue
|
||||
}
|
||||
stateIDs[fmt.Sprintf("%s:%d", tgt, it.ID)] = struct{}{}
|
||||
}
|
||||
|
||||
ruleIDs := map[string]struct{}{}
|
||||
for _, k := range rules {
|
||||
ruleIDs[k] = struct{}{}
|
||||
}
|
||||
|
||||
missing := []string{}
|
||||
for k := range stateIDs {
|
||||
if _, ok := ruleIDs[k]; !ok {
|
||||
missing = append(missing, k)
|
||||
}
|
||||
}
|
||||
orphan := []string{}
|
||||
for k := range ruleIDs {
|
||||
if _, ok := stateIDs[k]; !ok {
|
||||
orphan = append(orphan, k)
|
||||
}
|
||||
}
|
||||
sort.Strings(missing)
|
||||
sort.Strings(orphan)
|
||||
|
||||
summary["missing_rules"] = len(missing)
|
||||
summary["orphan_rules"] = len(orphan)
|
||||
summary["missing_rule_ids"] = missing
|
||||
summary["orphan_rule_ids"] = orphan
|
||||
|
||||
for _, k := range missing {
|
||||
issues = append(issues, "nft_missing_rule: "+k)
|
||||
}
|
||||
for _, k := range orphan {
|
||||
issues = append(issues, "nft_orphan_rule: "+k)
|
||||
}
|
||||
|
||||
return issues, summary
|
||||
}
|
||||
Reference in New Issue
Block a user