Compare commits

...

23 Commits

Author SHA1 Message Date
Marco Lanzara
f6d656ce14 🚀 Release v1.0.122
- Tipo: patch
- Database schema: database-schema/schema.sql (solo struttura)
- Data: 2026-02-17 09:13:40
2026-02-17 09:13:40 +00:00
marco370
17dc79372e Saved progress at the end of the loop
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 5abe4a2e-1608-4c5e-a264-50329bac4934
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/s2eMVCL
2026-02-17 09:10:10 +00:00
marco370
4118d60d6d Update service monitoring to display detailed status and health
Refactor the services page to dynamically fetch and display the status of various systemd services and timers, improving the observability of the application's backend components.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: 48245392-3f34-4eac-aeaf-99e52684ddf2
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/s2eMVCL
2026-02-17 09:09:26 +00:00
marco370
6ce60ed5d3 Improve router connectivity checks and logging efficiency
Refactor logging configuration to reduce noise from slow or failed router connections, consolidating error details and improving the handling of unreachable routers.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 2b9a2559-b0f6-49cd-b8db-eb24672eef5e
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/6WuDAR4
2026-02-17 08:35:42 +00:00
marco370
fe113d5518 Improve error handling and logging for router operations
Implement a circuit breaker pattern for router connections and optimize logging to reduce noise from unresponsive routers.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 85f7e8cc-b58e-4a55-87f1-84eb08509a81
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/6WuDAR4
2026-02-17 08:19:02 +00:00
Marco Lanzara
9104c67f97 🚀 Release v1.0.121
- Tipo: patch
- Database schema: database-schema/schema.sql (solo struttura)
- Data: 2026-02-17 08:11:26
2026-02-17 08:11:26 +00:00
marco370
d01eca2cf0 Saved progress at the end of the loop
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 2b961dac-b073-4f80-8b6f-8bb8c7b26675
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/6WuDAR4
2026-02-17 08:07:59 +00:00
marco370
b7abd340bc Improve logging for Mikrotik requests and IP blocking operations
Enhance logging in `mikrotik.ts` to include request details, response statuses, and timings. Add verbose logging for successful operations and warnings for errors or slow responses. Update `getExistingBlockedIps` to log total entries and specific list counts per router. Modify `addToAddressList` to log successful additions and specific error conditions. Update `bulkBlockIps` to log detailed operation outcomes, including partial and failed IPs, with a final summary. Add router information to the `BLOCK-ALL` log in `routes.ts`.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: 3945267e-74c4-4c36-912a-462ddd667392
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/6WuDAR4
2026-02-17 08:07:45 +00:00
marco370
0bd84ed2ed Ensure backend services are running and auto-blocking is functional
Add systemd service for Node.js backend, update scripts, and verify service status and auto-block functionality.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: ee67fff9-dcaf-42b7-ac9b-297b17ddfdb3
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/6WuDAR4
2026-02-17 07:53:05 +00:00
Marco Lanzara
74eb423a92 🚀 Release v1.0.120
- Tipo: patch
- Database schema: database-schema/schema.sql (solo struttura)
- Data: 2026-02-17 07:48:15
2026-02-17 07:48:15 +00:00
marco370
3c8c03bb98 Saved progress at the end of the loop
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 0c68b0a5-a8f9-48dc-bd76-f9bc06f520aa
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/6WuDAR4
2026-02-17 07:47:41 +00:00
marco370
2f76875f2b Add systemd service for Node.js backend and update deployment scripts
Create `ids-backend.service` for the Node.js backend, modify `check_frontend.sh` to use systemd, and update `install_systemd_services.sh` to include the new service.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: 4484d762-7461-4e0f-bf71-fa7a7609e794
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/6WuDAR4
2026-02-17 07:47:24 +00:00
marco370
f9e0e1a98e Diagnose issues with the Intrusion Detection System backend services
Identify that the `ids-backend` (Node.js) service is not found and `ids-analytics` is also missing, while `ids-auto-block` fails due to the absence of the backend.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 70f0c377-a69a-4cca-811c-25145638dcc0
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/cJuycQ5
2026-02-17 07:37:31 +00:00
Marco Lanzara
544b7cfa49 🚀 Release v1.0.119
- Tipo: patch
- Database schema: database-schema/schema.sql (solo struttura)
- Data: 2026-02-17 07:32:28
2026-02-17 07:32:28 +00:00
marco370
1fc63c657a Saved progress at the end of the loop
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 700b70e8-ba3c-4702-99d1-a30058c7e961
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/cJuycQ5
2026-02-16 18:36:27 +00:00
marco370
b45b810eb9 Improve IP blocking process by increasing timeouts and adding detailed logging
Increase auto-block timeout to 300s, update systemd service timeout to 480s, and reduce individual MikroTik request timeout to 8s. Add per-router logging for blocking operations.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: 455f4d8c-e90c-45d5-a7f1-e5f98b1345d3
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/cJuycQ5
2026-02-16 18:35:39 +00:00
Marco Lanzara
64c491f245 🚀 Release v1.0.118
- Tipo: patch
- Database schema: database-schema/schema.sql (solo struttura)
- Data: 2026-02-16 18:28:03
2026-02-16 18:28:03 +00:00
marco370
88b0dd7472 Improve backend restart reliability for improved system stability
Update backend check script to handle user permissions for systemctl restarts and add fallback process checking.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: e3c3b9b2-fba8-4fc9-b4fb-ac39615693a8
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/4aeldgV
2026-02-16 18:25:43 +00:00
Marco Lanzara
b18e0a51e1 🚀 Release v1.0.117
- Tipo: patch
- Database schema: database-schema/schema.sql (solo struttura)
- Data: 2026-02-16 15:49:34
2026-02-16 15:49:34 +00:00
marco370
a7967260b1 Improve IP blocking by separating detection and blocking steps
Refactor auto_block.py to call the Node.js backend for blocking critical IPs and adjust the auto-block service configuration.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: aef8a3be-adf0-4bdc-942f-3e7b19be7d72
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/4aeldgV
2026-02-16 15:04:35 +00:00
marco370
59416f0fe3 Configure analytics timer to run hourly and fix script execution
Correctly set up the analytics timer to run hourly and address issues with script parameter passing.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 7725d830-0400-498d-a538-8a6f833ea045
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/4aeldgV
2026-02-16 14:55:05 +00:00
Marco Lanzara
85db2b1483 🚀 Release v1.0.116
- Tipo: patch
- Database schema: database-schema/schema.sql (solo struttura)
- Data: 2026-02-16 14:49:08
2026-02-16 14:49:08 +00:00
marco370
cc7a0f6f0f Update scripts to properly manage backend and frontend services
Adjusted `check_frontend.sh` and `restart_all.sh` to use `systemctl` for the ML backend and direct process management for the frontend, resolving issues with incorrect Python environments and process termination.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: cb6e0872-24a9-4a4b-a053-9491c053b13f
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/4aeldgV
2026-02-16 14:48:50 +00:00
20 changed files with 1520 additions and 549 deletions

View File

@ -0,0 +1,57 @@
echo "=== TEST PORTA 5000 ===" && curl -s -o /dev/null -w "HTTP %{http_code}\n" http://localhost:5000/api/health && echo "=== TEST AUTO-BLOCK MANUALE ===" && sudo -u ids /opt/ids/python_ml/venv/bin/python3 /opt/ids/python_ml/auto_block.py 2>&1 && echo "=== STATO TUTTI I SERVIZI ===" && systemctl status ids-backend ids-ml-backend ids-syslog-parser ids-auto-block.timer --no-pager -l
=== TEST PORTA 5000 ===
HTTP 200
=== TEST AUTO-BLOCK MANUALE ===
[2026-02-17 08:51:22] Starting auto-block cycle...
[2026-02-17 08:51:22] Step 1: Detection ML...
[2026-02-17 08:51:22] Detection completata: 0 anomalie rilevate
[2026-02-17 08:51:22] Step 2: Blocco IP critici sui router...
[2026-02-17 08:51:22] 24 IP bloccati sui router, 0 falliti, 0 gia' bloccati
=== STATO TUTTI I SERVIZI ===
● ids-backend.service - IDS Node.js Backend (Express API + Frontend)
Loaded: loaded (/etc/systemd/system/ids-backend.service; enabled; preset: disabled)
Active: active (running) since Tue 2026-02-17 08:51:09 CET; 57s ago
Process: 31307 ExecStartPre=/bin/bash -c test -f /opt/ids/dist/index.js || (echo "ERRORE: dist/index.js non trovato - eseguire npm run build" && exit 1) (code=exited, status=0/SUCCESS)
Main PID: 31308 (node)
Tasks: 11 (limit: 100409)
Memory: 59.1M (max: 1.0G available: 964.8M)
CPU: 1.669s
CGroup: /system.slice/ids-backend.service
└─31308 node dist/index.js
Feb 17 08:51:09 ids.alfacom.it systemd[1]: Starting IDS Node.js Backend (Express API + Frontend)...
Feb 17 08:51:09 ids.alfacom.it systemd[1]: Started IDS Node.js Backend (Express API + Frontend).
● ids-ml-backend.service - IDS ML Backend (FastAPI)
Loaded: loaded (/etc/systemd/system/ids-ml-backend.service; enabled; preset: disabled)
Active: active (running) since Tue 2026-02-17 08:50:14 CET; 1min 51s ago
Main PID: 31127 (python3)
Tasks: 26 (limit: 100409)
Memory: 256.8M (max: 2.0G available: 1.7G)
CPU: 4.073s
CGroup: /system.slice/ids-ml-backend.service
└─31127 /opt/ids/python_ml/venv/bin/python3 main.py
Feb 17 08:50:14 ids.alfacom.it systemd[1]: Started IDS ML Backend (FastAPI).
● ids-syslog-parser.service - IDS Syslog Parser (Network Logs Processor)
Loaded: loaded (/etc/systemd/system/ids-syslog-parser.service; enabled; preset: disabled)
Active: active (running) since Mon 2026-02-16 12:18:52 CET; 20h ago
Main PID: 1069 (python3)
Tasks: 1 (limit: 100409)
Memory: 9.7M (max: 1.0G available: 1014.2M)
CPU: 1h 59min 34.854s
CGroup: /system.slice/ids-syslog-parser.service
└─1069 /opt/ids/python_ml/venv/bin/python3 syslog_parser.py
Feb 16 12:18:52 ids.alfacom.it systemd[1]: Started IDS Syslog Parser (Network Logs Processor).
● ids-auto-block.timer - IDS Auto-Blocking Timer - Run every 5 minutes
Loaded: loaded (/etc/systemd/system/ids-auto-block.timer; enabled; preset: disabled)
Active: active (running) since Mon 2026-02-16 19:24:04 CET; 13h ago
Until: Mon 2026-02-16 19:24:04 CET; 13h ago
Trigger: n/a
Triggers: ● ids-auto-block.service
Docs: https://github.com/yourusername/ids
Feb 16 19:24:04 ids.alfacom.it systemd[1]: Started IDS Auto-Blocking Timer - Run every 5 minutes.

View File

