Compare commits

...

2 Commits

Author SHA1 Message Date
Marco Lanzara
89a531eec4 🚀 Release v1.0.107
- Tipo: patch
- Database schema: database-schema/schema.sql (solo struttura)
- Data: 2026-02-14 10:15:20
2026-02-14 10:15:20 +00:00
marco370
255444d2dd Add ability to mass block critical IP addresses from the system
Add a new endpoint to the ML backend to block all critical IPs and an API route to trigger it from the server.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 685ee18c-cd9c-4b9a-8cb1-70c4b25db835
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/18EyBWl
2026-02-14 10:15:07 +00:00
4 changed files with 138 additions and 10 deletions

View File

@ -2,7 +2,7 @@
-- PostgreSQL database dump -- PostgreSQL database dump
-- --
\restrict zQNR3d1f0L7BheutpfeBwyF7BjurD3GAqhrSEQdUccum6NzNnt3IiQ7Hh7Nri9q \restrict VfY2jMibUtM7epqSxI0eI9IK5petlVg4wE8lvRgi6qIK19f865uN5QWYQxOQJY8
-- Dumped from database version 16.11 (df20cf9) -- Dumped from database version 16.11 (df20cf9)
-- Dumped by pg_dump version 16.10 -- Dumped by pg_dump version 16.10
@ -387,5 +387,5 @@ ALTER TABLE ONLY public.public_blacklist_ips
-- PostgreSQL database dump complete -- PostgreSQL database dump complete
-- --
\unrestrict zQNR3d1f0L7BheutpfeBwyF7BjurD3GAqhrSEQdUccum6NzNnt3IiQ7Hh7Nri9q \unrestrict VfY2jMibUtM7epqSxI0eI9IK5petlVg4wE8lvRgi6qIK19f865uN5QWYQxOQJY8

View File

@ -111,6 +111,10 @@ class UnblockIPRequest(BaseModel):
ip_address: str ip_address: str
list_name: str = "ddos_blocked" list_name: str = "ddos_blocked"
class BlockAllCriticalRequest(BaseModel):
min_score: float = 80.0
list_name: str = "ddos_blocked"
# API Endpoints # API Endpoints
@ -499,6 +503,94 @@ async def block_ip(request: BlockIPRequest):
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e))
@app.post("/block-all-critical")
async def block_all_critical(request: BlockAllCriticalRequest):
"""Blocca tutti gli IP critici non ancora bloccati sui router"""
try:
conn = get_db_connection()
cursor = conn.cursor(cursor_factory=RealDictCursor)
cursor.execute("SELECT * FROM routers WHERE enabled = true")
routers = cursor.fetchall()
if not routers:
raise HTTPException(status_code=400, detail="Nessun router configurato")
cursor.execute("""
SELECT DISTINCT source_ip, MAX(CAST(risk_score AS FLOAT)) as max_score,
MAX(anomaly_type) as anomaly_type
FROM detections
WHERE CAST(risk_score AS FLOAT) >= %s
AND blocked = false
AND source_ip NOT IN (
SELECT ip_address FROM whitelist WHERE active = true
)
GROUP BY source_ip
ORDER BY max_score DESC
""", (request.min_score,))
unblocked_ips = cursor.fetchall()
if not unblocked_ips:
cursor.close()
conn.close()
return {
"message": "Nessun IP critico da bloccare",
"blocked": 0,
"total_critical": 0,
"skipped_whitelisted": 0
}
blocked_count = 0
failed_count = 0
results_detail = []
for ip_row in unblocked_ips:
ip = ip_row['source_ip']
score = ip_row['max_score']
anomaly = ip_row['anomaly_type']
try:
block_results = await mikrotik_manager.block_ip_on_all_routers(
routers,
ip,
list_name=request.list_name,
comment=f"IDS bulk-block: {anomaly} (score: {score:.0f})"
)
if any(block_results.values()):
cursor.execute("""
UPDATE detections
SET blocked = true, blocked_at = NOW()
WHERE source_ip = %s AND blocked = false
""", (ip,))
blocked_count += 1
results_detail.append({"ip": ip, "score": score, "status": "blocked"})
else:
failed_count += 1
results_detail.append({"ip": ip, "score": score, "status": "failed"})
except Exception as e:
failed_count += 1
results_detail.append({"ip": ip, "score": score, "status": f"error: {str(e)}"})
conn.commit()
cursor.close()
conn.close()
return {
"message": f"Blocco massivo completato: {blocked_count} IP bloccati, {failed_count} falliti",
"blocked": blocked_count,
"failed": failed_count,
"total_critical": len(unblocked_ips),
"details": results_detail[:50]
}
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.post("/unblock-ip") @app.post("/unblock-ip")
async def unblock_ip(request: UnblockIPRequest): async def unblock_ip(request: UnblockIPRequest):
"""Sblocca un IP da tutti i router""" """Sblocca un IP da tutti i router"""

View File

@ -622,6 +622,42 @@ export async function registerRoutes(app: Express): Promise<Server> {
} }
}); });
app.post("/api/ml/block-all-critical", async (req, res) => {
try {
const { min_score = 80 } = req.body;
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 300000); // 5 min timeout
const response = await fetch(`${ML_BACKEND_URL}/block-all-critical`, {
method: "POST",
headers: getMLBackendHeaders(),
body: JSON.stringify({ min_score }),
signal: controller.signal,
});
clearTimeout(timeout);
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
return res.status(response.status).json({
error: errorData.detail || "Block all critical failed",
});
}
const data = await response.json();
res.json(data);
} catch (error: any) {
if (error.name === 'AbortError') {
return res.status(504).json({ error: "Timeout - operazione troppo lunga" });
}
if (error.code === 'ECONNREFUSED') {
return res.status(503).json({ error: "ML backend non disponibile" });
}
res.status(500).json({ error: error.message || "Errore blocco massivo" });
}
});
app.get("/api/ml/stats", async (req, res) => { app.get("/api/ml/stats", async (req, res) => {
try { try {
const controller = new AbortController(); const controller = new AbortController();

View File

@ -1,7 +1,13 @@
{ {
"version": "1.0.106", "version": "1.0.107",
"lastUpdate": "2026-02-14T09:48:51.345Z", "lastUpdate": "2026-02-14T10:15:20.502Z",
"changelog": [ "changelog": [
{
"version": "1.0.107",
"date": "2026-02-14",
"type": "patch",
"description": "Deployment automatico v1.0.107"
},
{ {
"version": "1.0.106", "version": "1.0.106",
"date": "2026-02-14", "date": "2026-02-14",
@ -295,12 +301,6 @@
"date": "2025-11-24", "date": "2025-11-24",
"type": "patch", "type": "patch",
"description": "Deployment automatico v1.0.58" "description": "Deployment automatico v1.0.58"
},
{
"version": "1.0.57",
"date": "2025-11-24",
"type": "patch",
"description": "Deployment automatico v1.0.57"
} }
] ]
} }