Compare commits
No commits in common. "89a531eec4dda1b27f8a54c21ff7a95de8ef175b" and "897c9a3d5c48552830a3cd277a678f39b37bff86" have entirely different histories.
89a531eec4
...
897c9a3d5c
@ -2,7 +2,7 @@
|
|||||||
-- PostgreSQL database dump
|
-- PostgreSQL database dump
|
||||||
--
|
--
|
||||||
|
|
||||||
\restrict VfY2jMibUtM7epqSxI0eI9IK5petlVg4wE8lvRgi6qIK19f865uN5QWYQxOQJY8
|
\restrict zQNR3d1f0L7BheutpfeBwyF7BjurD3GAqhrSEQdUccum6NzNnt3IiQ7Hh7Nri9q
|
||||||
|
|
||||||
-- 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 VfY2jMibUtM7epqSxI0eI9IK5petlVg4wE8lvRgi6qIK19f865uN5QWYQxOQJY8
|
\unrestrict zQNR3d1f0L7BheutpfeBwyF7BjurD3GAqhrSEQdUccum6NzNnt3IiQ7Hh7Nri9q
|
||||||
|
|
||||||
|
|||||||
@ -111,10 +111,6 @@ 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
|
||||||
|
|
||||||
@ -503,94 +499,6 @@ 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"""
|
||||||
|
|||||||
@ -622,42 +622,6 @@ 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();
|
||||||
|
|||||||
16
version.json
16
version.json
@ -1,13 +1,7 @@
|
|||||||
{
|
{
|
||||||
"version": "1.0.107",
|
"version": "1.0.106",
|
||||||
"lastUpdate": "2026-02-14T10:15:20.502Z",
|
"lastUpdate": "2026-02-14T09:48:51.345Z",
|
||||||
"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",
|
||||||
@ -301,6 +295,12 @@
|
|||||||
"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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user