feat(api, web): add Linux nft destination port hits for blocked IPs
Build and Push EvoFirewall Docker Image / build-and-push (push) Successful in 1m59s
Build and Push EvoFirewall Docker Image / create-release (push) Skipped

Track tcp/udp dports via deny_port_hits, expose aggregate and per-IP ports in UI; install-link re-run refreshes nft rules.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Denozordec
2026-08-11 00:33:03 +07:00
co-authored by Cursor
parent 402182195f
commit c5069fbdaf
16 changed files with 897 additions and 30 deletions
+23
View File
@@ -226,6 +226,13 @@ export const applyReportIpHitSchema = z.object({
packets: z.number().int().nonnegative(),
})
export const applyReportPortHitSchema = z.object({
ip: z.string().min(1).max(64),
port: z.number().int().min(1).max(65535),
protocol: z.enum(['tcp', 'udp']),
packets: z.number().int().nonnegative(),
})
export const applyReportBodySchema = z.object({
status: z.string(),
prefix_count: z.number().int().optional(),
@@ -236,6 +243,14 @@ export const applyReportBodySchema = z.object({
source: z.string().optional(),
/** Linux nft/ipset per-element drop counters (top-N, packets > 0). */
ip_hits: z.array(applyReportIpHitSchema).max(200).optional(),
/** Linux nft dynamic set per-(ip, proto, dport) deny hits (top-N). */
port_hits: z.array(applyReportPortHitSchema).max(500).optional(),
})
export const agentIpPortStatSchema = z.object({
port: z.number().int(),
protocol: z.enum(['tcp', 'udp']),
packets: z.number().int(),
})
export const agentIpBlockStatSchema = z.object({
@@ -243,6 +258,14 @@ export const agentIpBlockStatSchema = z.object({
packets: z.number().int(),
first_seen_at: z.string(),
last_seen_at: z.string(),
ports: z.array(agentIpPortStatSchema).optional(),
})
export const agentPortBlockStatSchema = z.object({
port: z.number().int(),
protocol: z.enum(['tcp', 'udp']),
packets: z.number().int(),
last_seen_at: z.string(),
})
export const agentPolicySchema = z.object({