DDoS_Detect_Sim / app.py
EdBoy2202's picture
Create app.py
f1e3e91 verified
Raw
History Blame Contribute Delete
10.8 kB
import streamlit as st
import pandas as pd
import time
import random
import folium
from folium.plugins import MarkerCluster
from streamlit_folium import st_folium
import pygeoip
from collections import deque, OrderedDict
import datetime
import plotly.graph_objs as go
from plotly.subplots import make_subplots
# Function to get geolocation
def get_geolocation(ip):
gi = pygeoip.GeoIP('GeoLiteCity.dat')
try:
return gi.record_by_addr(ip)
except:
return None
# Function to simulate a DDoS attack
def simulate_ddos_attack():
simulated_ips = [f"192.168.1.{random.randint(1, 255)}" for _ in range(10)]
packets = random.randint(50, 200) # Random packet count
return simulated_ips, packets
# Set up the Streamlit app
st.title("Real-Time Network Traffic DDoS Monitor")
# Create a single stop button at the top of the app
stop_button = st.button('Stop', key='stop_button')
# Statistics section
st.header("Statistics")
col1, col2, col3 = st.columns(3)
with col1:
total_packets = st.empty()
with col2:
ddos_flows = st.empty()
with col3:
benign_flows = st.empty()
# Divider line
st.markdown("---")
# Active Flows section
st.header("Active Flows")
# Create placeholders for the tables, graphs, and map
active_flows_placeholder = st.empty()
malicious_ips_placeholder = st.empty()
graphs_placeholder = st.empty()
map_placeholder = st.empty()
# Initialize map in session state if it doesn't exist
if 'map' not in st.session_state:
st.session_state.map = folium.Map(location=[0, 0], zoom_start=2)
st.session_state.marker_cluster = MarkerCluster().add_to(st.session_state.map)
st.session_state.map_counter = 0
m = st.session_state.map
marker_cluster = st.session_state.marker_cluster
# Display the initial map
st_folium(m, width=700, height=500, key="initial_map")
# Load data in chunks
chunk_size = 1000 # Adjust this value based on your needs
data_iterator = pd.read_csv('SSDP_Flood_output_copy.csv', chunksize=chunk_size)
# Initialize data structures
if 'ip_packet_counts' not in st.session_state:
st.session_state.ip_packet_counts = {}
if 'time_series_data' not in st.session_state:
st.session_state.time_series_data = []
if 'ip_packet_time_series' not in st.session_state:
st.session_state.ip_packet_time_series = {}
if 'recent_rows' not in st.session_state:
st.session_state.recent_rows = deque(maxlen=10) # Correctly structured as a deque
if 'malicious_ips' not in st.session_state:
st.session_state.malicious_ips = OrderedDict()
# Initialize counters
if 'total_packet_count' not in st.session_state:
st.session_state.total_packet_count = 0
if 'ddos_flow_count' not in st.session_state:
st.session_state.ddos_flow_count = 0
if 'benign_flow_count' not in st.session_state:
st.session_state.benign_flow_count = 0
# Flag to track if the map needs updating
map_updated = False
# Display Simulate DDoS Attack button
if st.button("Simulate DDoS Attack"):
simulated_ips, packets = simulate_ddos_attack()
current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
for ip in simulated_ips:
# Create a structured row to append
row = {
'time': current_time,
'src': ip,
'sport': random.randint(1024, 65535),
'dst': '192.168.0.1', # Target IP
'dport': 80, # Target port
'protocol': 'TCP',
'packets': packets,
'label': 1 # Simulate as malicious
}
# Ensure the row is appended correctly
st.session_state.recent_rows.append(row)
# Update counters
st.session_state.total_packet_count += packets
st.session_state.ddos_flow_count += 1
# Update the statistics
total_packets.metric("Total Packets", st.session_state.total_packet_count)
ddos_flows.metric("DDoS Flows", st.session_state.ddos_flow_count)
benign_flows.metric("Benign Flows", st.session_state.benign_flow_count)
# Convert recent_rows deque to DataFrame
try:
active_flows_df = pd.DataFrame(list(st.session_state.recent_rows))
# Ensure DataFrame has expected columns
if not {'time', 'src', 'sport', 'dst', 'dport', 'protocol', 'packets'}.issubset(active_flows_df.columns):
st.error("DataFrame does not have the expected structure.")
continue
# Update active flows
active_flows_placeholder.dataframe(
active_flows_df[['time', 'src', 'sport', 'dst', 'dport', 'protocol', 'packets']],
height=300,
use_container_width=True,
hide_index=True
)
# Update the map with the simulated IP
geo_info = get_geolocation(ip)
if geo_info:
folium.Marker(
location=[geo_info['latitude'], geo_info['longitude']],
popup=ip,
icon=folium.Icon(color='red', icon='info-sign')
).add_to(marker_cluster)
# Update the map view
map_updated = True
except Exception as e:
st.error(f"Error creating DataFrame: {str(e)}")
if map_updated:
map_placeholder.empty()
st.session_state.map_counter += 1
st_folium(m, width=700, height=500, key=f"map_{st.session_state.map_counter}")
map_updated = False
# Process data in chunks
for chunk_index, chunk in enumerate(data_iterator):
for row_index, row in chunk.iterrows():
if stop_button:
st.write('Stopped by user')
break
# Update counters
st.session_state.total_packet_count += row['packets']
if row['label'] == 1:
st.session_state.ddos_flow_count += 1
else:
st.session_state.benign_flow_count += 1
# Update statistics
total_packets.metric("Total Packets", st.session_state.total_packet_count)
ddos_flows.metric("DDoS Flows", st.session_state.ddos_flow_count)
benign_flows.metric("Benign Flows", st.session_state.benign_flow_count)
# Update the time column with current time
current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
row['time'] = current_time
# Update active flows table
st.session_state.recent_rows.append(dict(row)) # Append the dictionary of the row
# Convert recent_rows deque to DataFrame
try:
active_flows_df = pd.DataFrame(list(st.session_state.recent_rows))
active_flows_placeholder.dataframe(
active_flows_df[['time', 'src', 'sport', 'dst', 'dport', 'protocol', 'packets']],
height=300,
use_container_width=True,
hide_index=True
)
except Exception as e:
st.error(f"Error creating DataFrame: {str(e)}")
# Update the malicious IPs list if the IP is malicious
if row['label'] == 1:
if row['src'] not in st.session_state.malicious_ips:
st.session_state.malicious_ips[row['src']] = True
if len(st.session_state.malicious_ips) > 10:
st.session_state.malicious_ips.popitem(last=False)
# Add new malicious IP to the map
geo_info = get_geolocation(row['src'])
if geo_info:
folium.Marker(
location=[geo_info['latitude'], geo_info['longitude']],
popup=row['src'],
icon=folium.Icon(color='red', icon='info-sign')
).add_to(marker_cluster)
# Set flag to update map
map_updated = True
# Format malicious IPs as a numbered list
malicious_ips_text = "**Recent Malicious IPs:**\n"
for i, ip in enumerate(st.session_state.malicious_ips.keys(), 1):
malicious_ips_text += f"{i}. <span style='color: red;'>{ip}</span>\n"
malicious_ips_placeholder.markdown(malicious_ips_text, unsafe_allow_html=True)
# Update packet counts for the source IP
src_ip = row['src']
packets = row['packets']
if src_ip not in st.session_state.ip_packet_counts:
st.session_state.ip_packet_counts[src_ip] = 0
st.session_state.ip_packet_time_series[src_ip] = []
st.session_state.ip_packet_counts[src_ip] += packets
st.session_state.ip_packet_time_series[src_ip].append((current_time, st.session_state.ip_packet_counts[src_ip]))
# Add current total packet count to time series data
st.session_state.time_series_data.append((current_time, st.session_state.total_packet_count))
# Create and update the graphs
if len(st.session_state.ip_packet_counts) > 0:
fig = make_subplots(rows=3, cols=1,
subplot_titles=("Top 10 Source IPs by Packet Count",
"Total Packet Count Over Time",
"Packet Count per Source IP Over Time"))
top_ips = sorted(st.session_state.ip_packet_counts.items(), key=lambda x: x[1], reverse=True)[:10]
ips, counts = zip(*top_ips)
fig.add_trace(go.Bar(x=ips, y=counts), row=1, col=1)
times, packet_counts = zip(*st.session_state.time_series_data[-100:])
fig.add_trace(go.Scatter(x=times, y=packet_counts, mode='lines'), row=2, col=1)
for ip in ips:
ip_times, ip_counts = zip(*st.session_state.ip_packet_time_series[ip][-100:])
fig.add_trace(go.Scatter(x=ip_times, y=ip_counts, mode='lines', name=ip), row=3, col=1)
fig.update_layout(height=1200, showlegend=True)
fig.update_xaxes(title_text="Source IP", row=1, col=1)
fig.update_xaxes(title_text="Time", row=2, col=1)
fig.update_xaxes(title_text="Time", row=3, col=1)
fig.update_yaxes(title_text="Packet Count", row=1, col=1)
fig.update_yaxes(title_text="Total Packet Count", row=2, col=1)
fig.update_yaxes(title_text="Packet Count", row=3, col=1)
graphs_placeholder.plotly_chart(fig, use_container_width=True)
# Update the map if new points were added
if map_updated:
map_placeholder.empty()
st.session_state.map_counter += 1
st_folium(m, width=700, height=500, key=f"map_{st.session_state.map_counter}")
map_updated = False
time.sleep(0.1)
if stop_button:
break
st.write("Data processing complete")