File size: 4,016 Bytes
892886a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import streamlit as st
import pandas as pd
import ipaddress
import plotly.express as px
import os

# 📌 Définition du plan d'adressage de l'Université
UNIVERSITY_IP_RANGES = [
    "192.168.0.0/16",
    "10.0.0.0/8",
    "172.16.0.0/12"
]

# 📌 Fichier cache pour accélérer les chargements suivants
CACHE_FILE = "logs_cache.parquet"

# 📌 Fonction optimisée pour lire un gros fichier .log par morceaux (chunks)
@st.cache_data
def load_logs(file, max_lines=1000000):
    col_names = ["timestamp", "ipsource", "ipdestination", "protocole", "portsource", "portdest",
                 "regle1", "status", "interface", "inconnu", "regle2"]
    
    logs_list = []
    chunk_size = 50000  # Charger les logs par paquets de 50 000 lignes pour éviter de saturer la mémoire
    total_loaded = 0

    with st.spinner("⏳ Chargement des logs..."):
        for chunk in pd.read_csv(file, sep=";", names=col_names, parse_dates=["timestamp"], dtype=str, chunksize=chunk_size):
            chunk["portsource"] = pd.to_numeric(chunk["portsource"], errors='coerce')
            chunk["portdest"] = pd.to_numeric(chunk["portdest"], errors='coerce')
            logs_list.append(chunk)
            total_loaded += chunk.shape[0]
            
            if total_loaded >= max_lines:
                break  # On stoppe après max_lines lignes pour un chargement plus rapide

    df = pd.concat(logs_list, ignore_index=True)
    return df

# 📌 Traitement des logs pour extraire les statistiques demandées
def process_logs(df):
    # 📊 1️⃣ TOP 5 des IP sources les plus émettrices
    df_top_ips = df["ipsource"].value_counts().nlargest(5).reset_index()
    df_top_ips.columns = ["ipsource", "count"]

    # 📊 2️⃣ TOP 10 des ports < 1024 avec accès autorisé
    df_ports = df[(df["portdest"] < 1024) & (df["status"] == "PERMIT")]
    df_top_ports = df_ports["portdest"].value_counts().nlargest(10).reset_index()
    df_top_ports.columns = ["portdest", "count"]

    # 🚫 3️⃣ Lister les accès hors plan d’adressage universitaire
    df["is_outside"] = df["ipsource"].apply(lambda ip: not any(ipaddress.ip_address(ip) in ipaddress.ip_network(net) for net in UNIVERSITY_IP_RANGES))
    df_outside_university = df[df["is_outside"]]

    return df_top_ips, df_top_ports, df_outside_university

# 🎨 Interface Streamlit
st.title("⚡ Analyse Optimisée des Logs Réseau")

# 📂 Upload du fichier log
uploaded_file = st.file_uploader("📂 Charger un fichier .log", type="log")

# 🚀 CHARGEMENT OPTIMISÉ
if uploaded_file:
    if os.path.exists(CACHE_FILE):
        st.info("📂 Chargement des logs depuis le cache...")
        df_logs = pd.read_parquet(CACHE_FILE)
    else:
        df_logs = load_logs(uploaded_file)  # Charger seulement 200 000 lignes pour un affichage rapide
        df_logs.to_parquet(CACHE_FILE)  # Stocker en cache pour éviter de recharger à chaque fois

    # 📌 Traitement des logs
    df_top_ips, df_top_ports, df_outside_university = process_logs(df_logs)

    # 📊 TOP 5 des IP sources les plus émettrices
    st.subheader("📊 TOP 5 des IP sources les plus émettrices")
    fig_ips = px.bar(df_top_ips, x="ipsource", y="count", title="TOP 5 IP Sources")
    st.plotly_chart(fig_ips, use_container_width=True)

    # 📊 TOP 10 des ports < 1024 avec accès autorisé
    st.subheader("📊 TOP 10 des ports < 1024 avec accès autorisé")
    fig_ports = px.bar(df_top_ports, x="portdest", y="count", title="TOP 10 Ports Destinataires < 1024 Autorisés")
    st.plotly_chart(fig_ports, use_container_width=True)

    # 🚫 Liste des accès hors plan d’adressage universitaire
    st.subheader("🚫 Accès hors plan d’adressage universitaire")
    st.dataframe(df_outside_university)

    # 💾 Télécharger les résultats filtrés
    st.download_button("💾 Télécharger les IP hors plan d'adressage", df_outside_university.to_csv(index=False), file_name="ips_hors_universite.csv")

st.info("📌 Charge un fichier `.log` pour voir l'analyse.")