@ -0,0 +1,85 @@
tail -f /var/log/ids/backend.log
9:21:00 AM [express] GET /api/detections 304 in 19ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7c…
9:21:01 AM [express] GET /api/services/status 200 in 29ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:21:02 AM [express] GET /api/routers 200 in 3ms :: [{"id":"c6904896-59dc-4060-952f-0e55df7dee4a","n…
9:21:12 AM [express] PUT /api/routers/c6904896-59dc-4060-952f-0e55df7dee4a 200 in 8ms :: {"id":"c690…
9:21:12 AM [express] GET /api/routers 304 in 2ms :: [{"id":"c6904896-59dc-4060-952f-0e55df7dee4a","n…
9:22:16 AM [express] POST /api/ml/block-all-critical 200 in 99ms :: {"message":"Nessun IP critico da…
9:24:17 AM [express] POST /api/ml/block-all-critical 200 in 75ms :: {"message":"Nessun IP critico da…
 Using standard PostgreSQL database
9:26:18 AM [express] serving on port 5000
✅ Database connection successful
9:28:19 AM [express] POST /api/ml/block-all-critical 200 in 93ms :: {"message":"Nessun IP critico da…
9:30:19 AM [express] POST /api/ml/block-all-critical 200 in 82ms :: {"message":"Nessun IP critico da…
9:30:25 AM [express] GET /api/training-history 200 in 6ms :: [{"id":"7570df54-8169-4fb2-abdc-e9c1bfa…
9:30:29 AM [express] GET /api/detections 200 in 24ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7c…
9:30:29 AM [express] GET /api/whitelist 200 in 259ms :: {"items":[{"id":"49b5b9a9-4683-452c-a784-fc5…
9:30:37 AM [express] GET /api/services/status 200 in 22ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:30:39 AM [express] POST /api/services/ids-syslog-parser/start 500 in 22ms :: {"error":"Service con…
9:30:42 AM [express] GET /api/services/status 200 in 21ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:30:47 AM [express] GET /api/services/status 200 in 18ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:30:52 AM [express] GET /api/services/status 200 in 17ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:30:57 AM [express] GET /api/services/status 200 in 17ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:31:02 AM [express] GET /api/services/status 200 in 17ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:31:07 AM [express] GET /api/services/status 200 in 23ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:31:12 AM [express] GET /api/services/status 200 in 18ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:31:16 AM [express] GET /api/services/status 200 in 18ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:31:21 AM [express] GET /api/services/status 200 in 17ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:31:26 AM [express] GET /api/services/status 200 in 17ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:31:27 AM [express] GET /api/detections 304 in 11ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7c…
9:31:27 AM [express] GET /api/whitelist 200 in 229ms :: {"items":[{"id":"91108765-7ef6-4e49-87d8-319…
9:31:30 AM [express] GET /api/public-lists 200 in 5ms :: [{"id":"2a835798-02a7-4129-a528-d39a026ad15…
9:31:32 AM [express] GET /api/services/status 200 in 19ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:31:37 AM [express] GET /api/services/status 200 in 20ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:31:42 AM [express] GET /api/services/status 200 in 19ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:31:47 AM [express] GET /api/services/status 200 in 18ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:31:52 AM [express] GET /api/services/status 200 in 17ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:31:57 AM [express] GET /api/services/status 200 in 21ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:32:02 AM [express] GET /api/services/status 200 in 18ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:32:07 AM [express] GET /api/services/status 200 in 24ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:32:12 AM [express] GET /api/services/status 200 in 24ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:32:17 AM [express] GET /api/services/status 200 in 23ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:32:25 AM [express] GET /api/services/status 200 in 2875ms :: {"services":{"mlBackend":{"name":"ML …
[BLOCK-ALL] Avvio blocco massivo: 11/11 IP con score >= 80 su 2 router
[BULK-BLOCK] Starting: 11 IPs on 2 routers (10.20.30.100, 185.203.24.2)
[BULK-BLOCK] Router 185.203.24.2: 124 IPs already in list (50ms)
9:32:30 AM [express] GET /api/services/status 200 in 31ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:32:35 AM [express] GET /api/services/status 200 in 31ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:32:40 AM [express] GET /api/services/status 200 in 46ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:32:46 AM [express] GET /api/services/status 200 in 75ms :: {"services":{"mlBackend":{"name":"ML Ba…
[MIKROTIK] Failed to get address-list from 10.20.30.100: This operation was aborted
[BULK-BLOCK] Router 10.20.30.100: 0 IPs already in list (20004ms)
[BULK-BLOCK] 0 already blocked, 11 new to block
9:32:51 AM [express] GET /api/services/status 200 in 40ms :: {"services":{"mlBackend":{"name":"ML Ba…
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 87.17.182.32: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 185.98.164.31: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 109.115.163.146: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 2.118.225.238: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 74.125.99.38: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 192.178.112.96: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 74.125.111.102: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 212.14.142.214: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8000ms for IP 89.96.215.146: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 172.217.39.230: This operation was aborted
9:32:56 AM [express] GET /api/services/status 200 in 44ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:33:01 AM [express] GET /api/services/status 200 in 46ms :: {"services":{"mlBackend":{"name":"ML Ba…
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 104.19.148.8: This operation was aborted
[BULK-BLOCK] Progress: 11/11
[BULK-BLOCK] Router 10.20.30.100: 0 blocked, 11 failed, 0 skipped
[BULK-BLOCK] Router 185.203.24.2: 11 blocked, 0 failed, 0 skipped
[BULK-BLOCK] Done: 11 blocked, 0 failed, 0 skipped
[BLOCK-ALL] Database aggiornato: 11 IP marcati come bloccati
9:33:03 AM [express] POST /api/ml/block-all-critical 200 in 36137ms :: {"message":"Blocco massivo co…
9:33:07 AM [express] GET /api/services/status 200 in 1125ms :: {"services":{"mlBackend":{"name":"ML …
9:33:12 AM [express] GET /api/services/status 200 in 40ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:33:17 AM [express] GET /api/services/status 200 in 56ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:33:22 AM [express] GET /api/services/status 200 in 58ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:33:27 AM [express] GET /api/services/status 200 in 57ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:33:32 AM [express] GET /api/services/status 200 in 57ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:33:37 AM [express] GET /api/services/status 200 in 52ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:33:42 AM [express] GET /api/services/status 200 in 77ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:33:48 AM [express] GET /api/services/status 200 in 50ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:33:53 AM [express] GET /api/services/status 200 in 72ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:33:58 AM [express] GET /api/services/status 200 in 69ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:34:03 AM [express] GET /api/services/status 200 in 64ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:34:08 AM [express] GET /api/services/status 200 in 79ms :: {"services":{"mlBackend":{"name":"ML Ba…

View File

@ -0,0 +1,224 @@
tail -f /var/log/ids/backend.log
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8000ms for IP 188.8.66.34: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 151.101.193.229: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 109.205.211.40: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 151.59.33.110: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 151.73.209.26: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 79.8.248.29: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 217.202.28.18: This operation was aborted
 Using standard PostgreSQL database
9:13:09 AM [express] serving on port 5000
✅ Database connection successful
[BLOCK-ALL] Avvio blocco massivo: 100/100 IP con score >= 80 su 2 router
[BULK-BLOCK] Starting: 100 IPs on 2 routers (10.20.30.100, 185.203.24.2)
[BULK-BLOCK] Router 185.203.24.2: 74 IPs already in list (38ms)
9:14:15 AM [express] GET /api/detections 200 in 17ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7c…
9:14:15 AM [express] GET /api/services/status 200 in 42ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:14:20 AM [express] GET /api/detections 200 in 19ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7c…
9:14:20 AM [express] GET /api/services/status 200 in 20ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:14:25 AM [express] GET /api/detections 200 in 7ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7cf…
9:14:25 AM [express] GET /api/whitelist 200 in 222ms :: {"items":[{"id":"4b7a60b4-b47c-431e-8efa-864…
[MIKROTIK] Failed to get address-list from 10.20.30.100: This operation was aborted
[BULK-BLOCK] Router 10.20.30.100: 0 IPs already in list (20004ms)
[BULK-BLOCK] 0 already blocked, 100 new to block
9:14:35 AM [express] GET /api/detections 200 in 8ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7cf…
9:14:39 AM [express] GET /api/training-history 200 in 5ms :: [{"id":"4306f5a1-b30b-4241-97d9-6b6a1e2…
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8003ms for IP 151.73.24.49: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 104.16.248.249: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 77.39.130.185: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 104.16.249.249: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 104.18.36.146: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8003ms for IP 193.205.185.20: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8003ms for IP 50.93.53.165: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8004ms for IP 91.208.175.82: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8004ms for IP 74.0.42.209: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8005ms for IP 79.6.115.203: This operation was aborted
9:14:50 AM [express] GET /api/detections 200 in 31ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7c…
9:14:50 AM [express] GET /api/whitelist 200 in 246ms :: {"items":[{"id":"49b5b9a9-4683-452c-a784-fc5…
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 142.250.181.168: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 195.32.127.72: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 93.150.41.42: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 212.183.171.12: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8003ms for IP 78.134.17.204: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 62.94.77.251: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8003ms for IP 151.73.24.107: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8003ms for IP 74.125.45.108: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8003ms for IP 2.42.47.211: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8004ms for IP 89.97.31.234: This operation was aborted
9:14:52 AM [express] GET /api/dashboard/live 200 in 12ms :: {"totalPackets":75520962,"attackPackets"…
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 31.197.212.130: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 44.197.141.31: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 146.75.61.140: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 93.150.200.81: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 101.56.92.15: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8003ms for IP 2.33.192.82: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8003ms for IP 151.41.104.237: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8003ms for IP 77.39.220.111: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8003ms for IP 185.96.131.245: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8004ms for IP 142.250.181.164: This operation was aborted
9:15:00 AM [express] GET /api/routers 200 in 16ms :: [{"id":"c6904896-59dc-4060-952f-0e55df7dee4a","…
9:15:00 AM [express] GET /api/detections 200 in 24ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7c…
9:15:00 AM [express] GET /api/services/status 200 in 28ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:15:05 AM [express] GET /api/detections 200 in 11ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7c…
9:15:05 AM [express] GET /api/services/status 200 in 18ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:15:06 AM [express] GET /api/stats 200 in 5385ms :: {"routers":{"total":2,"enabled":2},"detections"…
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 45.146.216.240: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 62.112.11.234: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 51.159.85.76: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 188.8.66.34: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 151.101.193.229: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 109.205.211.40: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8003ms for IP 151.59.33.110: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8003ms for IP 151.73.209.26: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8003ms for IP 79.8.248.29: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8003ms for IP 217.202.28.18: This operation was aborted
[ANALYTICS QUERY] {
startDate: '2026-01-18T08:15:10.899Z',
endDate: '2026-02-17T08:15:10.899Z',
hourly: true,
hourCondition: 'NOT NULL'
}
[ANALYTICS RESULTS] 41 records found
[ANALYTICS SAMPLE] {
id: 'b3216c05-7f95-4ba9-a5fb-b37461441401',
date: 2026-02-16T00:00:00.000Z,
hour: 23,
totalPackets: 10463767,
totalBytes: 13102201398,
uniqueIps: 25472,
normalPackets: 10463767,
normalBytes: 13102201398,
normalUniqueIps: 25472,
topNormalIps: '[{"ip": "88.39.149.52", "packets": 3744014, "bytes": 5747025096, "country": null}, {"ip": "79.11.175.156", "packets": 1279527, "bytes": 1892212998, "country": null}, {"ip": "95.229.133.69", "packets": 1188856, "bytes": 1758976078, "country": null}, {"ip": "188.12.75.242", "packets": 1168922, "bytes": 1729133469, "country": null}, {"ip": "95.229.85.134", "packets": 1151191, "bytes": 1703382127, "country": null}, {"ip": "74.125.45.108", "packets": 108382, "bytes": 13501983, "country": "United States"}, {"ip": "185.243.5.22", "packets": 87376, "bytes": 38384352, "country": null}, {"ip": "104.16.248.249", "packets": 72117, "bytes": 40864635, "country": "Canada"}, {"ip": "8.8.8.8", "packets": 66005, "bytes": 18862021, "country": "United States"}, {"ip": "95.110.183.67", "packets": 51456, "bytes": 2281666, "country": "Italy"}]',
attackPackets: 0,
attackBytes: 0,
attackUniqueIps: 0,
attacksByCountry: '{}',
attacksByType: '{}',
topAttackers: '[]',
trafficByCountry: '{"Canada": {"normal": 81941, "attacks": 0}, "The Netherlands": {"normal": 49409, "attacks": 0}, "Singapore": {"normal": 61, "attacks": 0}, "Germany": {"normal": 339, "attacks": 0}, "United States":
{"normal": 385230, "attacks": 0}, "Italy": {"normal": 73801, "attacks": 0}, "Netherlands": {"normal": 19928, "attacks": 0}}',
createdAt: 2026-02-17T00:05:00.185Z
}
9:15:10 AM [express] GET /api/analytics/recent 200 in 16ms :: [{"id":"b3216c05-7f95-4ba9-a5fb-b37461…
9:15:12 AM [express] GET /api/training-history 200 in 3ms :: [{"id":"4306f5a1-b30b-4241-97d9-6b6a1e2…
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 7968ms for IP 151.73.139.162: HTTP 401: {"error":401,"message":"Unauthorized"}
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 7969ms for IP 217.28.70.122: HTTP 401: {"error":401,"message":"Unauthorized"}
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 7971ms for IP 79.9.120.141: HTTP 401: {"error":401,"message":"Unauthorized"}
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 7971ms for IP 52.123.129.14: HTTP 401: {"error":401,"message":"Unauthorized"}
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 7970ms for IP 157.240.231.35: HTTP 401: {"error":401,"message":"Unauthorized"}
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 7975ms for IP 46.229.84.162: HTTP 401: {"error":401,"message":"Unauthorized"}
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 7973ms for IP 178.248.182.171: HTTP 401: {"error":401,"message":"Unauthorized"}
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 7974ms for IP 93.43.107.86: HTTP 401: {"error":401,"message":"Unauthorized"}
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 7974ms for IP 178.248.51.104: HTTP 401: {"error":401,"message":"Unauthorized"}
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 7977ms for IP 93.51.52.251: HTTP 401: {"error":401,"message":"Unauthorized"}
[BULK-BLOCK] Progress: 50/100
9:15:19 AM [express] GET /api/ml/stats 200 in 6466ms :: {"logs":{"total":126216346,"last_hour":0},"d…
9:15:22 AM [express] POST /api/ml/train 200 in 10ms :: {"message":"Training avviato in background","…
9:15:22 AM [express] GET /api/training-history 304 in 3ms :: [{"id":"4306f5a1-b30b-4241-97d9-6b6a1e2…
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 85.44.118.45: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 2.228.8.122: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8000ms for IP 188.217.110.96: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 151.84.198.239: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 93.54.65.87: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 213.82.166.186: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 23.216.150.137: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 185.110.20.185: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 95.100.171.8: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 79.11.222.236: This operation was aborted
9:15:28 AM [express] GET /api/ml/stats 304 in 6490ms :: {"logs":{"total":126216346,"last_hour":0},"d…
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 85.35.59.252: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 79.10.32.9: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 79.13.197.84: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 94.85.21.211: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 213.215.214.82: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 185.82.114.4: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 5.158.71.206: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 94.34.87.184: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 93.67.251.46: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 31.7.147.21: This operation was aborted
9:15:32 AM [express] GET /api/training-history 304 in 15ms :: [{"id":"4306f5a1-b30b-4241-97d9-6b6a1e…
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 91.187.197.104: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 172.217.38.150: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 217.141.0.110: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 172.217.38.157: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 140.82.121.3: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 95.255.202.79: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 151.58.132.84: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 82.55.154.58: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 62.98.165.6: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 95.110.183.67: This operation was aborted
9:15:42 AM [express] GET /api/training-history 304 in 16ms :: [{"id":"4306f5a1-b30b-4241-97d9-6b6a1e…
9:15:45 AM [express] GET /api/ml/stats 304 in 7198ms :: {"logs":{"total":126216346,"last_hour":0},"d…
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 93.40.225.146: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 216.128.11.53: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 95.230.242.4: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 2.118.179.69: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 188.8.204.7: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 185.168.176.197: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 93.64.198.214: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 217.202.56.187: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8002ms for IP 5.63.174.25: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 151.64.151.157: This operation was aborted
9:15:52 AM [express] GET /api/training-history 304 in 17ms :: [{"id":"4306f5a1-b30b-4241-97d9-6b6a1e…
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 79.2.176.5: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 82.192.139.100: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 93.40.226.33: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 93.146.168.160: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 94.101.59.182: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 185.104.127.31: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 31.197.212.236: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8000ms for IP 79.3.132.252: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 172.217.38.148: This operation was aborted
[BULK-BLOCK] SLOW: Router 10.20.30.100 took 8001ms for IP 172.217.38.151: This operation was aborted
[BULK-BLOCK] Progress: 100/100
[BULK-BLOCK] Router 10.20.30.100: 0 blocked, 100 failed, 0 skipped
[BULK-BLOCK] Router 185.203.24.2: 50 blocked, 0 failed, 50 skipped
[BULK-BLOCK] Done: 100 blocked, 0 failed, 0 skipped
[BLOCK-ALL] Database aggiornato: 100 IP marcati come bloccati
9:15:55 AM [express] POST /api/ml/block-all-critical 200 in 100172ms :: {"message":"Blocco massivo c…
9:16:02 AM [express] GET /api/training-history 304 in 2ms :: [{"id":"4306f5a1-b30b-4241-97d9-6b6a1e2…
9:16:02 AM [express] GET /api/ml/stats 200 in 6527ms :: {"logs":{"total":126216346,"last_hour":0},"d…
9:16:12 AM [express] GET /api/training-history 304 in 13ms :: [{"id":"4306f5a1-b30b-4241-97d9-6b6a1e…
9:16:19 AM [express] GET /api/ml/stats 304 in 6558ms :: {"logs":{"total":126216346,"last_hour":0},"d…
9:16:19 AM [express] POST /api/ml/block-all-critical 200 in 76ms :: {"message":"Nessun IP critico da…
9:16:22 AM [express] GET /api/training-history 304 in 3ms :: [{"id":"4306f5a1-b30b-4241-97d9-6b6a1e2…
9:16:29 AM [express] GET /api/training-history 304 in 3ms :: [{"id":"4306f5a1-b30b-4241-97d9-6b6a1e2…
9:16:35 AM [express] GET /api/ml/stats 304 in 6623ms :: {"logs":{"total":126216346,"last_hour":0},"d…
9:16:39 AM [express] GET /api/training-history 304 in 13ms :: [{"id":"4306f5a1-b30b-4241-97d9-6b6a1e…
9:16:49 AM [express] GET /api/training-history 304 in 14ms :: [{"id":"4306f5a1-b30b-4241-97d9-6b6a1e…
9:16:59 AM [express] GET /api/training-history 304 in 15ms :: [{"id":"4306f5a1-b30b-4241-97d9-6b6a1e…
[ML Stats] Fallback to database - ML Backend error: This operation was aborted
9:17:06 AM [express] GET /api/ml/stats 200 in 20345ms :: {"source":"database_fallback","ml_backend_s…
9:17:08 AM [express] GET /api/detections 200 in 21ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7c…
9:17:08 AM [express] GET /api/routers 200 in 21ms :: [{"id":"c6904896-59dc-4060-952f-0e55df7dee4a","…
9:17:13 AM [express] GET /api/services/status 200 in 5007ms :: {"services":{"mlBackend":{"name":"ML …
9:17:13 AM [express] GET /api/detections 304 in 8ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7cf…
9:17:14 AM [express] GET /api/stats 200 in 5393ms :: {"routers":{"total":2,"enabled":2},"detections"…
9:17:18 AM [express] GET /api/detections 304 in 7ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7cf…
9:17:23 AM [express] GET /api/services/status 304 in 5006ms :: {"services":{"mlBackend":{"name":"ML …
9:17:23 AM [express] GET /api/detections 304 in 7ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7cf…
9:17:28 AM [express] GET /api/services/status 200 in 85ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:17:28 AM [express] GET /api/detections 304 in 8ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7cf…
9:17:29 AM [express] GET /api/stats 304 in 5314ms :: {"routers":{"total":2,"enabled":2},"detections"…
9:17:33 AM [express] GET /api/services/status 200 in 29ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:17:33 AM [express] GET /api/detections 304 in 7ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7cf…
9:17:38 AM [express] GET /api/services/status 200 in 53ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:17:39 AM [express] GET /api/detections 304 in 7ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7cf…
9:17:43 AM [express] GET /api/services/status 200 in 70ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:17:44 AM [express] GET /api/detections 304 in 8ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7cf…
9:17:44 AM [express] GET /api/stats 304 in 5395ms :: {"routers":{"total":2,"enabled":2},"detections"…
9:17:49 AM [express] GET /api/services/status 200 in 47ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:17:49 AM [express] GET /api/detections 304 in 7ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7cf…
9:17:54 AM [express] GET /api/detections 304 in 12ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7c…
9:17:54 AM [express] GET /api/services/status 200 in 61ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:17:59 AM [express] GET /api/detections 304 in 11ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7c…
9:17:59 AM [express] GET /api/services/status 200 in 30ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:18:00 AM [express] GET /api/stats 304 in 5405ms :: {"routers":{"total":2,"enabled":2},"detections"…
9:18:04 AM [express] GET /api/detections 304 in 7ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7cf…
9:18:04 AM [express] GET /api/services/status 200 in 64ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:18:09 AM [express] GET /api/detections 304 in 8ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7cf…
9:18:09 AM [express] GET /api/services/status 200 in 21ms :: {"services":{"mlBackend":{"name":"ML Ba…
9:18:14 AM [express] GET /api/detections 304 in 21ms :: {"detections":[{"id":"fcde52d3-0ae4-4904-a7c…
9:18:15 AM [express] GET /api/stats 304 in 5344ms :: {"routers":{"total":2,"enabled":2},"detections"…

View File

@ -0,0 +1,158 @@
echo "=== 1. STATO SERVIZI ===" && systemctl status ids-backend ids-ml-backend ids-syslog-parser ids-analytics ids-auto-block.timer ids-auto-block.service --no-pager -l 2>&1 | tail -80 && echo "=== 2. LOG
NODE.JS ===" && journalctl -u ids-backend --no-pager -n 50 && echo "=== 3. LOG ML ===" && journalctl -u ids-ml-backend --no-pager -n 50 && echo "=== 4. LOG AUTO-BLOCK ===" && journalctl -u ids-auto-block --no-pager -n 50 && echo "=== 5. LOG SYSLOG ===" && journalctl -u ids-syslog-parser --no-pager -n 30 && echo "=== 6. PORTE ===" && ss -tlnp | grep -E '3001|5001|514' && echo "=== 7. PROCESSI ===" && ps aux | grep -E 'node|python|uvicorn' | grep -v grep && echo "=== 8. DISCO/MEMORIA ===" && df -h / && free -h && echo "=== 9. TEST CONNESSIONE ===" && curl -s -o /dev/null -w "%{http_code} - Node.js backend\n" http://localhost:3001/api/health && curl -s -o /dev/null -w "%{http_code} - ML backend\n" http://localhost:5001/health && echo "=== 10. LOG DB ===" && sudo -u ids psql -d ids_db -c "SELECT COUNT(*) as logs_last_30min FROM network_logs WHERE timestamp > NOW() - INTERVAL '30 minutes';"
=== 1. STATO SERVIZI ===
Unit ids-backend.service could not be found.
Unit ids-analytics.service could not be found.
● ids-ml-backend.service - IDS ML Backend (FastAPI)
Loaded: loaded (/etc/systemd/system/ids-ml-backend.service; enabled; preset: disabled)
Active: active (running) since Mon 2026-02-16 19:29:06 CET; 13h ago
Main PID: 17629 (python3)
Tasks: 26 (limit: 100409)
Memory: 75.8M (max: 2.0G available: 1.9G)
CPU: 40.396s
CGroup: /system.slice/ids-ml-backend.service
└─17629 /opt/ids/python_ml/venv/bin/python3 main.py
Feb 16 19:29:06 ids.alfacom.it systemd[1]: Started IDS ML Backend (FastAPI).
● ids-syslog-parser.service - IDS Syslog Parser (Network Logs Processor)
Loaded: loaded (/etc/systemd/system/ids-syslog-parser.service; enabled; preset: disabled)
Active: active (running) since Mon 2026-02-16 12:18:52 CET; 20h ago
Main PID: 1069 (python3)
Tasks: 1 (limit: 100409)
Memory: 9.7M (max: 1.0G available: 1014.2M)
CPU: 1h 59min 34.173s
CGroup: /system.slice/ids-syslog-parser.service
└─1069 /opt/ids/python_ml/venv/bin/python3 syslog_parser.py
Feb 16 12:18:52 ids.alfacom.it systemd[1]: Started IDS Syslog Parser (Network Logs Processor).
● ids-auto-block.timer - IDS Auto-Blocking Timer - Run every 5 minutes
Loaded: loaded (/etc/systemd/system/ids-auto-block.timer; enabled; preset: disabled)
Active: active (running) since Mon 2026-02-16 19:24:04 CET; 13h ago
Until: Mon 2026-02-16 19:24:04 CET; 13h ago
Trigger: n/a
Triggers: ● ids-auto-block.service
Docs: https://github.com/yourusername/ids
Feb 16 19:24:04 ids.alfacom.it systemd[1]: Started IDS Auto-Blocking Timer - Run every 5 minutes.
● ids-auto-block.service - IDS Auto-Blocking Service - Detect and Block Malicious IPs
Loaded: loaded (/etc/systemd/system/ids-auto-block.service; disabled; preset: disabled)
Active: activating (start) since Tue 2026-02-17 08:33:33 CET; 3min 14s ago
TriggeredBy: ● ids-auto-block.timer
Main PID: 30644 (python3)
Tasks: 1 (limit: 100409)
Memory: 14.7M
CPU: 148ms
CGroup: /system.slice/ids-auto-block.service
└─30644 /opt/ids/python_ml/venv/bin/python3 /opt/ids/python_ml/auto_block.py
Feb 17 08:33:33 ids.alfacom.it systemd[1]: Starting IDS Auto-Blocking Service - Detect and Block Malicious IPs...
=== 2. LOG NODE.JS ===
-- No entries --
=== 3. LOG ML ===
Feb 16 15:51:21 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 12676 (n/a) with signal SIGKILL.
Feb 16 15:51:21 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 12677 (n/a) with signal SIGKILL.
Feb 16 15:51:21 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 12681 (n/a) with signal SIGKILL.
Feb 16 15:51:21 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 12682 (n/a) with signal SIGKILL.
Feb 16 15:51:21 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 12684 (python3) with signal SIGKILL.
Feb 16 15:51:21 ids.alfacom.it systemd[1]: ids-ml-backend.service: Main process exited, code=killed, status=9/KILL
Feb 16 15:51:21 ids.alfacom.it systemd[1]: ids-ml-backend.service: Failed with result 'timeout'.
Feb 16 15:51:21 ids.alfacom.it systemd[1]: Stopped IDS ML Backend (FastAPI).
Feb 16 15:51:21 ids.alfacom.it systemd[1]: ids-ml-backend.service: Consumed 9.526s CPU time.
Feb 16 15:51:26 ids.alfacom.it systemd[1]: Started IDS ML Backend (FastAPI).
Feb 16 16:50:11 ids.alfacom.it systemd[1]: Stopping IDS ML Backend (FastAPI)...
Feb 16 16:51:41 ids.alfacom.it systemd[1]: ids-ml-backend.service: State 'stop-sigterm' timed out. Killing.
Feb 16 16:51:41 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 13099 (python3) with signal SIGKILL.
Feb 16 16:51:41 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 13102 (python3) with signal SIGKILL.
Feb 16 16:51:41 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 13103 (n/a) with signal SIGKILL.
Feb 16 16:51:41 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 13110 (n/a) with signal SIGKILL.
Feb 16 16:51:41 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 13112 (n/a) with signal SIGKILL.
Feb 16 16:51:41 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 13116 (n/a) with signal SIGKILL.
Feb 16 16:51:41 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 13117 (python3) with signal SIGKILL.
Feb 16 16:51:41 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 13122 (python3) with signal SIGKILL.
Feb 16 16:51:41 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 13125 (n/a) with signal SIGKILL.
Feb 16 16:51:41 ids.alfacom.it systemd[1]: ids-ml-backend.service: Main process exited, code=killed, status=9/KILL
Feb 16 16:51:41 ids.alfacom.it systemd[1]: ids-ml-backend.service: Failed with result 'timeout'.
Feb 16 16:51:41 ids.alfacom.it systemd[1]: Stopped IDS ML Backend (FastAPI).
Feb 16 16:51:41 ids.alfacom.it systemd[1]: ids-ml-backend.service: Consumed 15.919s CPU time.
Feb 16 16:51:46 ids.alfacom.it systemd[1]: Started IDS ML Backend (FastAPI).
Feb 16 19:27:20 ids.alfacom.it systemd[1]: Stopping IDS ML Backend (FastAPI)...
Feb 16 19:28:50 ids.alfacom.it systemd[1]: ids-ml-backend.service: State 'stop-sigterm' timed out. Killing.
Feb 16 19:28:50 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 14614 (python3) with signal SIGKILL.
Feb 16 19:28:50 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 14619 (python3) with signal SIGKILL.
Feb 16 19:28:50 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 14626 (python3) with signal SIGKILL.
Feb 16 19:28:50 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 14675 (n/a) with signal SIGKILL.
Feb 16 19:28:50 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 14676 (python3) with signal SIGKILL.
Feb 16 19:28:50 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 14677 (python3) with signal SIGKILL.
Feb 16 19:28:50 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 14678 (python3) with signal SIGKILL.
Feb 16 19:28:50 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 14679 (python3) with signal SIGKILL.
Feb 16 19:28:50 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 14680 (python3) with signal SIGKILL.
Feb 16 19:28:50 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 14681 (python3) with signal SIGKILL.
Feb 16 19:28:50 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 14682 (python3) with signal SIGKILL.
Feb 16 19:28:50 ids.alfacom.it systemd[1]: ids-ml-backend.service: Killing process 14683 (python3) with signal SIGKILL.
Feb 16 19:28:50 ids.alfacom.it systemd[1]: ids-ml-backend.service: Main process exited, code=killed, status=9/KILL
Feb 16 19:28:50 ids.alfacom.it systemd[1]: ids-ml-backend.service: Failed with result 'timeout'.
Feb 16 19:28:50 ids.alfacom.it systemd[1]: Stopped IDS ML Backend (FastAPI).
Feb 16 19:28:50 ids.alfacom.it systemd[1]: ids-ml-backend.service: Consumed 15.247s CPU time.
Feb 16 19:28:50 ids.alfacom.it systemd[1]: Started IDS ML Backend (FastAPI).
Feb 16 19:29:00 ids.alfacom.it systemd[1]: Stopping IDS ML Backend (FastAPI)...
Feb 16 19:29:01 ids.alfacom.it systemd[1]: ids-ml-backend.service: Deactivated successfully.
Feb 16 19:29:01 ids.alfacom.it systemd[1]: Stopped IDS ML Backend (FastAPI).
Feb 16 19:29:01 ids.alfacom.it systemd[1]: ids-ml-backend.service: Consumed 4.113s CPU time.
Feb 16 19:29:06 ids.alfacom.it systemd[1]: Started IDS ML Backend (FastAPI).
=== 4. LOG AUTO-BLOCK ===
Feb 17 07:45:29 ids.alfacom.it systemd[1]: Failed to start IDS Auto-Blocking Service - Detect and Block Malicious IPs.
Feb 17 07:45:29 ids.alfacom.it systemd[1]: Starting IDS Auto-Blocking Service - Detect and Block Malicious IPs...
Feb 17 07:49:30 ids.alfacom.it systemd[1]: ids-auto-block.service: Main process exited, code=exited, status=1/FAILURE
Feb 17 07:49:30 ids.alfacom.it systemd[1]: ids-auto-block.service: Failed with result 'exit-code'.
Feb 17 07:49:30 ids.alfacom.it systemd[1]: Failed to start IDS Auto-Blocking Service - Detect and Block Malicious IPs.
Feb 17 07:49:30 ids.alfacom.it systemd[1]: Starting IDS Auto-Blocking Service - Detect and Block Malicious IPs...
Feb 17 07:53:30 ids.alfacom.it systemd[1]: ids-auto-block.service: Main process exited, code=exited, status=1/FAILURE
Feb 17 07:53:30 ids.alfacom.it systemd[1]: ids-auto-block.service: Failed with result 'exit-code'.
Feb 17 07:53:30 ids.alfacom.it systemd[1]: Failed to start IDS Auto-Blocking Service - Detect and Block Malicious IPs.
Feb 17 07:53:30 ids.alfacom.it systemd[1]: Starting IDS Auto-Blocking Service - Detect and Block Malicious IPs...
Feb 17 07:57:30 ids.alfacom.it systemd[1]: ids-auto-block.service: Main process exited, code=exited, status=1/FAILURE
Feb 17 07:57:30 ids.alfacom.it systemd[1]: ids-auto-block.service: Failed with result 'exit-code'.
Feb 17 07:57:30 ids.alfacom.it systemd[1]: Failed to start IDS Auto-Blocking Service - Detect and Block Malicious IPs.
Feb 17 07:57:30 ids.alfacom.it systemd[1]: Starting IDS Auto-Blocking Service - Detect and Block Malicious IPs...
Feb 17 08:01:31 ids.alfacom.it systemd[1]: ids-auto-block.service: Main process exited, code=exited, status=1/FAILURE
Feb 17 08:01:31 ids.alfacom.it systemd[1]: ids-auto-block.service: Failed with result 'exit-code'.
Feb 17 08:01:31 ids.alfacom.it systemd[1]: Failed to start IDS Auto-Blocking Service - Detect and Block Malicious IPs.
Feb 17 08:01:31 ids.alfacom.it systemd[1]: Starting IDS Auto-Blocking Service - Detect and Block Malicious IPs...
Feb 17 08:05:31 ids.alfacom.it systemd[1]: ids-auto-block.service: Main process exited, code=exited, status=1/FAILURE
Feb 17 08:05:31 ids.alfacom.it systemd[1]: ids-auto-block.service: Failed with result 'exit-code'.
Feb 17 08:05:31 ids.alfacom.it systemd[1]: Failed to start IDS Auto-Blocking Service - Detect and Block Malicious IPs.
Feb 17 08:05:31 ids.alfacom.it systemd[1]: Starting IDS Auto-Blocking Service - Detect and Block Malicious IPs...
Feb 17 08:09:31 ids.alfacom.it systemd[1]: ids-auto-block.service: Main process exited, code=exited, status=1/FAILURE
Feb 17 08:09:31 ids.alfacom.it systemd[1]: ids-auto-block.service: Failed with result 'exit-code'.
Feb 17 08:09:31 ids.alfacom.it systemd[1]: Failed to start IDS Auto-Blocking Service - Detect and Block Malicious IPs.
Feb 17 08:09:31 ids.alfacom.it systemd[1]: Starting IDS Auto-Blocking Service - Detect and Block Malicious IPs...
Feb 17 08:13:32 ids.alfacom.it systemd[1]: ids-auto-block.service: Main process exited, code=exited, status=1/FAILURE
Feb 17 08:13:32 ids.alfacom.it systemd[1]: ids-auto-block.service: Failed with result 'exit-code'.
Feb 17 08:13:32 ids.alfacom.it systemd[1]: Failed to start IDS Auto-Blocking Service - Detect and Block Malicious IPs.
Feb 17 08:13:32 ids.alfacom.it systemd[1]: Starting IDS Auto-Blocking Service - Detect and Block Malicious IPs...
Feb 17 08:17:32 ids.alfacom.it systemd[1]: ids-auto-block.service: Main process exited, code=exited, status=1/FAILURE
Feb 17 08:17:32 ids.alfacom.it systemd[1]: ids-auto-block.service: Failed with result 'exit-code'.
Feb 17 08:17:32 ids.alfacom.it systemd[1]: Failed to start IDS Auto-Blocking Service - Detect and Block Malicious IPs.
Feb 17 08:17:32 ids.alfacom.it systemd[1]: Starting IDS Auto-Blocking Service - Detect and Block Malicious IPs...
Feb 17 08:21:32 ids.alfacom.it systemd[1]: ids-auto-block.service: Main process exited, code=exited, status=1/FAILURE
Feb 17 08:21:32 ids.alfacom.it systemd[1]: ids-auto-block.service: Failed with result 'exit-code'.
Feb 17 08:21:32 ids.alfacom.it systemd[1]: Failed to start IDS Auto-Blocking Service - Detect and Block Malicious IPs.
Feb 17 08:21:32 ids.alfacom.it systemd[1]: Starting IDS Auto-Blocking Service - Detect and Block Malicious IPs...
Feb 17 08:25:33 ids.alfacom.it systemd[1]: ids-auto-block.service: Main process exited, code=exited, status=1/FAILURE
Feb 17 08:25:33 ids.alfacom.it systemd[1]: ids-auto-block.service: Failed with result 'exit-code'.
Feb 17 08:25:33 ids.alfacom.it systemd[1]: Failed to start IDS Auto-Blocking Service - Detect and Block Malicious IPs.
Feb 17 08:25:33 ids.alfacom.it systemd[1]: Starting IDS Auto-Blocking Service - Detect and Block Malicious IPs...
Feb 17 08:29:33 ids.alfacom.it systemd[1]: ids-auto-block.service: Main process exited, code=exited, status=1/FAILURE
Feb 17 08:29:33 ids.alfacom.it systemd[1]: ids-auto-block.service: Failed with result 'exit-code'.
Feb 17 08:29:33 ids.alfacom.it systemd[1]: Failed to start IDS Auto-Blocking Service - Detect and Block Malicious IPs.
Feb 17 08:29:33 ids.alfacom.it systemd[1]: Starting IDS Auto-Blocking Service - Detect and Block Malicious IPs...
Feb 17 08:33:33 ids.alfacom.it systemd[1]: ids-auto-block.service: Main process exited, code=exited, status=1/FAILURE
Feb 17 08:33:33 ids.alfacom.it systemd[1]: ids-auto-block.service: Failed with result 'exit-code'.
Feb 17 08:33:33 ids.alfacom.it systemd[1]: Failed to start IDS Auto-Blocking Service - Detect and Block Malicious IPs.
Feb 17 08:33:33 ids.alfacom.it systemd[1]: Starting IDS Auto-Blocking Service - Detect and Block Malicious IPs...
=== 5. LOG SYSLOG ===
Feb 16 12:18:52 ids.alfacom.it systemd[1]: Started IDS Syslog Parser (Network Logs Processor).
=== 6. PORTE ===

View File

@ -0,0 +1,110 @@
echo "=== VERIFICA BACKEND NODE.JS ===" && ls -la /etc/systemd/system/ids-*.service /etc/systemd/system/ids-*.timer && echo "=== FILE SERVICE DISPONIBILI ===" && cat /etc/systemd/system/ids-backend.service 2>&1 || echo "FILE NON TROVATO" && echo "=== NGINX/REVERSE PROXY ===" && ss -tlnp | grep -E '80|443|3001|5001' && echo "=== TEST PORTA 3001 ===" && curl -v --connect-timeout 5 http://localhost:3001/api/health 2>&1 && echo "=== COME VIENE AVVIATO NODE.JS ===" && ps aux | grep -i node | grep -v grep && echo "=== PM2 STATUS ===" && pm2 list 2>&1 || echo "PM2 non installato" && echo "=== CONTENUTO /opt/ids/ ===" && ls -la /opt/ids/ && echo "=== PACKAGE.JSON ===" && cat /opt/ids/package.json 2>&1 | head -30 && echo "=== AUTO_BLOCK OUTPUT DETTAGLIATO ===" && sudo -u ids /opt/ids/python_ml/venv/bin/python3 /opt/ids/python_ml/auto_block.py 2>&1
=== VERIFICA BACKEND NODE.JS ===
-rw-r--r--. 1 root root 473 Feb 16 15:52 /etc/systemd/system/ids-analytics-aggregator.service
-rw-r--r--. 1 root root 339 Feb 16 15:52 /etc/systemd/system/ids-analytics-aggregator.timer
-rw-r--r--. 1 root root 674 Feb 16 19:23 /etc/systemd/system/ids-auto-block.service
-rw-r--r--. 1 root root 457 Feb 14 11:42 /etc/systemd/system/ids-auto-block.timer
-rw-r--r--. 1 root root 550 Nov 25 11:47 /etc/systemd/system/ids-cleanup.service
-rw-r--r--. 1 root root 440 Nov 25 11:47 /etc/systemd/system/ids-cleanup.timer
-rw-r--r--. 1 root root 623 Nov 27 19:29 /etc/systemd/system/ids-list-fetcher.service
-rw-r--r--. 1 root root 246 Nov 27 19:29 /etc/systemd/system/ids-list-fetcher.timer
-rw-r--r--. 1 root root 675 Nov 24 12:12 /etc/systemd/system/ids-ml-backend.service
-rw-r--r--. 1 root root 620 Nov 24 19:19 /etc/systemd/system/ids-ml-training.service
-rw-r--r--. 1 root root 398 Nov 24 19:19 /etc/systemd/system/ids-ml-training.timer
-rw-r--r--. 1 root root 727 Nov 24 12:12 /etc/systemd/system/ids-syslog-parser.service
=== FILE SERVICE DISPONIBILI ===
cat: /etc/systemd/system/ids-backend.service: No such file or directory
FILE NON TROVATO
=== NGINX/REVERSE PROXY ===
LISTEN 1107 2048 0.0.0.0:8000 0.0.0.0:* users:(("python3",pid=17629,fd=12))
=== TEST PORTA 3001 ===
* Trying ::1:3001...
* connect to ::1 port 3001 failed: Connection refused
* Trying 127.0.0.1:3001...
* connect to 127.0.0.1 port 3001 failed: Connection refused
* Failed to connect to localhost port 3001: Connection refused
* Closing connection 0
curl: (7) Failed to connect to localhost port 3001: Connection refused
PM2 non installato
=== CONTENUTO /opt/ids/ ===
total 608
drwxr-xr-x. 14 ids ids 4096 Feb 16 19:28 .
drwxr-xr-x. 3 root root 43 Nov 17 18:20 ..
-rw-------. 1 ids ids 508 Feb 16 19:28 .env
-rw-r-----. 1 root root 508 Feb 16 19:28 .env.backup
-rw-r--r--. 1 ids ids 446 Nov 17 18:23 .env.example
drwxr-xr-x. 8 ids ids 4096 Feb 16 19:28 .git
-rw-r--r--. 1 ids ids 686 Nov 17 18:23 .gitignore
-rw-r--r--. 1 ids ids 801 Jan 2 12:50 .replit
-rw-r--r--. 1 ids ids 6264 Nov 17 17:08 GUIDA_INSTALLAZIONE.md
-rw-r--r--. 1 ids ids 44765 Feb 16 08:50 IDS_Conformita_ISO27001.docx
-rw-r--r--. 1 ids ids 7595 Nov 25 19:14 MIKROTIK_API_FIX.md
-rw-r--r--. 1 ids ids 8452 Nov 17 16:40 README.md
-rw-r--r--. 1 ids ids 9092 Nov 17 16:40 RISPOSTA_DEPLOYMENT.md
drwxr-xr-x. 2 ids ids 12288 Feb 16 16:49 attached_assets
drwxr-xr-x. 2 ids ids 4096 Feb 17 04:00 backups
drwxr-xr-x. 4 ids ids 49 Nov 17 16:40 client
-rw-r--r--. 1 ids ids 459 Nov 17 16:40 components.json
drwxr-xr-x. 3 ids ids 4096 Feb 16 19:28 database-schema
-rwxr-xr-x. 1 ids ids 10264 Nov 17 18:23 deploy-to-gitlab.sh
drwxr-xr-x. 7 ids ids 4096 Feb 16 19:28 deployment
-rw-r--r--. 1 ids ids 3165 Nov 17 16:40 design_guidelines.md
drwxr-xr-x. 3 root root 36 Nov 24 11:05 dist
-rw-r--r--. 1 ids ids 325 Nov 17 16:40 drizzle.config.ts
drwxr-xr-x. 4 ids ids 4096 Nov 17 16:40 extracted_idf
-rw-r--r--. 1 ids ids 28609 Feb 16 08:50 generate_iso27001_doc.py
-rw-r--r--. 1 ids ids 1033 Nov 17 17:08 git.env.example
-rw-r--r--. 1 ids ids 96 Nov 26 11:14 main.py
drwxr-xr-x. 328 ids ids 12288 Feb 16 19:28 node_modules
-rw-r--r--. 1 ids ids 299523 Feb 16 19:28 package-lock.json
-rw-r--r--. 1 ids ids 3696 Nov 17 16:40 package.json
-rw-r--r--. 1 ids ids 80 Nov 17 16:40 postcss.config.js
-rwxr-xr-x. 1 ids ids 2496 Nov 17 16:40 push-gitlab.sh
-rw-r--r--. 1 ids ids 191 Feb 16 08:50 pyproject.toml
drwxr-xr-x. 7 ids ids 4096 Feb 16 16:49 python_ml
-rw-r--r--. 1 ids ids 5796 Feb 16 12:33 replit.md
drwxr-xr-x. 2 ids ids 104 Feb 16 12:55 server
drwxr-xr-x. 2 ids ids 23 Jan 2 15:50 shared
-rw-r--r--. 1 ids ids 4050 Nov 17 16:40 tailwind.config.ts
-rw-r--r--. 1 ids ids 657 Nov 17 16:40 tsconfig.json
-rw-r--r--. 1 ids ids 37505 Feb 16 08:50 uv.lock
-rw-r--r--. 1 ids ids 7329 Feb 16 19:28 version.json
-rw-r--r--. 1 ids ids 1080 Nov 17 16:40 vite.config.ts
=== PACKAGE.JSON ===
{
"name": "rest-express",
"version": "1.0.0",
"type": "module",
"license": "MIT",
"scripts": {
"dev": "NODE_ENV=development tsx server/index.ts",
"build": "vite build && esbuild server/index.ts --platform=node --packages=external --bundle --format=esm --outdir=dist",
"start": "NODE_ENV=production node dist/index.js",
"check": "tsc",
"db:push": "drizzle-kit push"
},
"dependencies": {
"@hookform/resolvers": "^3.10.0",
"@jridgewell/trace-mapping": "^0.3.25",
"@neondatabase/serverless": "^0.10.4",
"@radix-ui/react-accordion": "^1.2.4",
"@radix-ui/react-alert-dialog": "^1.1.7",
"@radix-ui/react-aspect-ratio": "^1.1.3",
"@radix-ui/react-avatar": "^1.1.4",
"@radix-ui/react-checkbox": "^1.1.5",
"@radix-ui/react-collapsible": "^1.1.4",
"@radix-ui/react-context-menu": "^2.2.7",
"@radix-ui/react-dialog": "^1.1.7",
"@radix-ui/react-dropdown-menu": "^2.1.7",
"@radix-ui/react-hover-card": "^1.1.7",
"@radix-ui/react-label": "^2.1.3",
"@radix-ui/react-menubar": "^1.1.7",
"@radix-ui/react-navigation-menu": "^1.2.6",
"@radix-ui/react-popover": "^1.1.7",
=== AUTO_BLOCK OUTPUT DETTAGLIATO ===
[2026-02-17 08:38:05] Starting auto-block cycle...
[2026-02-17 08:38:05] Step 1: Detection ML...
[2026-02-17 08:38:05] ML Detection timeout, skip (blocco IP esistenti continua)
[2026-02-17 08:38:05] Step 2: Blocco IP critici sui router...
[2026-02-17 08:38:05] ERRORE: Timeout blocco IP (120s)
[root@ids ~]#

View File

@ -0,0 +1,77 @@
journalctl -u ids-analytics-aggregator.timer -f
Feb 16 12:18:50 ids.alfacom.it systemd[1]: Started IDS Analytics Aggregation Timer - Runs every hour.
Feb 16 12:40:08 ids.alfacom.it systemd[1]: ids-analytics-aggregator.timer: Deactivated successfully.
Feb 16 12:40:08 ids.alfacom.it systemd[1]: Stopped IDS Analytics Aggregation Timer - Runs every hour.
Feb 16 12:40:08 ids.alfacom.it systemd[1]: Stopping IDS Analytics Aggregation Timer - Runs every hour...
Feb 16 12:40:08 ids.alfacom.it systemd[1]: Started IDS Analytics Aggregation Timer - Runs every hour.
^C
[root@ids ids]# systemctl status ids-ml-backend
● ids-ml-backend.service - IDS ML Backend (FastAPI)
Loaded: loaded (/etc/systemd/system/ids-ml-backend.service; enabled; preset: disabled)
Active: active (running) since Mon 2026-02-16 15:51:26 CET; 9min ago
Main PID: 13099 (python3)
Tasks: 26 (limit: 100409)
Memory: 402.9M (max: 2.0G available: 1.6G)
CPU: 15.905s
CGroup: /system.slice/ids-ml-backend.service
└─13099 /opt/ids/python_ml/venv/bin/python3 main.py
Feb 16 15:51:26 ids.alfacom.it systemd[1]: Started IDS ML Backend (FastAPI).
[root@ids ids]# cat /var/log/ids/backend.log | tail -20
[Mon Feb 16 15:40:04 CET 2026] Backend riavviato con PID: 12165
INFO: Started server process [12165]
INFO: Waiting for application startup.
INFO: Application startup complete.
ERROR: [Errno 98] error while attempting to bind on address ('0.0.0.0', 8000): address already in use
INFO: Waiting for application shutdown.
INFO: Application shutdown complete.
[WARNING] Extended Isolation Forest not available, using standard IF
[ML] Using Hybrid ML Detector (Extended Isolation Forest + Feature Selection)
[HYBRID] Ensemble classifier loaded
[HYBRID] Models loaded (version: latest)
[HYBRID] Selected features: 18/25
[HYBRID] Mode: Hybrid (IF + Ensemble)
[ML] ✓ Hybrid detector models loaded and ready
 Starting IDS API on http://0.0.0.0:8000
 Docs available at http://0.0.0.0:8000/docs
[Mon Feb 16 15:45:01 CET 2026] Backend Python NON attivo, riavvio via systemctl...
[Mon Feb 16 15:45:04 CET 2026] ERRORE: Backend non si è avviato. Controlla: journalctl -u ids-ml-backend
[Mon Feb 16 15:50:01 CET 2026] Backend Python NON attivo, riavvio via systemctl...
[Mon Feb 16 15:50:04 CET 2026] ERRORE: Backend non si è avviato. Controlla: journalctl -u ids-ml-backend
[root@ids ids]# systemctl status ids-auto-block
journalctl -u ids-auto-block --no-pager | tail -20
× ids-auto-block.service - IDS Auto-Blocking Service - Detect and Block Malicious IPs
Loaded: loaded (/etc/systemd/system/ids-auto-block.service; disabled; preset: disabled)
Active: failed (Result: signal) since Mon 2026-02-16 12:47:58 CET; 3h 13min ago
TriggeredBy: ○ ids-auto-block.timer
Docs: https://github.com/yourusername/ids
Main PID: 2896 (code=killed, signal=TERM)
CPU: 155ms
Feb 16 12:46:47 ids.alfacom.it systemd[1]: Starting IDS Auto-Blocking Service - Detect and Block Malicious IPs...
Feb 16 12:47:58 ids.alfacom.it systemd[1]: ids-auto-block.service: Main process exited, code=killed, status=15/TERM
Feb 16 12:47:58 ids.alfacom.it systemd[1]: ids-auto-block.service: Failed with result 'signal'.
Feb 16 12:47:58 ids.alfacom.it systemd[1]: Stopped IDS Auto-Blocking Service - Detect and Block Malicious IPs.
Feb 16 12:38:46 ids.alfacom.it systemd[1]: Starting IDS Auto-Blocking Service - Detect and Block Malicious IPs...
Feb 16 12:40:46 ids.alfacom.it systemd[1]: ids-auto-block.service: Main process exited, code=exited, status=1/FAILURE
Feb 16 12:40:46 ids.alfacom.it systemd[1]: ids-auto-block.service: Failed with result 'exit-code'.
Feb 16 12:40:46 ids.alfacom.it systemd[1]: Failed to start IDS Auto-Blocking Service - Detect and Block Malicious IPs.
Feb 16 12:40:46 ids.alfacom.it systemd[1]: Starting IDS Auto-Blocking Service - Detect and Block Malicious IPs...
Feb 16 12:42:46 ids.alfacom.it systemd[1]: ids-auto-block.service: Main process exited, code=exited, status=1/FAILURE
Feb 16 12:42:46 ids.alfacom.it systemd[1]: ids-auto-block.service: Failed with result 'exit-code'.
Feb 16 12:42:46 ids.alfacom.it systemd[1]: Failed to start IDS Auto-Blocking Service - Detect and Block Malicious IPs.
Feb 16 12:42:46 ids.alfacom.it systemd[1]: Starting IDS Auto-Blocking Service - Detect and Block Malicious IPs...
Feb 16 12:44:47 ids.alfacom.it systemd[1]: ids-auto-block.service: Main process exited, code=exited, status=1/FAILURE
Feb 16 12:44:47 ids.alfacom.it systemd[1]: ids-auto-block.service: Failed with result 'exit-code'.
Feb 16 12:44:47 ids.alfacom.it systemd[1]: Failed to start IDS Auto-Blocking Service - Detect and Block Malicious IPs.
Feb 16 12:44:47 ids.alfacom.it systemd[1]: Starting IDS Auto-Blocking Service - Detect and Block Malicious IPs...
Feb 16 12:46:47 ids.alfacom.it systemd[1]: ids-auto-block.service: Main process exited, code=exited, status=1/FAILURE
Feb 16 12:46:47 ids.alfacom.it systemd[1]: ids-auto-block.service: Failed with result 'exit-code'.
Feb 16 12:46:47 ids.alfacom.it systemd[1]: Failed to start IDS Auto-Blocking Service - Detect and Block Malicious IPs.
Feb 16 12:46:47 ids.alfacom.it systemd[1]: Starting IDS Auto-Blocking Service - Detect and Block Malicious IPs...
Feb 16 12:47:58 ids.alfacom.it systemd[1]: ids-auto-block.service: Main process exited, code=killed, status=15/TERM
Feb 16 12:47:58 ids.alfacom.it systemd[1]: ids-auto-block.service: Failed with result 'signal'.
Feb 16 12:47:58 ids.alfacom.it systemd[1]: Stopped IDS Auto-Blocking Service - Detect and Block Malicious IPs.
[root@ids ids]# curl -X POST http://localhost:5000/api/ml/block-all-critical \
-H "Content-Type: application/json" \
-d '{"min_score": 80, "limit": 200}'

View File

@ -0,0 +1,57 @@
sudo /opt/ids/deployment/setup_analytics_timer.sh
╔═══════════════════════════════════════════════╗
║ IDS Analytics Timer Setup ║
╚═══════════════════════════════════════════════╝
 Copia file systemd...
 Reload systemd daemon...
⚙ Enable e start timer...
 Stato timer:
● ids-analytics-aggregator.timer - IDS Analytics Aggregation Timer - Runs every hour
Loaded: loaded (/etc/systemd/system/ids-analytics-aggregator.timer; enabled; preset: disabled)
Active: active (waiting) since Mon 2026-02-16 12:40:08 CET; 3h 12min ago
Until: Mon 2026-02-16 12:40:08 CET; 3h 12min ago
Trigger: Mon 2026-02-16 16:05:00 CET; 12min left
Triggers: ● ids-analytics-aggregator.service
Feb 16 12:40:08 ids.alfacom.it systemd[1]: Stopped IDS Analytics Aggregation Timer - Runs every hour.
Feb 16 12:40:08 ids.alfacom.it systemd[1]: Stopping IDS Analytics Aggregation Timer - Runs every hour...
Feb 16 12:40:08 ids.alfacom.it systemd[1]: Started IDS Analytics Aggregation Timer - Runs every hour.
 Prossime esecuzioni:
NEXT LEFT LAST PASSED UNIT ACTIVATES
Mon 2026-02-16 16:05:00 CET 12min left Mon 2026-02-16 15:05:00 CET 47min ago ids-analytics-aggregator.timer ids-analytics-aggregator.service
1 timers listed.
Pass --all to see loaded but inactive timers, too.
╔═══════════════════════════════════════════════╗
║ ✅ ANALYTICS TIMER CONFIGURATO ║
╚═══════════════════════════════════════════════╝
📝 Comandi utili:
Stato timer: sudo systemctl status ids-analytics-aggregator.timer
Prossime run: sudo systemctl list-timers
Log aggregazione: sudo journalctl -u ids-analytics-aggregator -f
Test manuale: sudo systemctl start ids-analytics-aggregator
[root@ids ids]# systemctl status ids-analytics-aggregator.timer
● ids-analytics-aggregator.timer - IDS Analytics Aggregation Timer - Runs every hour
Loaded: loaded (/etc/systemd/system/ids-analytics-aggregator.timer; enabled; preset: disabled)
Active: active (waiting) since Mon 2026-02-16 12:40:08 CET; 3h 12min ago
Until: Mon 2026-02-16 12:40:08 CET; 3h 12min ago
Trigger: Mon 2026-02-16 16:05:00 CET; 11min left
Triggers: ● ids-analytics-aggregator.service
Feb 16 12:40:08 ids.alfacom.it systemd[1]: Stopped IDS Analytics Aggregation Timer - Runs every hour.
Feb 16 12:40:08 ids.alfacom.it systemd[1]: Stopping IDS Analytics Aggregation Timer - Runs every hour...
Feb 16 12:40:08 ids.alfacom.it systemd[1]: Started IDS Analytics Aggregation Timer - Runs every hour.
[root@ids ids]# cd /opt/ids && ./deployment/run_analytics.sh
Usage: ./deployment/run_analytics.sh {hourly|daily}
[root@ids ids]# cd /opt/ids && ./deployment/run_analytics.sh {1}
Errore: modo deve essere 'hourly' o 'daily'
[root@ids ids]# cd /opt/ids && ./deployment/run_analytics.sh {hourly}
Errore: modo deve essere 'hourly' o 'daily'
[root@ids ids]# cd /opt/ids && ./deployment/run_analytics.sh {hourly=1}
Errore: modo deve essere 'hourly' o 'daily'

View File

@ -2,25 +2,21 @@ import { useQuery, useMutation } from "@tanstack/react-query";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Activity, Brain, Database, FileText, Terminal, RefreshCw, AlertCircle, Play, Square, RotateCw } from "lucide-react"; import { Activity, Brain, Database, FileText, Terminal, RefreshCw, Play, Square, RotateCw, Shield, Trash2, ListChecks, GraduationCap, Server, Clock, Timer } from "lucide-react";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { useToast } from "@/hooks/use-toast"; import { useToast } from "@/hooks/use-toast";
import { queryClient, apiRequest } from "@/lib/queryClient"; import { queryClient, apiRequest } from "@/lib/queryClient";
interface ServiceStatus { interface ServiceStatus {
name: string; name: string;
status: "running" | "idle" | "offline" | "error" | "unknown"; status: string;
healthy: boolean; healthy: boolean;
details: any; details: any;
systemdUnit: string;
type: string;
} }
interface ServicesStatusResponse { interface ServicesStatusResponse {
services: { services: Record<string, ServiceStatus>;
mlBackend: ServiceStatus;
database: ServiceStatus;
syslogParser: ServiceStatus;
analyticsAggregator: ServiceStatus;
};
} }
export default function ServicesPage() { export default function ServicesPage() {
@ -28,10 +24,9 @@ export default function ServicesPage() {
const { data: servicesStatus, isLoading, refetch } = useQuery<ServicesStatusResponse>({ const { data: servicesStatus, isLoading, refetch } = useQuery<ServicesStatusResponse>({
queryKey: ["/api/services/status"], queryKey: ["/api/services/status"],
refetchInterval: 5000, // Refresh every 5s refetchInterval: 5000,
}); });
// Mutation for service control
const serviceControlMutation = useMutation({ const serviceControlMutation = useMutation({
mutationFn: async ({ service, action }: { service: string; action: string }) => { mutationFn: async ({ service, action }: { service: string; action: string }) => {
return apiRequest("POST", `/api/services/${service}/${action}`); return apiRequest("POST", `/api/services/${service}/${action}`);
@ -39,9 +34,8 @@ export default function ServicesPage() {
onSuccess: (data, variables) => { onSuccess: (data, variables) => {
toast({ toast({
title: "Operazione completata", title: "Operazione completata",
description: `Servizio ${variables.service}: ${variables.action} eseguito con successo`, description: `Servizio ${variables.service}: ${variables.action} eseguito`,
}); });
// Refresh status after 2 seconds
setTimeout(() => { setTimeout(() => {
queryClient.invalidateQueries({ queryKey: ["/api/services/status"] }); queryClient.invalidateQueries({ queryKey: ["/api/services/status"] });
}, 2000); }, 2000);
@ -59,39 +53,260 @@ export default function ServicesPage() {
serviceControlMutation.mutate({ service, action }); serviceControlMutation.mutate({ service, action });
}; };
const getStatusBadge = (service: ServiceStatus) => { const getStatusBadge = (service: ServiceStatus, key: string) => {
if (service.healthy) { if (service.healthy) {
return <Badge variant="default" className="bg-green-600" data-testid={`badge-status-healthy`}>Online</Badge>; return <Badge variant="default" className="bg-green-600" data-testid={`badge-status-${key}-healthy`}>Online</Badge>;
} }
if (service.status === 'idle') { if (service.status === 'idle') {
return <Badge variant="secondary" data-testid={`badge-status-idle`}>In Attesa</Badge>; return <Badge variant="secondary" data-testid={`badge-status-${key}-idle`}>In Attesa</Badge>;
} }
if (service.status === 'offline') { if (service.status === 'offline') {
return <Badge variant="destructive" data-testid={`badge-status-offline`}>Offline</Badge>; return <Badge variant="destructive" data-testid={`badge-status-${key}-offline`}>Offline</Badge>;
} }
if (service.status === 'error') { if (service.status === 'error') {
return <Badge variant="destructive" data-testid={`badge-status-error`}>Errore</Badge>; return <Badge variant="destructive" data-testid={`badge-status-${key}-error`}>Errore</Badge>;
} }
return <Badge variant="outline" data-testid={`badge-status-unknown`}>Sconosciuto</Badge>; return <Badge variant="outline" data-testid={`badge-status-${key}-unknown`}>Sconosciuto</Badge>;
}; };
const getStatusIndicator = (service: ServiceStatus) => { const getStatusIndicator = (service: ServiceStatus) => {
if (service.healthy) { if (service.healthy) {
return <div className="h-3 w-3 rounded-full bg-green-500" />; return <div className="h-3 w-3 rounded-full bg-green-500 shrink-0" />;
} }
if (service.status === 'idle') { if (service.status === 'idle') {
return <div className="h-3 w-3 rounded-full bg-yellow-500" />; return <div className="h-3 w-3 rounded-full bg-yellow-500 shrink-0" />;
} }
return <div className="h-3 w-3 rounded-full bg-red-500" />; return <div className="h-3 w-3 rounded-full bg-red-500 shrink-0" />;
};
const getServiceIcon = (key: string) => {
const icons: Record<string, any> = {
nodeBackend: Server,
mlBackend: Brain,
database: Database,
syslogParser: FileText,
analyticsAggregator: Activity,
autoBlock: Shield,
cleanup: Trash2,
listFetcher: ListChecks,
mlTraining: GraduationCap,
};
const Icon = icons[key] || Activity;
return <Icon className="h-5 w-5" />;
};
const controllableServices = [
"ids-ml-backend", "ids-syslog-parser", "ids-backend",
"ids-analytics-aggregator", "ids-auto-block", "ids-cleanup",
"ids-list-fetcher", "ids-ml-training"
];
const getLogCommand = (key: string): string | null => {
const logs: Record<string, string> = {
nodeBackend: "tail -f /var/log/ids/backend.log",
mlBackend: "journalctl -u ids-ml-backend -f",
database: "sudo journalctl -u postgresql-16 -f",
syslogParser: "tail -f /var/log/ids/syslog_parser.log",
analyticsAggregator: "journalctl -u ids-analytics-aggregator -f",
autoBlock: "journalctl -u ids-auto-block -f",
cleanup: "journalctl -u ids-cleanup -f",
listFetcher: "journalctl -u ids-list-fetcher -f",
mlTraining: "journalctl -u ids-ml-training -f",
};
return logs[key] || null;
};
const renderDetailRow = (label: string, value: any, variant?: "default" | "destructive" | "secondary" | "outline") => {
if (value === undefined || value === null) return null;
return (
<div className="flex items-center justify-between gap-2 flex-wrap">
<span className="text-sm text-muted-foreground">{label}:</span>
{variant ? (
<Badge variant={variant} className="text-xs">{String(value)}</Badge>
) : (
<span className="text-sm font-mono">{String(value)}</span>
)}
</div>
);
};
const renderServiceDetails = (key: string, service: ServiceStatus) => {
const d = service.details;
if (!d) return null;
switch (key) {
case "nodeBackend":
return (
<>
{renderDetailRow("Porta", d.port)}
{renderDetailRow("Uptime", d.uptime)}
</>
);
case "mlBackend":
return (
<>
{d.modelLoaded !== undefined && renderDetailRow("Modello ML", d.modelLoaded ? "Caricato" : "Non Caricato", d.modelLoaded ? "default" : "secondary")}
{d.error && renderDetailRow("Errore", d.error, "destructive")}
</>
);
case "database":
return (
<>
{d.connected && renderDetailRow("Connessione", "Attiva", "default")}
{d.error && renderDetailRow("Errore", d.error, "destructive")}
</>
);
case "syslogParser":
return (
<>
{d.recentLogs30min !== undefined && renderDetailRow("Log ultimi 30min", d.recentLogs30min.toLocaleString())}
{d.lastLog && renderDetailRow("Ultimo log", typeof d.lastLog === 'string' ? d.lastLog : new Date(d.lastLog).toLocaleString('it-IT'))}
{d.warning && renderDetailRow("Avviso", d.warning, "destructive")}
</>
);
case "analyticsAggregator":
return (
<>
{d.lastRun && renderDetailRow("Ultima esecuzione", new Date(d.lastRun).toLocaleString('it-IT'))}
{d.hoursSinceLastRun && renderDetailRow("Ore dall'ultimo run", d.hoursSinceLastRun + "h", parseFloat(d.hoursSinceLastRun) < 2 ? "default" : "destructive")}
{d.warning && renderDetailRow("Avviso", d.warning, "destructive")}
</>
);
case "autoBlock":
return (
<>
{renderDetailRow("Blocchi ultimi 10min", d.recentBlocks10min)}
{renderDetailRow("Totale bloccati", d.totalBlocked)}
{d.lastBlock && renderDetailRow("Ultimo blocco", typeof d.lastBlock === 'string' && d.lastBlock !== 'Mai' ? new Date(d.lastBlock).toLocaleString('it-IT') : d.lastBlock)}
{renderDetailRow("Intervallo", d.interval)}
</>
);
case "cleanup":
return (
<>
{renderDetailRow("Detection vecchie (>48h)", d.oldDetections48h, d.oldDetections48h > 0 ? "destructive" : "default")}
{renderDetailRow("Detection totali", d.totalDetections)}
{renderDetailRow("Intervallo", d.interval)}
{d.warning && renderDetailRow("Avviso", d.warning, "destructive")}
</>
);
case "listFetcher":
return (
<>
{renderDetailRow("Liste totali", d.totalLists)}
{renderDetailRow("Liste attive", d.enabledLists)}
{d.lastFetched && renderDetailRow("Ultimo fetch", typeof d.lastFetched === 'string' && d.lastFetched !== 'Mai' ? new Date(d.lastFetched).toLocaleString('it-IT') : d.lastFetched)}
{d.hoursSinceLastFetch && renderDetailRow("Ore dall'ultimo fetch", d.hoursSinceLastFetch + "h", parseFloat(d.hoursSinceLastFetch) < 1 ? "default" : "destructive")}
{renderDetailRow("Intervallo", d.interval)}
</>
);
case "mlTraining":
return (
<>
{d.lastTraining && renderDetailRow("Ultimo training", typeof d.lastTraining === 'string' && d.lastTraining !== 'Mai' ? new Date(d.lastTraining).toLocaleString('it-IT') : d.lastTraining)}
{d.daysSinceLastTraining && renderDetailRow("Giorni dall'ultimo", d.daysSinceLastTraining, parseFloat(d.daysSinceLastTraining) < 8 ? "default" : "destructive")}
{d.lastStatus && renderDetailRow("Stato ultimo training", d.lastStatus, d.lastStatus === 'completed' ? "default" : "destructive")}
{d.lastModel && renderDetailRow("Modello", d.lastModel)}
{d.recordsProcessed && renderDetailRow("Record processati", d.recordsProcessed.toLocaleString())}
{renderDetailRow("Intervallo", d.interval)}
</>
);
default:
return d.error ? renderDetailRow("Errore", d.error, "destructive") : null;
}
};
const coreServices = ["nodeBackend", "mlBackend", "database", "syslogParser"];
const timerServices = ["autoBlock", "analyticsAggregator", "cleanup", "listFetcher", "mlTraining"];
const renderServiceCard = (key: string, service: ServiceStatus) => {
const isControllable = controllableServices.includes(service.systemdUnit);
const isTimer = service.type === "timer";
const logCmd = getLogCommand(key);
return (
<Card key={key} data-testid={`card-service-${key}`}>
<CardHeader className="flex flex-row items-center justify-between gap-2 space-y-0 pb-2">
<CardTitle className="flex items-center gap-2 text-base">
{getServiceIcon(key)}
<span className="truncate">{service.name}</span>
</CardTitle>
<div className="flex items-center gap-2 shrink-0">
{isTimer && <Timer className="h-4 w-4 text-muted-foreground" />}
{getStatusIndicator(service)}
</div>
</CardHeader>
<CardContent className="space-y-3">
<div className="flex items-center justify-between gap-2">
<span className="text-sm text-muted-foreground">Stato:</span>
{getStatusBadge(service, key)}
</div>
<div className="flex items-center justify-between gap-2">
<span className="text-sm text-muted-foreground">Systemd:</span>
<Badge variant="outline" className="text-xs font-mono">
{service.systemdUnit}{isTimer ? '.timer' : '.service'}
</Badge>
</div>
{renderServiceDetails(key, service)}
{isControllable && (
<div className="space-y-2 pt-2 border-t">
<p className="text-xs font-medium text-muted-foreground">Controlli:</p>
<div className="flex gap-2 flex-wrap">
<Button
size="sm"
variant="outline"
onClick={() => handleServiceAction(service.systemdUnit, "restart")}
disabled={serviceControlMutation.isPending}
data-testid={`button-restart-${key}`}
>
<RotateCw className="h-3 w-3 mr-1" />
Restart
</Button>
<Button
size="sm"
variant="outline"
onClick={() => handleServiceAction(service.systemdUnit, "start")}
disabled={serviceControlMutation.isPending || service.status === 'running'}
data-testid={`button-start-${key}`}
>
<Play className="h-3 w-3 mr-1" />
Start
</Button>
<Button
size="sm"
variant="outline"
onClick={() => handleServiceAction(service.systemdUnit, "stop")}
disabled={serviceControlMutation.isPending || service.status === 'offline'}
data-testid={`button-stop-${key}`}
>
<Square className="h-3 w-3 mr-1" />
Stop
</Button>
</div>
</div>
)}
{logCmd && (
<div className="p-2 bg-muted rounded-md">
<p className="text-xs font-medium text-muted-foreground mb-1">Log:</p>
<code className="text-xs font-mono break-all" data-testid={`code-log-${key}`}>{logCmd}</code>
</div>
)}
</CardContent>
</Card>
);
}; };
return ( return (
<div className="flex flex-col gap-6 p-6" data-testid="page-services"> <div className="flex flex-col gap-6 p-6" data-testid="page-services">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between gap-4 flex-wrap">
<div> <div>
<h1 className="text-3xl font-semibold" data-testid="text-services-title">Gestione Servizi</h1> <h1 className="text-3xl font-semibold" data-testid="text-services-title">Gestione Servizi</h1>
<p className="text-muted-foreground" data-testid="text-services-subtitle"> <p className="text-muted-foreground" data-testid="text-services-subtitle">
Monitoraggio e controllo dei servizi IDS Monitoraggio e controllo di tutti i servizi IDS
</p> </p>
</div> </div>
<Button onClick={() => refetch()} variant="outline" data-testid="button-refresh"> <Button onClick={() => refetch()} variant="outline" data-testid="button-refresh">
@ -100,303 +315,40 @@ export default function ServicesPage() {
</Button> </Button>
</div> </div>
<Alert data-testid="alert-server-instructions"> {isLoading && (
<AlertCircle className="h-4 w-4" /> <div className="text-center py-8 text-muted-foreground">Caricamento stato servizi...</div>
<AlertTitle>Gestione Servizi Systemd</AlertTitle>
<AlertDescription>
I servizi IDS sono gestiti da systemd sul server AlmaLinux.
Usa i pulsanti qui sotto per controllarli oppure esegui i comandi systemctl direttamente sul server.
</AlertDescription>
</Alert>
{/* Services Grid */}
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
{/* ML Backend Service */}
<Card data-testid="card-ml-backend-service">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-lg">
<Brain className="h-5 w-5" />
ML Backend Python
{servicesStatus && getStatusIndicator(servicesStatus.services.mlBackend)}
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center justify-between">
<span className="text-sm text-muted-foreground">Stato:</span>
{servicesStatus && getStatusBadge(servicesStatus.services.mlBackend)}
</div>
{servicesStatus?.services.mlBackend.details?.modelLoaded !== undefined && (
<div className="flex items-center justify-between">
<span className="text-sm text-muted-foreground">Modello ML:</span>
<Badge variant={servicesStatus.services.mlBackend.details.modelLoaded ? "default" : "secondary"}>
{servicesStatus.services.mlBackend.details.modelLoaded ? "Caricato" : "Non Caricato"}
</Badge>
</div>
)} )}
{/* Service Controls */} {servicesStatus && (
<div className="mt-4 space-y-2"> <>
<p className="text-xs font-medium mb-2">Controlli Servizio:</p> <div>
<div className="flex gap-2 flex-wrap"> <h2 className="text-lg font-semibold mb-3 flex items-center gap-2">
<Button <Server className="h-5 w-5" />
size="sm" Servizi Core
variant="outline" </h2>
onClick={() => handleServiceAction("ids-ml-backend", "start")} <div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-4">
disabled={serviceControlMutation.isPending || servicesStatus?.services.mlBackend.status === 'running'} {coreServices.map((key) => {
data-testid="button-start-ml" const service = (servicesStatus.services as any)[key];
> return service ? renderServiceCard(key, service) : null;
<Play className="h-3 w-3 mr-1" /> })}
Start
</Button>
<Button
size="sm"
variant="outline"
onClick={() => handleServiceAction("ids-ml-backend", "stop")}
disabled={serviceControlMutation.isPending || servicesStatus?.services.mlBackend.status === 'offline'}
data-testid="button-stop-ml"
>
<Square className="h-3 w-3 mr-1" />
Stop
</Button>
<Button
size="sm"
variant="outline"
onClick={() => handleServiceAction("ids-ml-backend", "restart")}
disabled={serviceControlMutation.isPending}
data-testid="button-restart-ml"
>
<RotateCw className="h-3 w-3 mr-1" />
Restart
</Button>
</div> </div>
</div> </div>
{/* Manual Commands (fallback) */} <div>
<div className="mt-4 p-3 bg-muted rounded-lg"> <h2 className="text-lg font-semibold mb-3 flex items-center gap-2">
<p className="text-xs font-medium mb-2">Comando systemctl (sul server):</p> <Clock className="h-5 w-5" />
<code className="text-xs bg-background p-2 rounded block font-mono" data-testid="code-systemctl-ml"> Timer Systemd (Attivita Periodiche)
sudo systemctl {servicesStatus?.services.mlBackend.status === 'offline' ? 'start' : 'restart'} ids-ml-backend </h2>
</code> <div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4">
{timerServices.map((key) => {
const service = (servicesStatus.services as any)[key];
return service ? renderServiceCard(key, service) : null;
})}
</div> </div>
<div className="mt-4 p-3 bg-muted rounded-lg">
<p className="text-xs font-medium mb-2">Log:</p>
<code className="text-xs bg-background p-2 rounded block font-mono" data-testid="code-log-ml">
tail -f /var/log/ids/backend.log
</code>
</div>
</CardContent>
</Card>
{/* Database Service */}
<Card data-testid="card-database-service">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-lg">
<Database className="h-5 w-5" />
PostgreSQL Database
{servicesStatus && getStatusIndicator(servicesStatus.services.database)}
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center justify-between">
<span className="text-sm text-muted-foreground">Stato:</span>
{servicesStatus && getStatusBadge(servicesStatus.services.database)}
</div>
{servicesStatus?.services.database.status === 'running' && (
<div className="flex items-center justify-between">
<span className="text-sm text-muted-foreground">Connessione:</span>
<Badge variant="default" className="bg-green-600">Connesso</Badge>
</div> </div>
</>
)} )}
<div className="mt-4 p-3 bg-muted rounded-lg">
<p className="text-xs font-medium mb-2">Verifica status:</p>
<code className="text-xs bg-background p-2 rounded block font-mono" data-testid="code-status-db">
systemctl status postgresql-16
</code>
</div>
{servicesStatus?.services.database.status === 'error' && (
<div className="mt-4 p-3 bg-muted rounded-lg">
<p className="text-xs font-medium mb-2">Riavvia database:</p>
<code className="text-xs bg-background p-2 rounded block font-mono" data-testid="code-restart-db">
sudo systemctl restart postgresql-16
</code>
</div>
)}
<div className="mt-4 p-3 bg-muted rounded-lg">
<p className="text-xs font-medium mb-2">Log:</p>
<code className="text-xs bg-background p-2 rounded block font-mono" data-testid="code-log-db">
sudo journalctl -u postgresql-16 -f
</code>
</div>
</CardContent>
</Card>
{/* Syslog Parser Service */}
<Card data-testid="card-syslog-parser-service">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-lg">
<FileText className="h-5 w-5" />
Syslog Parser
{servicesStatus && getStatusIndicator(servicesStatus.services.syslogParser)}
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center justify-between">
<span className="text-sm text-muted-foreground">Stato:</span>
{servicesStatus && getStatusBadge(servicesStatus.services.syslogParser)}
</div>
{servicesStatus?.services.syslogParser.details?.pid && (
<div className="flex items-center justify-between">
<span className="text-sm text-muted-foreground">PID Processo:</span>
<Badge variant="outline" className="font-mono">
{servicesStatus.services.syslogParser.details.pid}
</Badge>
</div>
)}
{servicesStatus?.services.syslogParser.details?.systemd_unit && (
<div className="flex items-center justify-between">
<span className="text-sm text-muted-foreground">Systemd Unit:</span>
<Badge variant="outline" className="font-mono text-xs">
{servicesStatus.services.syslogParser.details.systemd_unit}
</Badge>
</div>
)}
{/* Service Controls */}
<div className="mt-4 space-y-2">
<p className="text-xs font-medium mb-2">Controlli Servizio:</p>
<div className="flex gap-2 flex-wrap">
<Button
size="sm"
variant="outline"
onClick={() => handleServiceAction("ids-syslog-parser", "start")}
disabled={serviceControlMutation.isPending || servicesStatus?.services.syslogParser.status === 'running'}
data-testid="button-start-parser"
>
<Play className="h-3 w-3 mr-1" />
Start
</Button>
<Button
size="sm"
variant="outline"
onClick={() => handleServiceAction("ids-syslog-parser", "stop")}
disabled={serviceControlMutation.isPending || servicesStatus?.services.syslogParser.status === 'offline'}
data-testid="button-stop-parser"
>
<Square className="h-3 w-3 mr-1" />
Stop
</Button>
<Button
size="sm"
variant="outline"
onClick={() => handleServiceAction("ids-syslog-parser", "restart")}
disabled={serviceControlMutation.isPending}
data-testid="button-restart-parser"
>
<RotateCw className="h-3 w-3 mr-1" />
Restart
</Button>
</div>
</div>
{/* Manual Commands (fallback) */}
<div className="mt-4 p-3 bg-muted rounded-lg">
<p className="text-xs font-medium mb-2">Comando systemctl (sul server):</p>
<code className="text-xs bg-background p-2 rounded block font-mono" data-testid="code-systemctl-parser">
sudo systemctl {servicesStatus?.services.syslogParser.status === 'offline' ? 'start' : 'restart'} ids-syslog-parser
</code>
</div>
<div className="mt-4 p-3 bg-muted rounded-lg">
<p className="text-xs font-medium mb-2">Log:</p>
<code className="text-xs bg-background p-2 rounded block font-mono" data-testid="code-log-parser">
tail -f /var/log/ids/syslog_parser.log
</code>
</div>
</CardContent>
</Card>
{/* Analytics Aggregator Service */}
<Card data-testid="card-analytics-aggregator-service">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-lg">
<Activity className="h-5 w-5" />
Analytics Aggregator
{servicesStatus && getStatusIndicator(servicesStatus.services.analyticsAggregator)}
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center justify-between">
<span className="text-sm text-muted-foreground">Stato:</span>
{servicesStatus && getStatusBadge(servicesStatus.services.analyticsAggregator)}
</div>
{servicesStatus?.services.analyticsAggregator.details?.lastRun && (
<div className="flex items-center justify-between">
<span className="text-sm text-muted-foreground">Ultima Aggregazione:</span>
<Badge variant="outline" className="text-xs">
{new Date(servicesStatus.services.analyticsAggregator.details.lastRun).toLocaleString('it-IT')}
</Badge>
</div>
)}
{servicesStatus?.services.analyticsAggregator.details?.hoursSinceLastRun && (
<div className="flex items-center justify-between">
<span className="text-sm text-muted-foreground">Ore dall'ultimo run:</span>
<Badge variant={parseFloat(servicesStatus.services.analyticsAggregator.details.hoursSinceLastRun) < 2 ? "default" : "destructive"}>
{servicesStatus.services.analyticsAggregator.details.hoursSinceLastRun}h
</Badge>
</div>
)}
{/* CRITICAL ALERT: Aggregator idle for too long */}
{servicesStatus?.services.analyticsAggregator.details?.hoursSinceLastRun &&
parseFloat(servicesStatus.services.analyticsAggregator.details.hoursSinceLastRun) > 2 && (
<Alert variant="destructive" className="mt-2" data-testid="alert-aggregator-idle">
<AlertCircle className="h-4 w-4" />
<AlertTitle className="text-sm font-semibold"> Timer Systemd Non Attivo</AlertTitle>
<AlertDescription className="text-xs mt-1">
<p className="mb-2">L'aggregatore non esegue da {servicesStatus.services.analyticsAggregator.details.hoursSinceLastRun}h! Dashboard e Analytics bloccati.</p>
<p className="font-semibold">Soluzione Immediata (sul server):</p>
<code className="block bg-destructive-foreground/10 p-2 rounded mt-1 font-mono text-xs">
sudo /opt/ids/deployment/setup_analytics_timer.sh
</code>
</AlertDescription>
</Alert>
)}
<div className="mt-4 p-3 bg-muted rounded-lg">
<p className="text-xs font-medium mb-2">Verifica timer:</p>
<code className="text-xs bg-background p-2 rounded block font-mono" data-testid="code-status-aggregator">
systemctl status ids-analytics-aggregator.timer
</code>
</div>
<div className="mt-4 p-3 bg-muted rounded-lg">
<p className="text-xs font-medium mb-2">Avvia aggregazione manualmente:</p>
<code className="text-xs bg-background p-2 rounded block font-mono" data-testid="code-run-aggregator">
cd /opt/ids && ./deployment/run_analytics.sh
</code>
</div>
<div className="mt-4 p-3 bg-muted rounded-lg">
<p className="text-xs font-medium mb-2">Log:</p>
<code className="text-xs bg-background p-2 rounded block font-mono" data-testid="code-log-aggregator">
journalctl -u ids-analytics-aggregator.timer -f
</code>
</div>
</CardContent>
</Card>
</div>
{/* Additional Commands */}
<Card data-testid="card-additional-commands"> <Card data-testid="card-additional-commands">
<CardHeader> <CardHeader>
<CardTitle className="flex items-center gap-2"> <CardTitle className="flex items-center gap-2">
@ -406,30 +358,27 @@ export default function ServicesPage() {
</CardHeader> </CardHeader>
<CardContent className="space-y-4"> <CardContent className="space-y-4">
<div> <div>
<p className="text-sm font-medium mb-2">Verifica tutti i processi IDS attivi:</p> <p className="text-sm font-medium mb-2">Stato di tutti i servizi IDS:</p>
<code className="text-xs bg-muted p-2 rounded block font-mono" data-testid="code-check-processes"> <code className="text-xs bg-muted p-2 rounded-md block font-mono" data-testid="code-all-services">
ps aux | grep -E "python.*(main|syslog_parser)" | grep -v grep systemctl list-units 'ids-*' --all
</code>
</div>
<div>
<p className="text-sm font-medium mb-2">Stato di tutti i timer IDS:</p>
<code className="text-xs bg-muted p-2 rounded-md block font-mono" data-testid="code-all-timers">
systemctl list-timers 'ids-*' --all
</code> </code>
</div> </div>
<div> <div>
<p className="text-sm font-medium mb-2">Verifica log RSyslog (ricezione log MikroTik):</p> <p className="text-sm font-medium mb-2">Verifica log RSyslog (ricezione log MikroTik):</p>
<code className="text-xs bg-muted p-2 rounded block font-mono" data-testid="code-check-rsyslog"> <code className="text-xs bg-muted p-2 rounded-md block font-mono" data-testid="code-check-rsyslog">
tail -f /var/log/mikrotik/raw.log tail -f /var/log/mikrotik/raw.log
</code> </code>
</div> </div>
<div> <div>
<p className="text-sm font-medium mb-2">Esegui training manuale ML:</p> <p className="text-sm font-medium mb-2">Verifica processi IDS attivi:</p>
<code className="text-xs bg-muted p-2 rounded block font-mono" data-testid="code-manual-training"> <code className="text-xs bg-muted p-2 rounded-md block font-mono" data-testid="code-check-processes">
curl -X POST http://localhost:8000/train -H "Content-Type: application/json" -d '&#123;"max_records": 10000, "hours_back": 24&#125;' ps aux | grep -E "python.*(main|syslog_parser)" | grep -v grep
</code>
</div>
<div>
<p className="text-sm font-medium mb-2">Verifica storico training nel database:</p>
<code className="text-xs bg-muted p-2 rounded block font-mono" data-testid="code-check-training">
psql $DATABASE_URL -c "SELECT * FROM training_history ORDER BY trained_at DESC LIMIT 5;"
</code> </code>
</div> </div>
</CardContent> </CardContent>

View File

@ -2,7 +2,7 @@
-- PostgreSQL database dump -- PostgreSQL database dump
-- --
\restrict 9ZJC58VvaMhFtxysGUfqAD6tVv0Q9ukBv5rvK14fndwaalwIHn442ILA7auN2Uq \restrict QQPZgpukcxzRMKOdS5xNsXDiphiHLW5uAuhQxN7luRJ2u8BkVkDOz1h9Un2BrJ0
-- 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 9ZJC58VvaMhFtxysGUfqAD6tVv0Q9ukBv5rvK14fndwaalwIHn442ILA7auN2Uq \unrestrict QQPZgpukcxzRMKOdS5xNsXDiphiHLW5uAuhQxN7luRJ2u8BkVkDOz1h9Un2BrJ0

View File

@ -2,6 +2,7 @@
# ========================================================= # =========================================================
# CHECK BACKEND - Verifica e riavvia backend Python se necessario # CHECK BACKEND - Verifica e riavvia backend Python se necessario
# Usa systemctl per gestire il servizio (con virtual environment) # Usa systemctl per gestire il servizio (con virtual environment)
# Nota: questo script può girare come root o come user ids
# ========================================================= # =========================================================
LOG_FILE="/var/log/ids/backend.log" LOG_FILE="/var/log/ids/backend.log"
@ -11,18 +12,28 @@ mkdir -p /var/log/ids
# Check if systemd service is active # Check if systemd service is active
if systemctl is-active --quiet ids-ml-backend; then if systemctl is-active --quiet ids-ml-backend; then
exit 0 exit 0
else fi
echo "[$(date)] Backend Python NON attivo, riavvio via systemctl..." >> "$LOG_FILE"
# Restart via systemctl (usa il venv configurato nel service) # Verifica anche se il processo Python è attivo (fallback)
if pgrep -f "python.*main.py" > /dev/null; then
exit 0
fi
echo "[$(date)] Backend Python NON attivo, riavvio..." >> "$LOG_FILE"
# Prova prima con systemctl (funziona se eseguito come root o con sudo configurato)
if [ "$(id -u)" -eq 0 ]; then
systemctl restart ids-ml-backend systemctl restart ids-ml-backend
else
# Se non siamo root, prova con sudo (richiede sudoers configurato)
sudo systemctl restart ids-ml-backend 2>/dev/null
fi
# Wait for startup # Wait for startup
sleep 3 sleep 5
if systemctl is-active --quiet ids-ml-backend; then if systemctl is-active --quiet ids-ml-backend || pgrep -f "python.*main.py" > /dev/null; then
echo "[$(date)] Backend riavviato con successo via systemctl" >> "$LOG_FILE" echo "[$(date)] Backend riavviato con successo" >> "$LOG_FILE"
else else
echo "[$(date)] ERRORE: Backend non si è avviato. Controlla: journalctl -u ids-ml-backend" >> "$LOG_FILE" echo "[$(date)] ERRORE: Backend non si è avviato. Controlla: journalctl -u ids-ml-backend" >> "$LOG_FILE"
fi fi
fi

View File

@ -1,28 +1,23 @@
#!/bin/bash #!/bin/bash
# ========================================================= # =========================================================
# CHECK FRONTEND - Verifica e riavvia frontend Node.js se necessario # CHECK FRONTEND - Verifica se backend Node.js e' attivo
# Usa systemctl per gestire il servizio
# ========================================================= # =========================================================
LOG_FILE="/var/log/ids/frontend.log" LOG_FILE="/var/log/ids/backend.log"
mkdir -p /var/log/ids mkdir -p /var/log/ids
# Check if systemd service is active if systemctl is-active --quiet ids-backend.service 2>/dev/null; then
if systemctl is-active --quiet ids-frontend; then
exit 0 exit 0
else else
echo "[$(date)] Frontend Node NON attivo, riavvio via systemctl..." >> "$LOG_FILE" echo "[$(date)] Backend Node.js NON attivo" >> "$LOG_FILE"
systemctl start ids-backend.service 2>> "$LOG_FILE" || true
# Restart via systemctl
systemctl restart ids-frontend
# Wait for startup
sleep 3 sleep 3
if systemctl is-active --quiet ids-frontend; then if systemctl is-active --quiet ids-backend.service 2>/dev/null; then
echo "[$(date)] Frontend riavviato con successo via systemctl" >> "$LOG_FILE" echo "[$(date)] Backend riavviato con successo via systemd" >> "$LOG_FILE"
else else
echo "[$(date)] ERRORE: Frontend non si è avviato. Controlla: journalctl -u ids-frontend" >> "$LOG_FILE" echo "[$(date)] ERRORE: Backend non si e' avviato - verificare con: journalctl -u ids-backend -n 20" >> "$LOG_FILE"
fi fi
fi fi

View File

@ -18,43 +18,49 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
echo "" echo ""
echo "📋 Installing systemd service files..." echo "Installing systemd service files..."
# Copy service files # Copy service files
cp "$PROJECT_ROOT/deployment/systemd/ids-backend.service" /etc/systemd/system/
cp "$PROJECT_ROOT/deployment/systemd/ids-ml-backend.service" /etc/systemd/system/ cp "$PROJECT_ROOT/deployment/systemd/ids-ml-backend.service" /etc/systemd/system/
cp "$PROJECT_ROOT/deployment/systemd/ids-syslog-parser.service" /etc/systemd/system/ cp "$PROJECT_ROOT/deployment/systemd/ids-syslog-parser.service" /etc/systemd/system/
cp "$PROJECT_ROOT/deployment/systemd/ids-auto-block.service" /etc/systemd/system/
# Ensure correct permissions # Ensure correct permissions
chmod 644 /etc/systemd/system/ids-backend.service
chmod 644 /etc/systemd/system/ids-ml-backend.service chmod 644 /etc/systemd/system/ids-ml-backend.service
chmod 644 /etc/systemd/system/ids-syslog-parser.service chmod 644 /etc/systemd/system/ids-syslog-parser.service
chmod 644 /etc/systemd/system/ids-auto-block.service
echo "Service files copied to /etc/systemd/system/" echo "Service files copied to /etc/systemd/system/"
echo "" echo ""
echo "🔄 Reloading systemd daemon..." echo "Reloading systemd daemon..."
systemctl daemon-reload systemctl daemon-reload
echo "" echo ""
echo "🔧 Enabling services to start on boot..." echo "Enabling services to start on boot..."
systemctl enable ids-backend.service
systemctl enable ids-ml-backend.service systemctl enable ids-ml-backend.service
systemctl enable ids-syslog-parser.service systemctl enable ids-syslog-parser.service
echo "" echo ""
echo "=========================================" echo "========================================="
echo "Installation Complete!" echo "Installation Complete!"
echo "=========================================" echo "========================================="
echo "" echo ""
echo "Next steps:" echo "Next steps:"
echo "" echo ""
echo "1. Start the services:" echo "1. Start the services:"
echo " sudo systemctl start ids-backend"
echo " sudo systemctl start ids-ml-backend" echo " sudo systemctl start ids-ml-backend"
echo " sudo systemctl start ids-syslog-parser" echo " sudo systemctl start ids-syslog-parser"
echo "" echo ""
echo "2. Check status:" echo "2. Check status:"
echo " sudo systemctl status ids-ml-backend" echo " sudo systemctl status ids-backend ids-ml-backend ids-syslog-parser"
echo " sudo systemctl status ids-syslog-parser"
echo "" echo ""
echo "3. View logs:" echo "3. View logs:"
echo " tail -f /var/log/ids/backend.log"
echo " tail -f /var/log/ids/ml_backend.log" echo " tail -f /var/log/ids/ml_backend.log"
echo " tail -f /var/log/ids/syslog_parser.log" echo " tail -f /var/log/ids/syslog_parser.log"
echo "" echo ""

View File

@ -1,17 +1,20 @@
#!/bin/bash #!/bin/bash
# ========================================================= # =========================================================
# RESTART ALL - Riavvio completo sistema IDS # RESTART ALL - Riavvio completo sistema IDS
# Usa systemctl per gestire tutti i servizi # Usa systemctl per ML Backend, processo diretto per frontend
# ========================================================= # =========================================================
LOG_FILE="/var/log/ids/cron.log" LOG_FILE="/var/log/ids/cron.log"
echo "$(date): === RESTART SETTIMANALE SISTEMA IDS ===" >> "$LOG_FILE" echo "$(date): === RESTART SETTIMANALE SISTEMA IDS ===" >> "$LOG_FILE"
# Stop all services via systemctl # Stop ML Backend via systemctl
echo "$(date): Arresto servizi..." >> "$LOG_FILE" echo "$(date): Arresto servizi..." >> "$LOG_FILE"
systemctl stop ids-ml-backend 2>/dev/null systemctl stop ids-ml-backend 2>/dev/null
systemctl stop ids-frontend 2>/dev/null
# Stop frontend processes
pkill -f "vite" 2>/dev/null
pkill -f "npm run dev" 2>/dev/null
sleep 5 sleep 5
@ -20,20 +23,23 @@ echo "$(date): Pulizia file temporanei..." >> "$LOG_FILE"
rm -f /var/log/ids/*.pid rm -f /var/log/ids/*.pid
find /tmp -name "ids_*" -mtime +7 -delete 2>/dev/null find /tmp -name "ids_*" -mtime +7 -delete 2>/dev/null
# Restart services via systemctl # Restart ML Backend via systemctl
echo "$(date): Riavvio servizi..." >> "$LOG_FILE" echo "$(date): Riavvio servizi..." >> "$LOG_FILE"
systemctl start ids-ml-backend systemctl start ids-ml-backend
sleep 3 sleep 3
systemctl start ids-frontend
# Verify # Restart frontend via check script
/opt/ids/deployment/check_frontend.sh >> "$LOG_FILE" 2>&1
# Verify ML Backend
if systemctl is-active --quiet ids-ml-backend; then if systemctl is-active --quiet ids-ml-backend; then
echo "$(date): ML Backend avviato con successo" >> "$LOG_FILE" echo "$(date): ML Backend avviato con successo" >> "$LOG_FILE"
else else
echo "$(date): ERRORE: ML Backend non si è avviato" >> "$LOG_FILE" echo "$(date): ERRORE: ML Backend non si è avviato" >> "$LOG_FILE"
fi fi
if systemctl is-active --quiet ids-frontend; then # Verify Frontend
if pgrep -f "vite" > /dev/null; then
echo "$(date): Frontend avviato con successo" >> "$LOG_FILE" echo "$(date): Frontend avviato con successo" >> "$LOG_FILE"
else else
echo "$(date): ERRORE: Frontend non si è avviato" >> "$LOG_FILE" echo "$(date): ERRORE: Frontend non si è avviato" >> "$LOG_FILE"

View File

@ -1,58 +1,56 @@
#!/bin/bash #!/bin/bash
# #
# Restart IDS Frontend (Node.js/Express/Vite) # Restart IDS Frontend (Node.js/Express)
# Utility per restart manuale del server frontend # Utility per restart manuale del server frontend via systemd
# #
set -e set -e
echo "🔄 Restart Frontend Node.js..." echo "Restart Backend Node.js via systemd..."
# Kill AGGRESSIVO di tutti i processi Node/Vite # Stop servizio
echo "⏸️ Stopping all Node/Vite processes..." echo "Stopping ids-backend..."
pkill -9 -f "node.*tsx" 2>/dev/null || true sudo systemctl stop ids-backend.service 2>/dev/null || true
pkill -9 -f "vite" 2>/dev/null || true
pkill -9 -f "npm run dev" 2>/dev/null || true
sleep 2 sleep 2
# Kill processo sulla porta 5000 (se esiste) # Kill eventuali processi orfani sulla porta 5000
echo "🔍 Liberando porta 5000..." echo "Liberando porta 5000..."
lsof -ti:5000 | xargs kill -9 2>/dev/null || true lsof -ti:5000 | xargs kill -9 2>/dev/null || true
sleep 1 sleep 1
# Verifica porta LIBERA # Verifica porta libera
if lsof -Pi :5000 -sTCP:LISTEN -t >/dev/null 2>&1; then if lsof -Pi :5000 -sTCP:LISTEN -t >/dev/null 2>&1; then
echo "ERRORE: Porta 5000 ancora occupata!" echo "ERRORE: Porta 5000 ancora occupata!"
echo "Processi sulla porta:" echo "Processi sulla porta:"
lsof -i:5000 lsof -i:5000
exit 1 exit 1
fi fi
echo "Porta 5000 libera" echo "Porta 5000 libera"
# Restart usando check_frontend.sh # Start servizio
echo "🚀 Starting frontend..." echo "Starting ids-backend..."
/opt/ids/deployment/check_frontend.sh sudo systemctl start ids-backend.service
# Attendi avvio completo # Attendi avvio completo
sleep 5 sleep 5
# Verifica avvio # Verifica avvio
if pgrep -f "vite" > /dev/null; then if systemctl is-active --quiet ids-backend.service; then
PID=$(pgrep -f "vite") echo "Backend avviato con successo"
echo "✅ Frontend avviato con PID: $PID" echo "Server disponibile su: http://localhost:5000"
echo "📡 Server disponibile su: http://localhost:5000"
# Test rapido # Test rapido
sleep 2 sleep 2
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:5000/ 2>/dev/null || echo "000") HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:5000/ 2>/dev/null || echo "000")
if [ "$HTTP_CODE" = "200" ]; then if [ "$HTTP_CODE" = "200" ]; then
echo "HTTP test OK (200)" echo "HTTP test OK (200)"
else else
echo "⚠️ HTTP test: $HTTP_CODE" echo "HTTP test: $HTTP_CODE (potrebbe essere in fase di avvio)"
fi fi
else else
echo "❌ Errore: Frontend non avviato!" echo "ERRORE: Backend non avviato!"
echo "📋 Controlla log: tail -f /var/log/ids/frontend.log" echo "Controlla log: journalctl -u ids-backend -n 20"
sudo journalctl -u ids-backend -n 20 --no-pager
exit 1 exit 1
fi fi

View File

@ -1,8 +1,7 @@
[Unit] [Unit]
Description=IDS Auto-Blocking Service - Detect and Block Malicious IPs Description=IDS Auto-Blocking Service - Detect and Block Malicious IPs
Documentation=https://github.com/yourusername/ids After=network.target postgresql-16.service
After=network.target ids-ml-backend.service postgresql-16.service Wants=ids-ml-backend.service
Requires=ids-ml-backend.service
[Service] [Service]
Type=oneshot Type=oneshot
@ -23,8 +22,8 @@ SyslogIdentifier=ids-auto-block
NoNewPrivileges=true NoNewPrivileges=true
PrivateTmp=true PrivateTmp=true
# Timeout: max 3 minuti per detection+blocking # Timeout: max 8 minuti per detection+blocking
TimeoutStartSec=180 TimeoutStartSec=480
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target

View File

@ -0,0 +1,32 @@
[Unit]
Description=IDS Node.js Backend (Express API + Frontend)
After=network.target postgresql-16.service
Wants=postgresql-16.service
[Service]
Type=simple
User=ids
Group=ids
WorkingDirectory=/opt/ids
EnvironmentFile=/opt/ids/.env
Environment=NODE_ENV=production
Environment=PORT=5000
Environment=PATH=/usr/local/bin:/usr/bin:/bin
ExecStartPre=/bin/bash -c 'test -f /opt/ids/dist/index.js || (echo "ERRORE: dist/index.js non trovato - eseguire npm run build" && exit 1)'
ExecStart=/usr/bin/env node dist/index.js
Restart=always
RestartSec=5
StartLimitInterval=300
StartLimitBurst=10
LimitNOFILE=65536
MemoryMax=1G
StandardOutput=append:/var/log/ids/backend.log
StandardError=append:/var/log/ids/backend.log
SyslogIdentifier=ids-backend
[Install]
WantedBy=multi-user.target

View File

@ -3,59 +3,92 @@
IDS Auto-Blocking Script IDS Auto-Blocking Script
Rileva e blocca automaticamente IP con risk_score >= 80 Rileva e blocca automaticamente IP con risk_score >= 80
Eseguito periodicamente da systemd timer (ogni 5 minuti) Eseguito periodicamente da systemd timer (ogni 5 minuti)
Flusso:
1. Chiama Node.js /api/ml/detect per eseguire detection ML
2. Chiama Node.js /api/ml/block-all-critical per bloccare IP critici sui router
""" """
import requests import requests
import sys import sys
from datetime import datetime from datetime import datetime
NODE_API_URL = "http://localhost:5000"
ML_API_URL = "http://localhost:8000" ML_API_URL = "http://localhost:8000"
def auto_block(): def auto_block():
"""Esegue detection e blocking automatico degli IP critici""" """Esegue detection e blocking automatico degli IP critici"""
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"[{timestamp}] 🔍 Starting auto-block detection...") print(f"[{timestamp}] Starting auto-block cycle...")
# Step 1: Esegui detection via ML Backend (se disponibile)
try: try:
# Chiama endpoint ML /detect con auto_block=true print(f"[{timestamp}] Step 1: Detection ML...")
response = requests.post( response = requests.post(
f"{ML_API_URL}/detect", f"{ML_API_URL}/detect",
json={ json={
"max_records": 5000, # Analizza ultimi 5000 log "max_records": 50000,
"hours_back": 1.0, # Ultima ora "hours_back": 1.0,
"risk_threshold": 80.0, # Solo IP critici (score >= 80) "risk_threshold": 75.0,
"auto_block": True # BLOCCA AUTOMATICAMENTE "auto_block": False
}, },
timeout=120 # 2 minuti timeout timeout=120
) )
if response.status_code == 200: if response.status_code == 200:
data = response.json() data = response.json()
detections = len(data.get("detections", [])) detections = len(data.get("detections", []))
print(f"[{timestamp}] Detection completata: {detections} anomalie rilevate")
else:
print(f"[{timestamp}] Detection API error: HTTP {response.status_code}")
except requests.exceptions.ConnectionError:
print(f"[{timestamp}] ML Backend non raggiungibile, skip detection (blocco IP esistenti continua)")
except requests.exceptions.Timeout:
print(f"[{timestamp}] ML Detection timeout, skip (blocco IP esistenti continua)")
except Exception as e:
print(f"[{timestamp}] Detection error: {e}")
# Step 2: Blocca IP critici (score >= 80) via Node.js
try:
print(f"[{timestamp}] Step 2: Blocco IP critici sui router...")
response = requests.post(
f"{NODE_API_URL}/api/ml/block-all-critical",
json={
"min_score": 80,
"limit": 200,
"list_name": "ddos_blocked"
},
timeout=300
)
if response.status_code == 200:
data = response.json()
blocked = data.get("blocked", 0) blocked = data.get("blocked", 0)
failed = data.get("failed", 0)
skipped = data.get("skipped", 0)
remaining = data.get("remaining", 0)
if blocked > 0: if blocked > 0:
print(f"✓ Detection completata: {detections} anomalie rilevate, {blocked} IP bloccati") print(f"[{timestamp}] {blocked} IP bloccati sui router, {failed} falliti, {skipped} gia' bloccati")
else: else:
print(f"✓ Detection completata: {detections} anomalie rilevate, nessun nuovo IP da bloccare") print(f"[{timestamp}] Nessun nuovo IP da bloccare ({skipped} gia' bloccati)")
if remaining > 0:
print(f"[{timestamp}] Rimangono {remaining} IP critici da bloccare")
return 0 return 0
else: else:
print(f"✗ API error: HTTP {response.status_code}") print(f"[{timestamp}] Block API error: HTTP {response.status_code} - {response.text[:200]}")
print(f" Response: {response.text}")
return 1 return 1
except requests.exceptions.ConnectionError: except requests.exceptions.ConnectionError:
print("✗ ERRORE: ML Backend non raggiungibile su http://localhost:8000") print(f"[{timestamp}] ERRORE: Node.js backend non raggiungibile su {NODE_API_URL}")
print(" Verifica che ids-ml-backend.service sia attivo:")
print(" sudo systemctl status ids-ml-backend")
return 1 return 1
except requests.exceptions.Timeout: except requests.exceptions.Timeout:
print("✗ ERRORE: Timeout dopo 120 secondi. Detection troppo lenta?") print(f"[{timestamp}] ERRORE: Timeout blocco IP (300s)")
return 1 return 1
except Exception as e: except Exception as e:
print(f"✗ ERRORE imprevisto: {type(e).__name__}: {e}") print(f"[{timestamp}] ERRORE imprevisto: {type(e).__name__}: {e}")
import traceback
traceback.print_exc()
return 1 return 1
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,3 +1,5 @@
const VERBOSE = process.env.MIKROTIK_DEBUG === '1' || process.env.MIKROTIK_DEBUG === 'true';
interface RouterConfig { interface RouterConfig {
id: string; id: string;
ipAddress: string; ipAddress: string;
@ -20,12 +22,13 @@ async function mikrotikRequest(
method: string, method: string,
path: string, path: string,
body?: any, body?: any,
timeoutMs: number = 10000 timeoutMs: number = 8000
): Promise<{ status: number; data: any }> { ): Promise<{ status: number; data: any }> {
const useHttps = router.apiPort === 443; const useHttps = router.apiPort === 443;
const protocol = useHttps ? "https" : "http"; const protocol = useHttps ? "https" : "http";
const url = `${protocol}://${router.ipAddress}:${router.apiPort}${path}`; const url = `${protocol}://${router.ipAddress}:${router.apiPort}${path}`;
const auth = Buffer.from(`${router.username}:${router.password}`).toString("base64"); const auth = Buffer.from(`${router.username}:${router.password}`).toString("base64");
const startTime = Date.now();
const origTlsReject = process.env.NODE_TLS_REJECT_UNAUTHORIZED; const origTlsReject = process.env.NODE_TLS_REJECT_UNAUTHORIZED;
if (useHttps) { if (useHttps) {
@ -60,9 +63,24 @@ async function mikrotikRequest(
data = text; data = text;
} }
const elapsed = Date.now() - startTime;
if (VERBOSE) {
const bodyStr = body ? ` body=${JSON.stringify(body)}` : '';
const dataPreview = typeof data === 'string' ? data.substring(0, 200) : JSON.stringify(data).substring(0, 200);
console.log(`[MIKROTIK] ${method} ${url} => HTTP ${response.status} (${elapsed}ms)${bodyStr} response=${dataPreview}`);
} else if (response.status >= 400) {
const dataPreview = typeof data === 'string' ? data.substring(0, 100) : JSON.stringify(data).substring(0, 100);
console.warn(`[MIKROTIK] ${method} ${router.ipAddress}${path} => HTTP ${response.status} (${elapsed}ms) err=${dataPreview}`);
} else if (elapsed > 5000) {
console.warn(`[MIKROTIK] SLOW: ${method} ${router.ipAddress}${path} => HTTP ${response.status} (${elapsed}ms)`);
}
return { status: response.status, data }; return { status: response.status, data };
} catch (error: any) { } catch (error: any) {
clearTimeout(timeout); clearTimeout(timeout);
const elapsed = Date.now() - startTime;
const errMsg = error.name === 'AbortError' ? `TIMEOUT after ${timeoutMs}ms` : error.message;
console.error(`[MIKROTIK] ${method} ${url} => ERRORE: ${errMsg} (${elapsed}ms)`);
if (useHttps && origTlsReject !== undefined) { if (useHttps && origTlsReject !== undefined) {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = origTlsReject; process.env.NODE_TLS_REJECT_UNAUTHORIZED = origTlsReject;
} else if (useHttps) { } else if (useHttps) {
@ -94,19 +112,26 @@ export async function getExistingBlockedIps(
listName: string = "ddos_blocked" listName: string = "ddos_blocked"
): Promise<Set<string>> { ): Promise<Set<string>> {
try { try {
if (VERBOSE) console.log(`[MIKROTIK] Fetching address-list da router ${router.ipAddress} (list=${listName}, timeout=20s)...`);
const { status, data } = await mikrotikRequest(router, "GET", "/rest/ip/firewall/address-list", undefined, 20000); const { status, data } = await mikrotikRequest(router, "GET", "/rest/ip/firewall/address-list", undefined, 20000);
if (status === 200 && Array.isArray(data)) { if (status === 200 && Array.isArray(data)) {
const ips = new Set<string>(); const ips = new Set<string>();
const allLists = new Map<string, number>();
for (const entry of data) { for (const entry of data) {
const count = allLists.get(entry.list) || 0;
allLists.set(entry.list, count + 1);
if (entry.list === listName) { if (entry.list === listName) {
ips.add(entry.address); ips.add(entry.address);
} }
} }
const listsInfo = Array.from(allLists.entries()).map(([name, count]) => `${name}:${count}`).join(', ');
console.log(`[MIKROTIK] Router ${router.ipAddress}: ${data.length} entries totali (${listsInfo}), ${ips.size} in list "${listName}"`);
return ips; return ips;
} }
console.warn(`[MIKROTIK] Router ${router.ipAddress}: risposta inattesa status=${status}, data non e' array`);
return new Set(); return new Set();
} catch (e: any) { } catch (e: any) {
console.error(`[MIKROTIK] Failed to get address-list from ${router.ipAddress}: ${e.message}`); console.error(`[MIKROTIK] Router ${router.ipAddress}: ERRORE fetch address-list: ${e.message}`);
return new Set(); return new Set();
} }
} }
@ -127,41 +152,53 @@ export async function addToAddressList(
}); });
if (status === 200 || status === 201) { if (status === 200 || status === 201) {
if (VERBOSE) console.log(`[BLOCK] OK: ${ipAddress} aggiunto su router ${router.ipAddress} (HTTP ${status})`);
return { routerIp: router.ipAddress, success: true }; return { routerIp: router.ipAddress, success: true };
} }
if (status === 400 || status === 409) { if (status === 400 || status === 409) {
const text = typeof data === "string" ? data.toLowerCase() : JSON.stringify(data).toLowerCase(); const text = typeof data === "string" ? data.toLowerCase() : JSON.stringify(data).toLowerCase();
if (text.includes("already") || text.includes("exists") || text.includes("duplicate") || text.includes("failure: already")) { if (text.includes("already") || text.includes("exists") || text.includes("duplicate") || text.includes("failure: already")) {
if (VERBOSE) console.log(`[BLOCK] SKIP: ${ipAddress} gia' presente su router ${router.ipAddress} (HTTP ${status})`);
return { routerIp: router.ipAddress, success: true, alreadyExists: true }; return { routerIp: router.ipAddress, success: true, alreadyExists: true };
} }
console.warn(`[BLOCK] VERIFICA: ${ipAddress} su router ${router.ipAddress} HTTP ${status} risposta="${text.substring(0, 150)}", verifico lista...`);
try { try {
const verifyResult = await mikrotikRequest(router, "GET", "/rest/ip/firewall/address-list"); const verifyResult = await mikrotikRequest(router, "GET", "/rest/ip/firewall/address-list");
if (verifyResult.status === 200 && Array.isArray(verifyResult.data)) { if (verifyResult.status === 200 && Array.isArray(verifyResult.data)) {
for (const entry of verifyResult.data) { for (const entry of verifyResult.data) {
if (entry.address === ipAddress && entry.list === listName) { if (entry.address === ipAddress && entry.list === listName) {
console.log(`[BLOCK] CONFERMATO: ${ipAddress} trovato nella lista di router ${router.ipAddress} dopo verifica`);
return { routerIp: router.ipAddress, success: true, alreadyExists: true }; return { routerIp: router.ipAddress, success: true, alreadyExists: true };
} }
} }
} }
} catch {} } catch (verifyErr: any) {
console.error(`[BLOCK] ERRORE verifica: ${ipAddress} su router ${router.ipAddress}: ${verifyErr.message}`);
}
const errMsg = `HTTP ${status}: ${typeof data === "string" ? data : JSON.stringify(data)}`;
console.error(`[BLOCK] FALLITO: ${ipAddress} su router ${router.ipAddress}: ${errMsg}`);
return { return {
routerIp: router.ipAddress, routerIp: router.ipAddress,
success: false, success: false,
error: `HTTP ${status}: ${typeof data === "string" ? data : JSON.stringify(data)}`, error: errMsg,
}; };
} }
const errMsg = `HTTP ${status}: ${typeof data === "string" ? data : JSON.stringify(data)}`;
console.error(`[BLOCK] FALLITO: ${ipAddress} su router ${router.ipAddress}: ${errMsg}`);
return { return {
routerIp: router.ipAddress, routerIp: router.ipAddress,
success: false, success: false,
error: `HTTP ${status}: ${typeof data === "string" ? data : JSON.stringify(data)}`, error: errMsg,
}; };
} catch (error: any) { } catch (error: any) {
const errMsg = error.name === 'AbortError' ? `TIMEOUT (8s)` : (error.message || "Connection failed");
console.error(`[BLOCK] ERRORE: ${ipAddress} su router ${router.ipAddress}: ${errMsg}`);
return { return {
routerIp: router.ipAddress, routerIp: router.ipAddress,
success: false, success: false,
error: error.message || "Connection failed", error: errMsg,
}; };
} }
} }
@ -172,8 +209,10 @@ export async function removeFromAddressList(
listName: string = "ddos_blocked" listName: string = "ddos_blocked"
): Promise<BlockResult> { ): Promise<BlockResult> {
try { try {
if (VERBOSE) console.log(`[UNBLOCK] Rimozione ${ipAddress} da router ${router.ipAddress} (list=${listName})...`);
const { status, data } = await mikrotikRequest(router, "GET", "/rest/ip/firewall/address-list"); const { status, data } = await mikrotikRequest(router, "GET", "/rest/ip/firewall/address-list");
if (status !== 200 || !Array.isArray(data)) { if (status !== 200 || !Array.isArray(data)) {
console.error(`[UNBLOCK] ERRORE: impossibile leggere address-list da router ${router.ipAddress}: HTTP ${status}`);
return { routerIp: router.ipAddress, success: false, error: "Failed to read address list" }; return { routerIp: router.ipAddress, success: false, error: "Failed to read address list" };
} }
@ -182,14 +221,18 @@ export async function removeFromAddressList(
const entryId = entry[".id"]; const entryId = entry[".id"];
const delResult = await mikrotikRequest(router, "DELETE", `/rest/ip/firewall/address-list/${entryId}`); const delResult = await mikrotikRequest(router, "DELETE", `/rest/ip/firewall/address-list/${entryId}`);
if (delResult.status === 200 || delResult.status === 204) { if (delResult.status === 200 || delResult.status === 204) {
console.log(`[UNBLOCK] OK: ${ipAddress} rimosso da router ${router.ipAddress}`);
return { routerIp: router.ipAddress, success: true }; return { routerIp: router.ipAddress, success: true };
} }
console.error(`[UNBLOCK] FALLITO: eliminazione ${ipAddress} da router ${router.ipAddress}: HTTP ${delResult.status}`);
return { routerIp: router.ipAddress, success: false, error: `Delete failed: ${delResult.status}` }; return { routerIp: router.ipAddress, success: false, error: `Delete failed: ${delResult.status}` };
} }
} }
if (VERBOSE) console.log(`[UNBLOCK] ${ipAddress} non trovato su router ${router.ipAddress} (gia' assente)`);
return { routerIp: router.ipAddress, success: true }; return { routerIp: router.ipAddress, success: true };
} catch (error: any) { } catch (error: any) {
console.error(`[UNBLOCK] ERRORE: ${ipAddress} su router ${router.ipAddress}: ${error.message}`);
return { routerIp: router.ipAddress, success: false, error: error.message }; return { routerIp: router.ipAddress, success: false, error: error.message };
} }
} }
@ -239,14 +282,21 @@ export async function bulkBlockIps(
return { blocked: 0, failed: 0, skipped: 0, details: [] }; return { blocked: 0, failed: 0, skipped: 0, details: [] };
} }
console.log(`[BULK-BLOCK] Starting: ${ipList.length} IPs on ${enabled.length} routers`); console.log(`[BULK-BLOCK] Starting: ${ipList.length} IPs on ${enabled.length} routers (${enabled.map(r => r.ipAddress).join(', ')})`);
const routerStatus = new Map<string, { ok: number; fail: number; skip: number }>();
for (const r of enabled) {
routerStatus.set(r.ipAddress, { ok: 0, fail: 0, skip: 0 });
}
const existingCache = new Map<string, Set<string>>(); const existingCache = new Map<string, Set<string>>();
await Promise.allSettled( await Promise.allSettled(
enabled.map(async (router) => { enabled.map(async (router) => {
const start = Date.now();
const existing = await getExistingBlockedIps(router, listName); const existing = await getExistingBlockedIps(router, listName);
const elapsed = Date.now() - start;
existingCache.set(router.ipAddress, existing); existingCache.set(router.ipAddress, existing);
console.log(`[BULK-BLOCK] Router ${router.ipAddress}: ${existing.size} IPs already in list`); console.log(`[BULK-BLOCK] Router ${router.ipAddress}: ${existing.size} IPs already in list (${elapsed}ms)`);
}) })
); );
@ -274,36 +324,72 @@ export async function bulkBlockIps(
let blocked = 0; let blocked = 0;
let failed = 0; let failed = 0;
const details: Array<{ ip: string; status: string }> = []; const details: Array<{ ip: string; status: string }> = [];
const partialIps: string[] = [];
const failedIps: string[] = [];
async function processIp(ip: string) { async function processIp(ip: string) {
const routerResults = await Promise.allSettled( const routerResults = await Promise.allSettled(
enabled.map(async (router) => { enabled.map(async (router) => {
const existing = existingCache.get(router.ipAddress) || new Set(); const existing = existingCache.get(router.ipAddress) || new Set();
if (existing.has(ip)) return true; if (existing.has(ip)) {
const st = routerStatus.get(router.ipAddress);
if (st) st.skip++;
return { success: true, skipped: true, routerIp: router.ipAddress };
}
const start = Date.now();
const result = await addToAddressList(router, ip, listName, `${commentPrefix} ${ip}`, timeoutDuration); const result = await addToAddressList(router, ip, listName, `${commentPrefix} ${ip}`, timeoutDuration);
return result.success; const elapsed = Date.now() - start;
const st = routerStatus.get(router.ipAddress);
if (result.success) {
if (st) st.ok++;
} else {
if (st) st.fail++;
}
return { success: result.success, skipped: false, routerIp: router.ipAddress, elapsed, error: result.error };
}) })
); );
const perRouterDetail = routerResults.map((r) => {
if (r.status === 'fulfilled') {
const v = r.value;
if (v.skipped) return `${v.routerIp}:SKIP`;
if (v.success) return `${v.routerIp}:OK(${v.elapsed}ms)`;
return `${v.routerIp}:FAIL(${v.elapsed}ms,${v.error})`;
}
return 'REJECTED';
}).join(' | ');
const anySuccess = routerResults.some( const anySuccess = routerResults.some(
(r) => r.status === "fulfilled" && r.value === true (r) => r.status === "fulfilled" && r.value.success
);
const allSuccess = routerResults.every(
(r) => r.status === "fulfilled" && r.value.success
); );
if (anySuccess) { if (anySuccess) {
blocked++; blocked++;
details.push({ ip, status: "blocked" }); details.push({ ip, status: "blocked" });
if (!allSuccess) {
partialIps.push(ip);
if (VERBOSE) console.warn(`[BULK-BLOCK] PARZIALE: IP ${ip}: ${perRouterDetail}`);
}
} else { } else {
failed++; failed++;
failedIps.push(ip);
details.push({ ip, status: "failed" }); details.push({ ip, status: "failed" });
if (VERBOSE) console.error(`[BULK-BLOCK] FALLITO: IP ${ip}: ${perRouterDetail}`);
} }
} }
const bulkStart = Date.now();
for (let i = 0; i < newIps.length; i += concurrency) { for (let i = 0; i < newIps.length; i += concurrency) {
const batch = newIps.slice(i, i + concurrency); const batch = newIps.slice(i, i + concurrency);
await Promise.allSettled(batch.map((ip) => processIp(ip))); await Promise.allSettled(batch.map((ip) => processIp(ip)));
if ((i + concurrency) % 50 === 0 || i + concurrency >= newIps.length) { const progress = Math.min(i + concurrency, newIps.length);
console.log(`[BULK-BLOCK] Progress: ${Math.min(i + concurrency, newIps.length)}/${newIps.length}`); if (progress === newIps.length || progress % 50 === 0) {
const elapsed = ((Date.now() - bulkStart) / 1000).toFixed(1);
console.log(`[BULK-BLOCK] Progress: ${progress}/${newIps.length} (${elapsed}s, ${blocked} ok, ${failed} fail)`);
} }
} }
@ -311,7 +397,17 @@ export async function bulkBlockIps(
details.push({ ip, status: "already_blocked" }); details.push({ ip, status: "already_blocked" });
} }
console.log(`[BULK-BLOCK] Done: ${blocked} blocked, ${failed} failed, ${skippedIps.length} skipped`); const totalElapsed = ((Date.now() - bulkStart) / 1000).toFixed(1);
routerStatus.forEach((st, routerIp) => {
console.log(`[BULK-BLOCK] Router ${routerIp}: ${st.ok} blocked, ${st.fail} failed, ${st.skip} skipped`);
});
console.log(`[BULK-BLOCK] Completato in ${totalElapsed}s: ${blocked} blocked, ${failed} failed, ${skippedIps.length} already_blocked, ${partialIps.length} parziali`);
if (failedIps.length > 0) {
console.error(`[BULK-BLOCK] IP non bloccati su nessun router (${failedIps.length}): ${failedIps.slice(0, 20).join(', ')}${failedIps.length > 20 ? '...' : ''}`);
}
if (partialIps.length > 0) {
console.warn(`[BULK-BLOCK] IP bloccati solo parzialmente (${partialIps.length}): ${partialIps.slice(0, 20).join(', ')}${partialIps.length > 20 ? '...' : ''}`);
}
return { blocked, failed, skipped: skippedIps.length, details }; return { blocked, failed, skipped: skippedIps.length, details };
} }

View File

@ -672,7 +672,8 @@ export async function registerRoutes(app: Express): Promise<Server> {
} }
const ipList = rows.map((r: any) => r.source_ip); const ipList = rows.map((r: any) => r.source_ip);
console.log(`[BLOCK-ALL] Avvio blocco massivo: ${ipList.length}/${totalUnblocked} IP con score >= ${min_score} su ${enabledRouters.length} router`); const routerInfo = enabledRouters.map((r: any) => `${r.name || r.ipAddress}(${r.ipAddress}:${r.apiPort})`).join(', ');
console.log(`[BLOCK-ALL] Avvio blocco massivo: ${ipList.length}/${totalUnblocked} IP con score >= ${min_score} su ${enabledRouters.length} router: ${routerInfo}`);
const result = await bulkBlockIps( const result = await bulkBlockIps(
enabledRouters as any, enabledRouters as any,
@ -779,39 +780,43 @@ export async function registerRoutes(app: Express): Promise<Server> {
// Services monitoring // Services monitoring
app.get("/api/services/status", async (req, res) => { app.get("/api/services/status", async (req, res) => {
try { try {
const mkService = (name: string) => ({ name, status: "unknown" as string, healthy: false, details: null as any, systemdUnit: "" as string, type: "service" as string });
const services = { const services = {
mlBackend: { name: "ML Backend Python", status: "unknown", healthy: false, details: null as any }, nodeBackend: { ...mkService("Node.js Backend"), systemdUnit: "ids-backend", type: "service" },
database: { name: "PostgreSQL Database", status: "unknown", healthy: false, details: null as any }, mlBackend: { ...mkService("ML Backend Python"), systemdUnit: "ids-ml-backend", type: "service" },
syslogParser: { name: "Syslog Parser", status: "unknown", healthy: false, details: null as any }, database: { ...mkService("PostgreSQL Database"), systemdUnit: "postgresql-16", type: "service" },
analyticsAggregator: { name: "Analytics Aggregator Timer", status: "unknown", healthy: false, details: null as any }, syslogParser: { ...mkService("Syslog Parser"), systemdUnit: "ids-syslog-parser", type: "service" },
analyticsAggregator: { ...mkService("Analytics Aggregator"), systemdUnit: "ids-analytics-aggregator", type: "timer" },
autoBlock: { ...mkService("Auto Block"), systemdUnit: "ids-auto-block", type: "timer" },
cleanup: { ...mkService("Cleanup Detections"), systemdUnit: "ids-cleanup", type: "timer" },
listFetcher: { ...mkService("Public Lists Fetcher"), systemdUnit: "ids-list-fetcher", type: "timer" },
mlTraining: { ...mkService("ML Training Settimanale"), systemdUnit: "ids-ml-training", type: "timer" },
}; };
// Node.js Backend - always running if this endpoint responds
services.nodeBackend.status = "running";
services.nodeBackend.healthy = true;
services.nodeBackend.details = { port: 5000, uptime: process.uptime().toFixed(0) + "s" };
// Check ML Backend Python // Check ML Backend Python
try { try {
const controller = new AbortController(); const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 5000); const timeout = setTimeout(() => controller.abort(), 5000);
const response = await fetch(`${ML_BACKEND_URL}/health`, { signal: controller.signal });
const response = await fetch(`${ML_BACKEND_URL}/health`, {
signal: controller.signal,
});
clearTimeout(timeout); clearTimeout(timeout);
if (response.ok) { if (response.ok) {
const data = await response.json(); const data = await response.json();
services.mlBackend.status = "running"; services.mlBackend.status = "running";
services.mlBackend.healthy = true; services.mlBackend.healthy = true;
services.mlBackend.details = { services.mlBackend.details = { modelLoaded: data.ml_model === "loaded", timestamp: data.timestamp };
modelLoaded: data.ml_model === "loaded",
timestamp: data.timestamp,
};
} else { } else {
services.mlBackend.status = "error"; services.mlBackend.status = "error";
services.mlBackend.details = { error: `HTTP ${response.status}` }; services.mlBackend.details = { error: `HTTP ${response.status}` };
} }
} catch (error: any) { } catch (error: any) {
services.mlBackend.status = "offline"; services.mlBackend.status = "offline";
services.mlBackend.details = { error: error.code === 'ECONNREFUSED' ? "Connection refused" : error.message }; services.mlBackend.details = { error: error.code === 'ECONNREFUSED' ? "Connessione rifiutata" : error.message };
} }
// Check Database // Check Database
@ -827,87 +832,156 @@ export async function registerRoutes(app: Express): Promise<Server> {
services.database.details = { error: error.message }; services.database.details = { error: error.message };
} }
// Check Syslog Parser via database (independent of ML Backend) // Check Syslog Parser via database
try { try {
const recentLogsResult = await db.execute( const recentLogsResult = await db.execute(
sql`SELECT COUNT(*) as count, MAX(timestamp) as last_log sql`SELECT COUNT(*) as count, MAX(timestamp) as last_log FROM network_logs WHERE timestamp > NOW() - INTERVAL '30 minutes'`
FROM network_logs
WHERE timestamp > NOW() - INTERVAL '30 minutes'`
); );
const logRows = (recentLogsResult as any).rows || recentLogsResult; const logRows = (recentLogsResult as any).rows || recentLogsResult;
const recentLogCount = parseInt(logRows[0]?.count || "0"); const recentLogCount = parseInt(logRows[0]?.count || "0");
const lastLogTime = logRows[0]?.last_log; const lastLogTime = logRows[0]?.last_log;
if (recentLogCount > 0) { if (recentLogCount > 0) {
services.syslogParser.status = "running"; services.syslogParser.status = "running";
services.syslogParser.healthy = true; services.syslogParser.healthy = true;
services.syslogParser.details = { services.syslogParser.details = { recentLogs30min: recentLogCount, lastLog: lastLogTime };
recentLogs30min: recentLogCount,
lastLog: lastLogTime,
};
} else { } else {
const lastLogEverResult = await db.execute( const lastLogEverResult = await db.execute(sql`SELECT MAX(timestamp) as last_log FROM network_logs`);
sql`SELECT MAX(timestamp) as last_log FROM network_logs`
);
const lastLogEverRows = (lastLogEverResult as any).rows || lastLogEverResult; const lastLogEverRows = (lastLogEverResult as any).rows || lastLogEverResult;
const lastLogEver = lastLogEverRows[0]?.last_log;
services.syslogParser.status = "offline"; services.syslogParser.status = "offline";
services.syslogParser.healthy = false; services.syslogParser.healthy = false;
services.syslogParser.details = { services.syslogParser.details = { recentLogs30min: 0, lastLog: lastLogEverRows[0]?.last_log || "Mai", warning: "Nessun log negli ultimi 30 minuti" };
recentLogs30min: 0,
lastLog: lastLogEver || "Never",
warning: "No logs received in last 30 minutes",
};
} }
} catch (error: any) { } catch (error: any) {
services.syslogParser.status = "error"; services.syslogParser.status = "error";
services.syslogParser.healthy = false;
services.syslogParser.details = { error: error.message }; services.syslogParser.details = { error: error.message };
} }
// Check Analytics Aggregator (via last record timestamp) // Check Analytics Aggregator (via last record timestamp)
try { try {
const latestAnalytics = await db const latestAnalytics = await db.select().from(networkAnalytics).orderBy(desc(networkAnalytics.date), desc(networkAnalytics.hour)).limit(1);
.select()
.from(networkAnalytics)
.orderBy(desc(networkAnalytics.date), desc(networkAnalytics.hour))
.limit(1);
if (latestAnalytics.length > 0) { if (latestAnalytics.length > 0) {
const lastRun = new Date(latestAnalytics[0].date); const lastRun = new Date(latestAnalytics[0].date);
const lastTimestamp = lastRun.toISOString(); const hoursSince = (Date.now() - lastRun.getTime()) / (1000 * 60 * 60);
const hoursSinceLastRun = (Date.now() - lastRun.getTime()) / (1000 * 60 * 60); if (hoursSince < 2) {
if (hoursSinceLastRun < 2) {
services.analyticsAggregator.status = "running"; services.analyticsAggregator.status = "running";
services.analyticsAggregator.healthy = true; services.analyticsAggregator.healthy = true;
services.analyticsAggregator.details = { services.analyticsAggregator.details = { lastRun: latestAnalytics[0].date, hoursSinceLastRun: hoursSince.toFixed(1) };
lastRun: latestAnalytics[0].date,
lastTimestamp,
hoursSinceLastRun: hoursSinceLastRun.toFixed(1),
};
} else { } else {
services.analyticsAggregator.status = "idle"; services.analyticsAggregator.status = "idle";
services.analyticsAggregator.healthy = false; services.analyticsAggregator.details = { lastRun: latestAnalytics[0].date, hoursSinceLastRun: hoursSince.toFixed(1), warning: "Nessuna aggregazione nelle ultime 2 ore" };
services.analyticsAggregator.details = {
lastRun: latestAnalytics[0].date,
lastTimestamp,
hoursSinceLastRun: hoursSinceLastRun.toFixed(1),
warning: "No aggregation in last 2 hours",
};
} }
} else { } else {
services.analyticsAggregator.status = "idle"; services.analyticsAggregator.status = "idle";
services.analyticsAggregator.healthy = false; services.analyticsAggregator.details = { error: "Nessun dato analytics trovato" };
services.analyticsAggregator.details = { error: "No analytics data found" };
} }
} catch (error: any) { } catch (error: any) {
services.analyticsAggregator.status = "error"; services.analyticsAggregator.status = "error";
services.analyticsAggregator.healthy = false;
services.analyticsAggregator.details = { error: error.message }; services.analyticsAggregator.details = { error: error.message };
} }
// Check Auto Block (via recent blocked detections)
try {
const recentBlockResult = await db.execute(
sql`SELECT COUNT(*) as count, MAX(detected_at) as last_block FROM detections WHERE blocked = true AND detected_at > NOW() - INTERVAL '10 minutes'`
);
const blockRows = (recentBlockResult as any).rows || recentBlockResult;
const recentBlocks = parseInt(blockRows[0]?.count || "0");
const lastBlock = blockRows[0]?.last_block;
const totalBlockedResult = await db.execute(sql`SELECT COUNT(*) as count FROM detections WHERE blocked = true`);
const totalBlockedRows = (totalBlockedResult as any).rows || totalBlockedResult;
const totalBlocked = parseInt(totalBlockedRows[0]?.count || "0");
services.autoBlock.status = recentBlocks > 0 ? "running" : "idle";
services.autoBlock.healthy = true;
services.autoBlock.details = {
recentBlocks10min: recentBlocks,
totalBlocked,
lastBlock: lastBlock || "Mai",
interval: "ogni 5 minuti"
};
} catch (error: any) {
services.autoBlock.status = "error";
services.autoBlock.details = { error: error.message };
}
// Check Cleanup (via absence of old detections)
try {
const oldDetResult = await db.execute(
sql`SELECT COUNT(*) as count FROM detections WHERE detected_at < NOW() - INTERVAL '48 hours'`
);
const oldRows = (oldDetResult as any).rows || oldDetResult;
const oldDetections = parseInt(oldRows[0]?.count || "0");
const totalDetResult = await db.execute(sql`SELECT COUNT(*) as count FROM detections`);
const totalRows = (totalDetResult as any).rows || totalDetResult;
const totalDetections = parseInt(totalRows[0]?.count || "0");
services.cleanup.status = oldDetections === 0 ? "running" : "idle";
services.cleanup.healthy = oldDetections === 0;
services.cleanup.details = {
oldDetections48h: oldDetections,
totalDetections,
interval: "ogni ora",
warning: oldDetections > 0 ? `${oldDetections} detection vecchie non ancora pulite` : undefined
};
} catch (error: any) {
services.cleanup.status = "error";
services.cleanup.details = { error: error.message };
}
// Check List Fetcher (via public lists last_updated)
try {
const listsResult = await db.execute(
sql`SELECT COUNT(*) as total,
COUNT(*) FILTER (WHERE enabled = true) as enabled,
MAX(last_fetch) as last_fetch
FROM public_lists`
);
const listRows = (listsResult as any).rows || listsResult;
const totalLists = parseInt(listRows[0]?.total || "0");
const enabledLists = parseInt(listRows[0]?.enabled || "0");
const lastFetched = listRows[0]?.last_fetch;
if (lastFetched) {
const hoursSince = (Date.now() - new Date(lastFetched).getTime()) / (1000 * 60 * 60);
services.listFetcher.status = hoursSince < 1 ? "running" : "idle";
services.listFetcher.healthy = hoursSince < 1;
services.listFetcher.details = { totalLists, enabledLists, lastFetched, hoursSinceLastFetch: hoursSince.toFixed(1), interval: "ogni 10 minuti" };
} else {
services.listFetcher.status = "idle";
services.listFetcher.details = { totalLists, enabledLists, lastFetched: "Mai", interval: "ogni 10 minuti" };
}
} catch (error: any) {
services.listFetcher.status = "error";
services.listFetcher.details = { error: error.message };
}
// Check ML Training (via training history)
try {
const latestTraining = await db.select().from(trainingHistory).orderBy(desc(trainingHistory.trainedAt)).limit(1);
if (latestTraining.length > 0) {
const lastTrainDate = new Date(latestTraining[0].trainedAt);
const daysSince = (Date.now() - lastTrainDate.getTime()) / (1000 * 60 * 60 * 24);
services.mlTraining.status = daysSince < 8 ? "running" : "idle";
services.mlTraining.healthy = daysSince < 8;
services.mlTraining.details = {
lastTraining: latestTraining[0].trainedAt,
daysSinceLastTraining: daysSince.toFixed(1),
lastStatus: latestTraining[0].status,
lastModel: latestTraining[0].modelVersion,
recordsProcessed: latestTraining[0].recordsProcessed,
interval: "settimanale"
};
} else {
services.mlTraining.status = "idle";
services.mlTraining.details = { lastTraining: "Mai", interval: "settimanale" };
}
} catch (error: any) {
services.mlTraining.status = "error";
services.mlTraining.details = { error: error.message };
}
res.json({ services }); res.json({ services });
} catch (error: any) { } catch (error: any) {
res.status(500).json({ error: "Failed to check services status" }); res.status(500).json({ error: "Failed to check services status" });
@ -915,7 +989,11 @@ export async function registerRoutes(app: Express): Promise<Server> {
}); });
// Service Control Endpoints (Secured - only allow specific systemd operations) // Service Control Endpoints (Secured - only allow specific systemd operations)
const ALLOWED_SERVICES = ["ids-ml-backend", "ids-syslog-parser"]; const ALLOWED_SERVICES = [
"ids-ml-backend", "ids-syslog-parser", "ids-backend",
"ids-analytics-aggregator", "ids-auto-block", "ids-cleanup",
"ids-list-fetcher", "ids-ml-training"
];
const ALLOWED_ACTIONS = ["start", "stop", "restart", "status"]; const ALLOWED_ACTIONS = ["start", "stop", "restart", "status"];
app.post("/api/services/:service/:action", async (req, res) => { app.post("/api/services/:service/:action", async (req, res) => {

View File

@ -1,7 +1,49 @@
{ {
"version": "1.0.115", "version": "1.0.122",
"lastUpdate": "2026-02-16T14:40:14.777Z", "lastUpdate": "2026-02-17T09:13:40.571Z",
"changelog": [ "changelog": [
{
"version": "1.0.122",
"date": "2026-02-17",
"type": "patch",
"description": "Deployment automatico v1.0.122"
},
{
"version": "1.0.121",
"date": "2026-02-17",
"type": "patch",
"description": "Deployment automatico v1.0.121"
},
{
"version": "1.0.120",
"date": "2026-02-17",
"type": "patch",
"description": "Deployment automatico v1.0.120"
},
{
"version": "1.0.119",
"date": "2026-02-17",
"type": "patch",
"description": "Deployment automatico v1.0.119"
},
{
"version": "1.0.118",
"date": "2026-02-16",
"type": "patch",
"description": "Deployment automatico v1.0.118"
},
{
"version": "1.0.117",
"date": "2026-02-16",
"type": "patch",
"description": "Deployment automatico v1.0.117"
},
{
"version": "1.0.116",
"date": "2026-02-16",
"type": "patch",
"description": "Deployment automatico v1.0.116"
},
{ {
"version": "1.0.115", "version": "1.0.115",
"date": "2026-02-16", "date": "2026-02-16",
@ -259,48 +301,6 @@
"date": "2025-11-25", "date": "2025-11-25",
"type": "patch", "type": "patch",
"description": "Deployment automatico v1.0.73" "description": "Deployment automatico v1.0.73"
},
{
"version": "1.0.72",
"date": "2025-11-25",
"type": "patch",
"description": "Deployment automatico v1.0.72"
},
{
"version": "1.0.71",
"date": "2025-11-25",
"type": "patch",
"description": "Deployment automatico v1.0.71"
},
{
"version": "1.0.70",
"date": "2025-11-25",
"type": "patch",
"description": "Deployment automatico v1.0.70"
},
{
"version": "1.0.69",
"date": "2025-11-25",
"type": "patch",
"description": "Deployment automatico v1.0.69"
},
{
"version": "1.0.68",
"date": "2025-11-24",
"type": "patch",
"description": "Deployment automatico v1.0.68"
},
{
"version": "1.0.67",
"date": "2025-11-24",
"type": "patch",
"description": "Deployment automatico v1.0.67"
},
{
"version": "1.0.66",
"date": "2025-11-24",
"type": "patch",
"description": "Deployment automatico v1.0.66"
} }
] ]
} }