diff --git a/.replit b/.replit index e303f0e..af7007c 100644 --- a/.replit +++ b/.replit @@ -14,10 +14,6 @@ run = ["npm", "run", "start"] localPort = 5000 externalPort = 80 -[[ports]] -localPort = 45045 -externalPort = 3000 - [env] PORT = "5000" diff --git a/attached_assets/Pasted--python3-11-main-py-8-60594-root-ids-python-ml-Starting-IDS-API-on-http-0-0-0-0-8000-Do-1763402969617_1763402969617.txt b/attached_assets/Pasted--python3-11-main-py-8-60594-root-ids-python-ml-Starting-IDS-API-on-http-0-0-0-0-8000-Do-1763402969617_1763402969617.txt new file mode 100644 index 0000000..c8e2964 --- /dev/null +++ b/attached_assets/Pasted--python3-11-main-py-8-60594-root-ids-python-ml-Starting-IDS-API-on-http-0-0-0-0-8000-Do-1763402969617_1763402969617.txt @@ -0,0 +1,79 @@ + python3.11 main.py & +[8] 60594 +[root@ids python_ml]# οš€ Starting IDS API on http://0.0.0.0:8000 +ο“š Docs available at http://0.0.0.0:8000/docs +INFO: Started server process [60594] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit) +INFO: 127.0.0.1:56130 - "GET /health HTTP/1.1" 200 OK +INFO: 127.0.0.1:46150 - "GET /health HTTP/1.1" 200 OK +INFO: 127.0.0.1:46162 - "GET /health HTTP/1.1" 200 OK +INFO: 127.0.0.1:38422 - "POST /train HTTP/1.1" 200 OK +[TRAINING] Estrazione feature da 100000 log... +[TRAINING] Feature estratte per 2431 IP unici +[TRAINING] Normalizzazione features... +[TRAINING] Addestramento Isolation Forest (contamination=0.01)... +[SAVE] Modello salvato in models +[TRAINING] Completato! 25/2431 IP anomali rilevati +[TRAIN ERROR] relation "training_history" does not exist +LINE 2: INSERT INTO training_history + ^ + +INFO: 127.0.0.1:40108 - "POST /detect HTTP/1.1" 500 Internal Server Error +INFO: 127.0.0.1:59452 - "GET /health HTTP/1.1" 200 OK +^C +[root@ids python_ml]# curl -X POST http://localhost:8000/detect \ + -H "Content-Type: application/json" \ + -d '{ + "max_records": 50000, + "auto_block": false, + "risk_threshold": 75 + }' +INFO: 127.0.0.1:60376 - "POST /detect HTTP/1.1" 200 OK +{"detections":[{"source_ip":"198.251.84.34","risk_score":100.0,"confidence":100.0,"anomaly_type":"ddos","reason":"Alta frequenza connessioni (392 conn/s); Burst anomali (max +3958 conn/10s)","log_count":10195,"first_seen":"2025-11-17T19:07:26","last_seen":"2025-11-17T19:07:52"},{"source_ip":"185.203.24.22","risk_score":96.87409746595517,"confidence":96.87409746595517,"anomaly_type":"brute_force","reason":"Burst anomali (max 762 conn/10s)","log_count":1658,"first_seen":"2025-11-17T19:07:26","last_seen":"2025-11-17T19:07:51"},{"source_ip":"185.203.26.201","risk_score":96.43235451556359,"confidence":96.43235451556359,"anomaly_type":"ddos","reason":"Alta frequenza connessioni (108 conn/s); Burst anomali (max 928 conn/10s)","log_count":2808,"first_seen":"2025-11-17T19:07:26","last_seen":"2025-11-17T19:07:52"},{"source_ip":"185.203.25.211","risk_score":95.88185436081642,"confidence":95.88185436081642,"anomaly_type":"brute_force","reason":"Burst anomali (max 700 conn/10s)","log_count":1174,"first_seen":"2025-11-17T19:07:27","last_seen":"2025-11-17T19:07:52"},{"source_ip":"185.203.25.233","risk_score":95.88185436081642,"confidence":95.88185436081642,"anomaly_type":"brute_force","reason":"Burst anomali (max 674 conn/10s)","log_count":1748,"first_seen":"2025-11-17T19:07:26","last_seen":"2025-11-17T19:07:52"},{"source_ip":"82.62.84.108","risk_score":92.72541858310075,"confidence":92.72541858310075,"anomaly_type":"brute_force","reason":"Burst anomali (max 396 conn/10s)","log_count":1046,"first_seen":"2025-11-17T19:07:26","last_seen":"2025-11-17T19:07:52"},{"source_ip":"10.0.254.133","risk_score":91.54425805202949,"confidence":91.54425805202949,"anomaly_type":"brute_force","reason":"Burst anomali (max 300 conn/10s)","log_count":604,"first_seen":"2025-11-17T19:07:32","last_seen":"2025-11-17T19:07:51"},{"source_ip":"10.1.0.254","risk_score":91.54425805202949,"confidence":91.54425805202949,"anomaly_type":"brute_force","reason":"Burst anomali (max 412 conn/10s)","log_count":894,"first_seen":"2025-11-17T19:07:26","last_seen":"2025-11-17T19:07:52"},{"source_ip":"185.203.24.23","risk_score":89.1027834206094,"confidence":89.1027834206094,"anomaly_type":"brute_force","reason":"Burst anomali (max 356 conn/10s)","log_count":698,"first_seen":"2025-11-17T19:07:26","last_seen":"2025-11-17T19:07:52"},{"source_ip":"126.220.199.81","risk_score":88.78712205056635,"confidence":88.78712205056635,"anomaly_type":"brute_force","reason":"Burst anomali (max 268 conn/10s)","log_count":746,"first_seen":"2025-11-17T19:07:26","last_seen":"2025-11-17T19:07:52"},{"source_ip":"79.124.56.186","risk_score":86.59534183084894,"confidence":86.59534183084894,"anomaly_type":"brute_force","reason":"Burst anomali (max 228 conn/10s)","log_count":532,"first_seen":"2025-11-17T19:07:26","last_seen":"2025-11-17T19:07:52"},{"source_ip":"10.0.254.29","risk_score":86.47026991411408,"confidence":86.47026991411408,"anomaly_type":"brute_force","reason":"Burst anomali (max 248 conn/10s)","log_count":260,"first_seen":"2025-11-17T19:07:43","last_seen":"2025-11-17T19:07:52"},{"source_ip":"185.203.24.2","risk_score":85.9534138699736,"confidence":85.9534138699736,"anomaly_type":"brute_force","reason":"Burst anomali (max 296 conn/10s)","log_count":502,"first_seen":"2025-11-17T19:07:26","last_seen":"2025-11-17T19:07:50"},{"source_ip":"92.247.211.188","risk_score":85.87164149615063,"confidence":85.87164149615063,"anomaly_type":"brute_force","reason":"Burst anomali (max 222 conn/10s)","log_count":522,"first_seen":"2025-11-17T19:07:26","last_seen":"2025-11-17T19:07:52"},{"source_ip":"65.108.39.39","risk_score":84.5366862611293,"confidence":84.5366862611293,"anomaly_type":"brute_force","reason":"Burst anomali (max 178 conn/10s)","log_count":472,"first_seen":"2025-11-17T19:07:26","last_seen":"2025-11-17T19:07:52"},{"source_ip":"185.203.25.69","risk_score":83.92450216776822,"confidence":83.92450216776822,"anomaly_type":"brute_force","reason":"Burst anomali (max 234 conn/10s)","log_count":406,"first_seen":"2025-11-17T19:07:27","last_seen":"2025-11-17T19:07:52"},{"source_ip":"79.124.49.174","risk_score":83.61934080057665,"confidence":83.61934080057665,"anomaly_type":"brute_force","reason":"Burst anomali (max 160 conn/10s)","log_count":380,"first_seen":"2025-11-17T19:07:26","last_seen":"2025-11-17T19:07:52"},{"source_ip":"185.203.25.254","risk_score":82.50570022464548,"confidence":82.50570022464548,"anomaly_type":"brute_force","reason":"Burst anomali (max 166 conn/10s)","log_count":397,"first_seen":"2025-11-17T19:07:26","last_seen":"2025-11-17T19:07:52"},{"source_ip":"67.213.119.137","risk_score":81.7805049846674,"confidence":81.7805049846674,"anomaly_type":"brute_force","reason":"Burst anomali (max 156 conn/10s)","log_count":354,"first_seen":"2025-11-17T19:07:26","last_seen":"2025-11-17T19:07:52"},{"source_ip":"10.0.254.205","risk_score":81.50046686823227,"confidence":81.50046686823227,"anomaly_type":"brute_force","reason":"Burst anomali (max 208 conn/10s)","log_count":280,"first_seen":"2025-11-17T19:07:29","last_seen":"2025-11-17T19:07:52"},{"source_ip":"160.202.129.17","risk_score":81.47969100137351,"confidence":81.47969100137351,"anomaly_type":"brute_force","reason":"Burst anomali (max 162 conn/10s)","log_count":350,"first_seen":"2025-11-17T19:07:26","last_seen":"2025-11-17T19:07:52"}],"total":21,"blocked":0,"message":"Trovate 21 anomalie"}[root@ids python_ml]# psql -h 127.0.0.1 -U ids_user -psql -h 127.0.0.1 -U ids_user -d ids_database -c " +SELECT source_ip, risk_score, confidence, log_count, detected_at +FROM detections +WHERE risk_score >= 75 +ORDER BY risk_score DESC +LIMIT 20; +" + source_ip | risk_score | confidence | log_count | detected_at +----------------+------------+------------+-----------+---------------------------- + 198.251.84.34 | 100.00 | 100.00 | 10195 | 2025-11-17 19:07:53.288029 + 185.203.24.22 | 96.87 | 96.87 | 1658 | 2025-11-17 19:07:53.288029 + 185.203.26.201 | 96.43 | 96.43 | 2808 | 2025-11-17 19:07:53.288029 + 185.203.25.233 | 95.88 | 95.88 | 1748 | 2025-11-17 19:07:53.288029 + 185.203.25.211 | 95.88 | 95.88 | 1174 | 2025-11-17 19:07:53.288029 + 82.62.84.108 | 92.73 | 92.73 | 1046 | 2025-11-17 19:07:53.288029 + 10.1.0.254 | 91.54 | 91.54 | 894 | 2025-11-17 19:07:53.288029 + 10.0.254.133 | 91.54 | 91.54 | 604 | 2025-11-17 19:07:53.288029 + 185.203.24.23 | 89.10 | 89.10 | 698 | 2025-11-17 19:07:53.288029 + 126.220.199.81 | 88.79 | 88.79 | 746 | 2025-11-17 19:07:53.288029 + 79.124.56.186 | 86.60 | 86.60 | 532 | 2025-11-17 19:07:53.288029 + 10.0.254.29 | 86.47 | 86.47 | 260 | 2025-11-17 19:07:53.288029 + 185.203.24.2 | 85.95 | 85.95 | 502 | 2025-11-17 19:07:53.288029 + 92.247.211.188 | 85.87 | 85.87 | 522 | 2025-11-17 19:07:53.288029 + 65.108.39.39 | 84.54 | 84.54 | 472 | 2025-11-17 19:07:53.288029 + 185.203.25.69 | 83.92 | 83.92 | 406 | 2025-11-17 19:07:53.288029 + 79.124.49.174 | 83.62 | 83.62 | 380 | 2025-11-17 19:07:53.288029 + 185.203.25.254 | 82.51 | 82.51 | 397 | 2025-11-17 19:07:53.288029 + 67.213.119.137 | 81.78 | 81.78 | 354 | 2025-11-17 19:07:53.288029 + 10.0.254.205 | 81.50 | 81.50 | 280 | 2025-11-17 19:07:53.288029 +(20 rows) + +[root@ids python_ml]# psql -h 127.0.0.1 -U ids_user -d ids_database -c " +SELECT model_version, records_processed, features_count, status, trained_at +FROM training_history +ORDER BY trained_at DESC +LIMIT 10; +> " + model_version | records_processed | features_count | status | trained_at +---------------+-------------------+----------------+--------+------------ +(0 rows) + +[root@ids python_ml]# curl http://localhost:8000/stats +INFO: 127.0.0.1:46636 - "GET /stats HTTP/1.1" 500 Internal Server Error +{"detail":"column \"logged_at\" does not exist\nLINE 3: WHERE logged_at >= NOW() - INTERVAL '1 hour'\n ^\n"}[root@ids python_ml]# +[root@ids python_ml]# \ No newline at end of file diff --git a/python_ml/cron_detect.sh b/python_ml/cron_detect.sh new file mode 100644 index 0000000..4083734 --- /dev/null +++ b/python_ml/cron_detect.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# ========================================================= +# CRON DETECTION - Rilevamento anomalie automatico +# ========================================================= +# Esegue detection ogni 5 minuti con blocco automatico IP critici +# ========================================================= + +# Logging +LOG_FILE="/var/log/ids/detection.log" +mkdir -p /var/log/ids +exec >> "$LOG_FILE" 2>&1 + +echo "=========================================" +echo "πŸ” [$(date)] DETECTION AUTOMATICA AVVIATA" +echo "=========================================" + +# Esegue detection via API con auto-block +curl -X POST http://localhost:8000/detect \ + -H "Content-Type: application/json" \ + -d '{ + "max_records": 50000, + "hours_back": 1, + "risk_threshold": 75, + "auto_block": true + }' \ + --max-time 120 + +EXIT_CODE=$? + +if [ $EXIT_CODE -eq 0 ]; then + echo "βœ… [$(date)] Detection completata con successo" +else + echo "❌ [$(date)] Detection fallita (exit code: $EXIT_CODE)" +fi + +echo "" diff --git a/python_ml/cron_train.sh b/python_ml/cron_train.sh new file mode 100644 index 0000000..06a89c6 --- /dev/null +++ b/python_ml/cron_train.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# ========================================================= +# CRON TRAINING - Addestramento automatico modello ML +# ========================================================= +# Esegue training ogni 12 ore con 100K log piΓΉ recenti +# ========================================================= + +# Logging +LOG_FILE="/var/log/ids/training.log" +mkdir -p /var/log/ids +exec >> "$LOG_FILE" 2>&1 + +echo "=========================================" +echo "πŸ€– [$(date)] TRAINING AUTOMATICO AVVIATO" +echo "=========================================" + +# Esegue training via API +curl -X POST http://localhost:8000/train \ + -H "Content-Type: application/json" \ + -d '{ + "max_records": 100000, + "hours_back": 24, + "contamination": 0.01 + }' \ + --max-time 300 + +EXIT_CODE=$? + +if [ $EXIT_CODE -eq 0 ]; then + echo "βœ… [$(date)] Training completato con successo" +else + echo "❌ [$(date)] Training fallito (exit code: $EXIT_CODE)" +fi + +echo "" diff --git a/python_ml/main.py b/python_ml/main.py index 124fda3..cbdbfb7 100644 --- a/python_ml/main.py +++ b/python_ml/main.py @@ -392,7 +392,7 @@ async def get_stats(): cursor.execute(""" SELECT COUNT(*) as recent FROM network_logs - WHERE logged_at >= NOW() - INTERVAL '1 hour' + WHERE timestamp >= NOW() - INTERVAL '1 hour' """) recent_logs = cursor.fetchone()['recent']