Sumayyea commited on
Commit
834f533
Β·
verified Β·
1 Parent(s): c365f6b

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +985 -0
  2. requirements.txt +4 -0
app.py ADDED
@@ -0,0 +1,985 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Cybersecurity Threat Monitoring Dashboard
3
+ A comprehensive multi-page dashboard built with Streamlit
4
+ Deployed on Hugging Face Spaces
5
+ """
6
+
7
+ import streamlit as st
8
+ import pandas as pd
9
+ import numpy as np
10
+ import plotly.express as px
11
+ import plotly.graph_objects as go
12
+ from datetime import datetime, timedelta
13
+ import random
14
+ import time
15
+
16
+ # Page configuration
17
+ st.set_page_config(
18
+ page_title="CyberShield - Threat Monitor",
19
+ page_icon="πŸ›‘οΈ",
20
+ layout="wide",
21
+ initial_sidebar_state="expanded"
22
+ )
23
+
24
+ # Load custom CSS for dark theme
25
+ def load_css():
26
+ st.markdown("""
27
+ <style>
28
+ /* Main dark theme */
29
+ .stApp {
30
+ background-color: #0a0a0f;
31
+ }
32
+
33
+ /* Sidebar styling */
34
+ [data-testid="stSidebar"] {
35
+ background-color: #12121a;
36
+ border-right: 1px solid #1e1e2e;
37
+ }
38
+
39
+ /* Metric cards */
40
+ .metric-card {
41
+ background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
42
+ border: 1px solid #0f3460;
43
+ border-radius: 10px;
44
+ padding: 20px;
45
+ text-align: center;
46
+ box-shadow: 0 4px 15px rgba(0, 255, 255, 0.1);
47
+ }
48
+
49
+ .metric-value {
50
+ font-size: 2.5rem;
51
+ font-weight: bold;
52
+ color: #00ffff;
53
+ text-shadow: 0 0 10px rgba(0, 255, 255, 0.5);
54
+ }
55
+
56
+ .metric-label {
57
+ font-size: 0.9rem;
58
+ color: #888;
59
+ text-transform: uppercase;
60
+ letter-spacing: 1px;
61
+ }
62
+
63
+ .metric-critical { color: #ff4757; text-shadow: 0 0 10px rgba(255, 71, 87, 0.5); }
64
+ .metric-high { color: #ff7f50; text-shadow: 0 0 10px rgba(255, 127, 80, 0.5); }
65
+ .metric-medium { color: #ffa502; text-shadow: 0 0 10px rgba(255, 165, 2, 0.5); }
66
+ .metric-low { color: #2ed573; text-shadow: 0 0 10px rgba(46, 213, 115, 0.5); }
67
+
68
+ /* Alert box */
69
+ .alert-critical {
70
+ background: linear-gradient(90deg, rgba(255,71,87,0.2) 0%, rgba(255,71,87,0.05) 100%);
71
+ border-left: 4px solid #ff4757;
72
+ padding: 15px;
73
+ margin: 10px 0;
74
+ border-radius: 5px;
75
+ }
76
+
77
+ .alert-high {
78
+ background: linear-gradient(90deg, rgba(255,127,80,0.2) 0%, rgba(255,127,80,0.05) 100%);
79
+ border-left: 4px solid #ff7f50;
80
+ padding: 15px;
81
+ margin: 10px 0;
82
+ border-radius: 5px;
83
+ }
84
+
85
+ /* Header styling */
86
+ .main-header {
87
+ background: linear-gradient(90deg, #0f3460 0%, #1a1a2e 50%, #0f3460 100%);
88
+ padding: 20px;
89
+ border-radius: 10px;
90
+ margin-bottom: 20px;
91
+ border: 1px solid #00ffff33;
92
+ text-align: center;
93
+ }
94
+
95
+ .main-header h1 {
96
+ color: #00ffff;
97
+ text-shadow: 0 0 20px rgba(0, 255, 255, 0.5);
98
+ margin: 0;
99
+ }
100
+
101
+ /* Table styling */
102
+ .dataframe {
103
+ background-color: #1a1a2e !important;
104
+ }
105
+
106
+ /* Status indicators */
107
+ .status-dot {
108
+ height: 10px;
109
+ width: 10px;
110
+ border-radius: 50%;
111
+ display: inline-block;
112
+ margin-right: 5px;
113
+ animation: pulse 2s infinite;
114
+ }
115
+
116
+ .status-active { background-color: #2ed573; }
117
+ .status-warning { background-color: #ffa502; }
118
+ .status-danger { background-color: #ff4757; }
119
+
120
+ @keyframes pulse {
121
+ 0% { opacity: 1; }
122
+ 50% { opacity: 0.5; }
123
+ 100% { opacity: 1; }
124
+ }
125
+
126
+ /* Scrollbar styling */
127
+ ::-webkit-scrollbar {
128
+ width: 8px;
129
+ height: 8px;
130
+ }
131
+
132
+ ::-webkit-scrollbar-track {
133
+ background: #1a1a2e;
134
+ }
135
+
136
+ ::-webkit-scrollbar-thumb {
137
+ background: #0f3460;
138
+ border-radius: 4px;
139
+ }
140
+
141
+ ::-webkit-scrollbar-thumb:hover {
142
+ background: #00ffff;
143
+ }
144
+ </style>
145
+ """, unsafe_allow_html=True)
146
+
147
+ load_css()
148
+
149
+ # ============== DATA GENERATION ==============
150
+
151
+ # Cache the data generation to improve performance
152
+ @st.cache_data(ttl=60)
153
+ def generate_threat_data(num_records=500):
154
+ """Generate realistic simulated threat data"""
155
+
156
+ attack_types = [
157
+ 'DDoS Attack', 'SQL Injection', 'XSS Attack', 'Brute Force',
158
+ 'Malware', 'Phishing', 'Ransomware', 'Man-in-the-Middle',
159
+ 'Zero-Day Exploit', 'Port Scanning', 'DNS Tunneling', 'Credential Stuffing'
160
+ ]
161
+
162
+ severities = ['Critical', 'High', 'Medium', 'Low']
163
+ severity_weights = [0.1, 0.25, 0.4, 0.25]
164
+
165
+ statuses = ['Active', 'Mitigated', 'Investigating', 'Blocked']
166
+ status_weights = [0.3, 0.25, 0.25, 0.2]
167
+
168
+ countries = [
169
+ ('Russia', 'RUS', 55.7558, 37.6173),
170
+ ('China', 'CHN', 39.9042, 116.4074),
171
+ ('United States', 'USA', 37.0902, -95.7129),
172
+ ('North Korea', 'PRK', 39.0392, 125.7625),
173
+ ('Iran', 'IRN', 35.6892, 51.3890),
174
+ ('Brazil', 'BRA', -14.2350, -51.9253),
175
+ ('India', 'IND', 20.5937, 78.9629),
176
+ ('Nigeria', 'NGA', 9.0820, 8.6753),
177
+ ('Vietnam', 'VNM', 14.0583, 108.2772),
178
+ ('Indonesia', 'IDN', -0.7893, 113.9213),
179
+ ('Ukraine', 'UKR', 48.3794, 31.1656),
180
+ ('Romania', 'ROU', 45.9432, 24.9668),
181
+ ('Germany', 'DEU', 51.1657, 10.4515),
182
+ ('Netherlands', 'NLD', 52.1326, 5.2913),
183
+ ('Turkey', 'TUR', 38.9637, 35.2433)
184
+ ]
185
+
186
+ target_countries = ['United States', 'United Kingdom', 'Germany', 'France', 'Japan', 'Australia', 'Canada']
187
+
188
+ common_ports = [22, 23, 25, 53, 80, 443, 445, 3306, 3389, 5432, 8080, 8443, 27017]
189
+
190
+ protocols = ['TCP', 'UDP', 'ICMP', 'HTTP', 'HTTPS', 'SSH', 'FTP', 'SMTP', 'DNS']
191
+
192
+ # Generate timestamps over the last 7 days
193
+ end_time = datetime.now()
194
+ start_time = end_time - timedelta(days=7)
195
+
196
+ data = []
197
+ for i in range(num_records):
198
+ country_data = random.choice(countries)
199
+ timestamp = start_time + timedelta(
200
+ seconds=random.randint(0, int((end_time - start_time).total_seconds()))
201
+ )
202
+
203
+ # Generate realistic IP
204
+ source_ip = f"{random.randint(1,223)}.{random.randint(0,255)}.{random.randint(0,255)}.{random.randint(1,254)}"
205
+ dest_ip = f"192.168.{random.randint(1,10)}.{random.randint(1,254)}"
206
+
207
+ attack_type = random.choice(attack_types)
208
+ severity = random.choices(severities, weights=severity_weights)[0]
209
+
210
+ data.append({
211
+ 'id': f'THR-{str(i+1).zfill(6)}',
212
+ 'timestamp': timestamp,
213
+ 'attack_type': attack_type,
214
+ 'severity': severity,
215
+ 'source_ip': source_ip,
216
+ 'source_country': country_data[0],
217
+ 'country_code': country_data[1],
218
+ 'latitude': country_data[2] + random.uniform(-5, 5),
219
+ 'longitude': country_data[3] + random.uniform(-5, 5),
220
+ 'destination_ip': dest_ip,
221
+ 'target_country': random.choice(target_countries),
222
+ 'port': random.choice(common_ports),
223
+ 'protocol': random.choice(protocols),
224
+ 'status': random.choices(statuses, weights=status_weights)[0],
225
+ 'packets': random.randint(100, 100000),
226
+ 'bytes': random.randint(10000, 10000000),
227
+ 'confidence': random.randint(60, 99)
228
+ })
229
+
230
+ return pd.DataFrame(data)
231
+
232
+ @st.cache_data(ttl=60)
233
+ def generate_network_metrics():
234
+ """Generate network traffic metrics"""
235
+ return {
236
+ 'total_bandwidth': random.uniform(500, 1000),
237
+ 'incoming_traffic': random.uniform(200, 500),
238
+ 'outgoing_traffic': random.uniform(150, 400),
239
+ 'blocked_requests': random.randint(1000, 5000),
240
+ 'active_connections': random.randint(500, 2000),
241
+ 'avg_response_time': random.uniform(10, 100),
242
+ 'uptime': 99.97,
243
+ 'threats_blocked_today': random.randint(100, 500)
244
+ }
245
+
246
+ def generate_alerts(df):
247
+ """Generate recent critical alerts"""
248
+ critical_threats = df[df['severity'].isin(['Critical', 'High'])].sort_values('timestamp', ascending=False).head(10)
249
+ return critical_threats
250
+
251
+ # ============== SIDEBAR ==============
252
+
253
+ def render_sidebar():
254
+ with st.sidebar:
255
+ st.markdown("""
256
+ <div style='text-align: center; padding: 20px 0;'>
257
+ <h1 style='color: #00ffff; font-size: 1.8rem;'>πŸ›‘οΈ CyberShield</h1>
258
+ <p style='color: #888; font-size: 0.8rem;'>Threat Monitoring System v2.0</p>
259
+ </div>
260
+ """, unsafe_allow_html=True)
261
+
262
+ st.markdown("---")
263
+
264
+ # Navigation
265
+ st.markdown("### πŸ“ Navigation")
266
+ page = st.radio(
267
+ "Select Page",
268
+ ["🏠 Overview", "πŸ“Š Threat Feed", "🌍 Geographic Analysis", "πŸ”Œ Network Analysis", "🚨 Alerts"],
269
+ label_visibility="collapsed"
270
+ )
271
+
272
+ st.markdown("---")
273
+
274
+ # Filters
275
+ st.markdown("### πŸ” Filters")
276
+
277
+ # Date range filter
278
+ date_range = st.date_input(
279
+ "Date Range",
280
+ value=(datetime.now() - timedelta(days=7), datetime.now()),
281
+ max_value=datetime.now()
282
+ )
283
+
284
+ # Severity filter
285
+ severity_filter = st.multiselect(
286
+ "Severity",
287
+ ["Critical", "High", "Medium", "Low"],
288
+ default=["Critical", "High", "Medium", "Low"]
289
+ )
290
+
291
+ # Attack type filter
292
+ attack_types = [
293
+ 'DDoS Attack', 'SQL Injection', 'XSS Attack', 'Brute Force',
294
+ 'Malware', 'Phishing', 'Ransomware', 'Man-in-the-Middle',
295
+ 'Zero-Day Exploit', 'Port Scanning', 'DNS Tunneling', 'Credential Stuffing'
296
+ ]
297
+ attack_filter = st.multiselect(
298
+ "Attack Types",
299
+ attack_types,
300
+ default=attack_types
301
+ )
302
+
303
+ st.markdown("---")
304
+
305
+ # System status
306
+ st.markdown("### πŸ’» System Status")
307
+ st.markdown("""
308
+ <div style='padding: 10px; background: #1a1a2e; border-radius: 5px;'>
309
+ <p><span class='status-dot status-active'></span> Firewall: Active</p>
310
+ <p><span class='status-dot status-active'></span> IDS/IPS: Active</p>
311
+ <p><span class='status-dot status-active'></span> SIEM: Connected</p>
312
+ <p><span class='status-dot status-warning'></span> Threat Intel: Updating</p>
313
+ </div>
314
+ """, unsafe_allow_html=True)
315
+
316
+ st.markdown("---")
317
+ st.markdown("""
318
+ <div style='text-align: center; color: #666; font-size: 0.7rem;'>
319
+ <p>Last Updated: """ + datetime.now().strftime("%Y-%m-%d %H:%M:%S") + """</p>
320
+ <p>Β© 2024 CyberShield</p>
321
+ </div>
322
+ """, unsafe_allow_html=True)
323
+
324
+ return page, date_range, severity_filter, attack_filter
325
+
326
+ # ============== PAGE FUNCTIONS ==============
327
+
328
+ def overview_page(df, metrics):
329
+ """Main overview dashboard page"""
330
+
331
+ # Header
332
+ st.markdown("""
333
+ <div class='main-header'>
334
+ <h1>πŸ›‘οΈ CYBERSHIELD THREAT MONITOR</h1>
335
+ <p style='color: #888;'>Real-time Security Operations Dashboard</p>
336
+ </div>
337
+ """, unsafe_allow_html=True)
338
+
339
+ # Key metrics row
340
+ col1, col2, col3, col4, col5 = st.columns(5)
341
+
342
+ total_threats = len(df)
343
+ critical_count = len(df[df['severity'] == 'Critical'])
344
+ high_count = len(df[df['severity'] == 'High'])
345
+ blocked_count = len(df[df['status'] == 'Blocked'])
346
+ active_count = len(df[df['status'] == 'Active'])
347
+
348
+ with col1:
349
+ st.markdown(f"""
350
+ <div class='metric-card'>
351
+ <div class='metric-value'>{total_threats:,}</div>
352
+ <div class='metric-label'>Total Threats</div>
353
+ </div>
354
+ """, unsafe_allow_html=True)
355
+
356
+ with col2:
357
+ st.markdown(f"""
358
+ <div class='metric-card'>
359
+ <div class='metric-value metric-critical'>{critical_count}</div>
360
+ <div class='metric-label'>Critical</div>
361
+ </div>
362
+ """, unsafe_allow_html=True)
363
+
364
+ with col3:
365
+ st.markdown(f"""
366
+ <div class='metric-card'>
367
+ <div class='metric-value metric-high'>{high_count}</div>
368
+ <div class='metric-label'>High Severity</div>
369
+ </div>
370
+ """, unsafe_allow_html=True)
371
+
372
+ with col4:
373
+ st.markdown(f"""
374
+ <div class='metric-card'>
375
+ <div class='metric-value metric-low'>{blocked_count}</div>
376
+ <div class='metric-label'>Blocked</div>
377
+ </div>
378
+ """, unsafe_allow_html=True)
379
+
380
+ with col5:
381
+ st.markdown(f"""
382
+ <div class='metric-card'>
383
+ <div class='metric-value' style='color: #ff6b6b;'>{active_count}</div>
384
+ <div class='metric-label'>Active Threats</div>
385
+ </div>
386
+ """, unsafe_allow_html=True)
387
+
388
+ st.markdown("<br>", unsafe_allow_html=True)
389
+
390
+ # Charts row 1
391
+ col1, col2 = st.columns(2)
392
+
393
+ with col1:
394
+ st.markdown("### πŸ“ˆ Threat Timeline (7 Days)")
395
+ df_timeline = df.copy()
396
+ df_timeline['date'] = df_timeline['timestamp'].dt.date
397
+ timeline_data = df_timeline.groupby(['date', 'severity']).size().reset_index(name='count')
398
+
399
+ fig_timeline = px.area(
400
+ timeline_data,
401
+ x='date',
402
+ y='count',
403
+ color='severity',
404
+ color_discrete_map={
405
+ 'Critical': '#ff4757',
406
+ 'High': '#ff7f50',
407
+ 'Medium': '#ffa502',
408
+ 'Low': '#2ed573'
409
+ }
410
+ )
411
+ fig_timeline.update_layout(
412
+ plot_bgcolor='rgba(0,0,0,0)',
413
+ paper_bgcolor='rgba(0,0,0,0)',
414
+ font_color='#888',
415
+ legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1),
416
+ margin=dict(l=0, r=0, t=30, b=0),
417
+ xaxis=dict(gridcolor='#1a1a2e'),
418
+ yaxis=dict(gridcolor='#1a1a2e')
419
+ )
420
+ st.plotly_chart(fig_timeline, use_container_width=True)
421
+
422
+ with col2:
423
+ st.markdown("### 🎯 Threat Severity Distribution")
424
+ severity_counts = df['severity'].value_counts()
425
+
426
+ fig_severity = go.Figure(data=[go.Pie(
427
+ labels=severity_counts.index,
428
+ values=severity_counts.values,
429
+ hole=0.6,
430
+ marker_colors=['#ff4757', '#ff7f50', '#ffa502', '#2ed573']
431
+ )])
432
+ fig_severity.update_layout(
433
+ plot_bgcolor='rgba(0,0,0,0)',
434
+ paper_bgcolor='rgba(0,0,0,0)',
435
+ font_color='#888',
436
+ showlegend=True,
437
+ legend=dict(orientation="h", yanchor="bottom", y=-0.1, xanchor="center", x=0.5),
438
+ margin=dict(l=0, r=0, t=30, b=0),
439
+ annotations=[dict(text='Threats', x=0.5, y=0.5, font_size=16, showarrow=False, font_color='#00ffff')]
440
+ )
441
+ st.plotly_chart(fig_severity, use_container_width=True)
442
+
443
+ # Charts row 2
444
+ col1, col2 = st.columns(2)
445
+
446
+ with col1:
447
+ st.markdown("### βš”οΈ Attack Type Distribution")
448
+ attack_counts = df['attack_type'].value_counts().head(10)
449
+
450
+ fig_attacks = px.bar(
451
+ x=attack_counts.values,
452
+ y=attack_counts.index,
453
+ orientation='h',
454
+ color=attack_counts.values,
455
+ color_continuous_scale='Tealgrn'
456
+ )
457
+ fig_attacks.update_layout(
458
+ plot_bgcolor='rgba(0,0,0,0)',
459
+ paper_bgcolor='rgba(0,0,0,0)',
460
+ font_color='#888',
461
+ showlegend=False,
462
+ margin=dict(l=0, r=0, t=10, b=0),
463
+ xaxis=dict(gridcolor='#1a1a2e', title='Count'),
464
+ yaxis=dict(gridcolor='#1a1a2e', title=''),
465
+ coloraxis_showscale=False
466
+ )
467
+ st.plotly_chart(fig_attacks, use_container_width=True)
468
+
469
+ with col2:
470
+ st.markdown("### πŸ”Œ Top Targeted Ports")
471
+ port_counts = df['port'].value_counts().head(10)
472
+
473
+ fig_ports = px.bar(
474
+ x=port_counts.index.astype(str),
475
+ y=port_counts.values,
476
+ color=port_counts.values,
477
+ color_continuous_scale='Reds'
478
+ )
479
+ fig_ports.update_layout(
480
+ plot_bgcolor='rgba(0,0,0,0)',
481
+ paper_bgcolor='rgba(0,0,0,0)',
482
+ font_color='#888',
483
+ showlegend=False,
484
+ margin=dict(l=0, r=0, t=10, b=0),
485
+ xaxis=dict(gridcolor='#1a1a2e', title='Port'),
486
+ yaxis=dict(gridcolor='#1a1a2e', title='Attacks'),
487
+ coloraxis_showscale=False
488
+ )
489
+ st.plotly_chart(fig_ports, use_container_width=True)
490
+
491
+ # Recent alerts section
492
+ st.markdown("### 🚨 Recent Critical Alerts")
493
+ recent_critical = df[df['severity'].isin(['Critical', 'High'])].sort_values('timestamp', ascending=False).head(5)
494
+
495
+ for _, alert in recent_critical.iterrows():
496
+ alert_class = 'alert-critical' if alert['severity'] == 'Critical' else 'alert-high'
497
+ st.markdown(f"""
498
+ <div class='{alert_class}'>
499
+ <strong>{alert['severity'].upper()}</strong> | {alert['attack_type']} |
500
+ Source: {alert['source_ip']} ({alert['source_country']}) |
501
+ Target Port: {alert['port']} |
502
+ {alert['timestamp'].strftime('%Y-%m-%d %H:%M:%S')}
503
+ </div>
504
+ """, unsafe_allow_html=True)
505
+
506
+
507
+ def threat_feed_page(df):
508
+ """Threat feed page with detailed table"""
509
+
510
+ st.markdown("## πŸ“Š Live Threat Feed")
511
+ st.markdown("Real-time view of all detected threats with detailed information")
512
+
513
+ # Search functionality
514
+ search = st.text_input("πŸ” Search (IP, Attack Type, Country)", "")
515
+
516
+ # Apply search filter
517
+ if search:
518
+ mask = (
519
+ df['source_ip'].str.contains(search, case=False, na=False) |
520
+ df['attack_type'].str.contains(search, case=False, na=False) |
521
+ df['source_country'].str.contains(search, case=False, na=False)
522
+ )
523
+ filtered_df = df[mask]
524
+ else:
525
+ filtered_df = df
526
+
527
+ # Sort by timestamp
528
+ filtered_df = filtered_df.sort_values('timestamp', ascending=False)
529
+
530
+ # Display metrics
531
+ col1, col2, col3, col4 = st.columns(4)
532
+ col1.metric("Total Records", len(filtered_df))
533
+ col2.metric("Critical", len(filtered_df[filtered_df['severity'] == 'Critical']))
534
+ col3.metric("Active", len(filtered_df[filtered_df['status'] == 'Active']))
535
+ col4.metric("Blocked", len(filtered_df[filtered_df['status'] == 'Blocked']))
536
+
537
+ # Format dataframe for display
538
+ display_df = filtered_df[[
539
+ 'id', 'timestamp', 'attack_type', 'severity', 'source_ip',
540
+ 'source_country', 'port', 'protocol', 'status', 'confidence'
541
+ ]].copy()
542
+ display_df['timestamp'] = display_df['timestamp'].dt.strftime('%Y-%m-%d %H:%M:%S')
543
+ display_df.columns = ['ID', 'Timestamp', 'Attack Type', 'Severity', 'Source IP',
544
+ 'Country', 'Port', 'Protocol', 'Status', 'Confidence %']
545
+
546
+ # Color code severity
547
+ def highlight_severity(row):
548
+ colors = {
549
+ 'Critical': 'background-color: rgba(255,71,87,0.3)',
550
+ 'High': 'background-color: rgba(255,127,80,0.3)',
551
+ 'Medium': 'background-color: rgba(255,165,2,0.3)',
552
+ 'Low': 'background-color: rgba(46,213,115,0.3)'
553
+ }
554
+ return [colors.get(row['Severity'], '')] * len(row)
555
+
556
+ st.dataframe(
557
+ display_df.head(100).style.apply(highlight_severity, axis=1),
558
+ use_container_width=True,
559
+ height=600
560
+ )
561
+
562
+ st.info(f"Showing {min(100, len(display_df))} of {len(display_df)} records")
563
+
564
+
565
+ def geographic_page(df):
566
+ """Geographic analysis page with world map"""
567
+
568
+ st.markdown("## 🌍 Geographic Threat Analysis")
569
+ st.markdown("Visualize attack origins and target locations worldwide")
570
+
571
+ col1, col2 = st.columns([2, 1])
572
+
573
+ with col1:
574
+ st.markdown("### πŸ—ΊοΈ Global Attack Origins")
575
+
576
+ # Aggregate by country for bubble size
577
+ country_stats = df.groupby(['source_country', 'country_code', 'latitude', 'longitude']).agg({
578
+ 'id': 'count',
579
+ 'severity': lambda x: (x == 'Critical').sum()
580
+ }).reset_index()
581
+ country_stats.columns = ['country', 'code', 'lat', 'lon', 'total_attacks', 'critical_attacks']
582
+
583
+ # Create map
584
+ fig_map = px.scatter_geo(
585
+ country_stats,
586
+ lat='lat',
587
+ lon='lon',
588
+ size='total_attacks',
589
+ color='critical_attacks',
590
+ hover_name='country',
591
+ hover_data={'total_attacks': True, 'critical_attacks': True, 'lat': False, 'lon': False},
592
+ color_continuous_scale='Reds',
593
+ size_max=50,
594
+ projection='natural earth'
595
+ )
596
+
597
+ fig_map.update_layout(
598
+ geo=dict(
599
+ bgcolor='rgba(0,0,0,0)',
600
+ landcolor='#1a1a2e',
601
+ oceancolor='#0a0a0f',
602
+ countrycolor='#333',
603
+ coastlinecolor='#333',
604
+ showocean=True,
605
+ showland=True,
606
+ showcountries=True
607
+ ),
608
+ plot_bgcolor='rgba(0,0,0,0)',
609
+ paper_bgcolor='rgba(0,0,0,0)',
610
+ font_color='#888',
611
+ margin=dict(l=0, r=0, t=0, b=0),
612
+ coloraxis_colorbar=dict(title='Critical')
613
+ )
614
+
615
+ st.plotly_chart(fig_map, use_container_width=True)
616
+
617
+ with col2:
618
+ st.markdown("### 🏴 Top Attack Sources")
619
+ top_countries = df['source_country'].value_counts().head(10)
620
+
621
+ fig_countries = px.bar(
622
+ x=top_countries.values,
623
+ y=top_countries.index,
624
+ orientation='h',
625
+ color=top_countries.values,
626
+ color_continuous_scale='Reds'
627
+ )
628
+ fig_countries.update_layout(
629
+ plot_bgcolor='rgba(0,0,0,0)',
630
+ paper_bgcolor='rgba(0,0,0,0)',
631
+ font_color='#888',
632
+ showlegend=False,
633
+ margin=dict(l=0, r=0, t=10, b=0),
634
+ xaxis=dict(gridcolor='#1a1a2e', title='Attacks'),
635
+ yaxis=dict(gridcolor='#1a1a2e', title=''),
636
+ coloraxis_showscale=False,
637
+ height=400
638
+ )
639
+ st.plotly_chart(fig_countries, use_container_width=True)
640
+
641
+ # Target countries
642
+ col1, col2 = st.columns(2)
643
+
644
+ with col1:
645
+ st.markdown("### 🎯 Top Targeted Countries")
646
+ target_counts = df['target_country'].value_counts()
647
+
648
+ fig_targets = px.pie(
649
+ values=target_counts.values,
650
+ names=target_counts.index,
651
+ hole=0.4,
652
+ color_discrete_sequence=px.colors.sequential.Tealgrn
653
+ )
654
+ fig_targets.update_layout(
655
+ plot_bgcolor='rgba(0,0,0,0)',
656
+ paper_bgcolor='rgba(0,0,0,0)',
657
+ font_color='#888',
658
+ margin=dict(l=0, r=0, t=10, b=0)
659
+ )
660
+ st.plotly_chart(fig_targets, use_container_width=True)
661
+
662
+ with col2:
663
+ st.markdown("### πŸ“Š Attack Flow by Country")
664
+ # Country-wise severity breakdown
665
+ country_severity = df.groupby(['source_country', 'severity']).size().reset_index(name='count')
666
+ country_severity = country_severity[country_severity['source_country'].isin(top_countries.index[:8])]
667
+
668
+ fig_flow = px.bar(
669
+ country_severity,
670
+ x='source_country',
671
+ y='count',
672
+ color='severity',
673
+ barmode='stack',
674
+ color_discrete_map={
675
+ 'Critical': '#ff4757',
676
+ 'High': '#ff7f50',
677
+ 'Medium': '#ffa502',
678
+ 'Low': '#2ed573'
679
+ }
680
+ )
681
+ fig_flow.update_layout(
682
+ plot_bgcolor='rgba(0,0,0,0)',
683
+ paper_bgcolor='rgba(0,0,0,0)',
684
+ font_color='#888',
685
+ margin=dict(l=0, r=0, t=10, b=0),
686
+ xaxis=dict(gridcolor='#1a1a2e', title=''),
687
+ yaxis=dict(gridcolor='#1a1a2e', title='Attacks'),
688
+ legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1)
689
+ )
690
+ st.plotly_chart(fig_flow, use_container_width=True)
691
+
692
+
693
+ def network_page(df, metrics):
694
+ """Network analysis page"""
695
+
696
+ st.markdown("## πŸ”Œ Network Analysis")
697
+ st.markdown("Monitor network traffic and identify suspicious patterns")
698
+
699
+ # Network metrics
700
+ col1, col2, col3, col4 = st.columns(4)
701
+
702
+ with col1:
703
+ st.markdown(f"""
704
+ <div class='metric-card'>
705
+ <div class='metric-value'>{metrics['total_bandwidth']:.1f}</div>
706
+ <div class='metric-label'>Bandwidth (Gbps)</div>
707
+ </div>
708
+ """, unsafe_allow_html=True)
709
+
710
+ with col2:
711
+ st.markdown(f"""
712
+ <div class='metric-card'>
713
+ <div class='metric-value'>{metrics['active_connections']:,}</div>
714
+ <div class='metric-label'>Active Connections</div>
715
+ </div>
716
+ """, unsafe_allow_html=True)
717
+
718
+ with col3:
719
+ st.markdown(f"""
720
+ <div class='metric-card'>
721
+ <div class='metric-value metric-low'>{metrics['uptime']}%</div>
722
+ <div class='metric-label'>System Uptime</div>
723
+ </div>
724
+ """, unsafe_allow_html=True)
725
+
726
+ with col4:
727
+ st.markdown(f"""
728
+ <div class='metric-card'>
729
+ <div class='metric-value'>{metrics['avg_response_time']:.1f}ms</div>
730
+ <div class='metric-label'>Avg Response Time</div>
731
+ </div>
732
+ """, unsafe_allow_html=True)
733
+
734
+ st.markdown("<br>", unsafe_allow_html=True)
735
+
736
+ # Charts
737
+ col1, col2 = st.columns(2)
738
+
739
+ with col1:
740
+ st.markdown("### πŸ” Top Attacker IPs")
741
+ top_ips = df.groupby('source_ip').agg({
742
+ 'id': 'count',
743
+ 'severity': lambda x: (x == 'Critical').sum(),
744
+ 'source_country': 'first'
745
+ }).reset_index()
746
+ top_ips.columns = ['IP Address', 'Total Attacks', 'Critical', 'Country']
747
+ top_ips = top_ips.sort_values('Total Attacks', ascending=False).head(10)
748
+
749
+ st.dataframe(
750
+ top_ips,
751
+ use_container_width=True,
752
+ hide_index=True
753
+ )
754
+
755
+ with col2:
756
+ st.markdown("### πŸ“‘ Protocol Distribution")
757
+ protocol_counts = df['protocol'].value_counts()
758
+
759
+ fig_protocol = px.pie(
760
+ values=protocol_counts.values,
761
+ names=protocol_counts.index,
762
+ color_discrete_sequence=px.colors.sequential.Plasma
763
+ )
764
+ fig_protocol.update_layout(
765
+ plot_bgcolor='rgba(0,0,0,0)',
766
+ paper_bgcolor='rgba(0,0,0,0)',
767
+ font_color='#888',
768
+ margin=dict(l=0, r=0, t=10, b=0)
769
+ )
770
+ st.plotly_chart(fig_protocol, use_container_width=True)
771
+
772
+ # Traffic gauge
773
+ col1, col2 = st.columns(2)
774
+
775
+ with col1:
776
+ st.markdown("### πŸ“₯ Incoming Traffic")
777
+ fig_in = go.Figure(go.Indicator(
778
+ mode="gauge+number",
779
+ value=metrics['incoming_traffic'],
780
+ title={'text': "Gbps", 'font': {'color': '#888'}},
781
+ gauge={
782
+ 'axis': {'range': [0, 600], 'tickcolor': '#888'},
783
+ 'bar': {'color': '#00ffff'},
784
+ 'bgcolor': '#1a1a2e',
785
+ 'bordercolor': '#333',
786
+ 'steps': [
787
+ {'range': [0, 200], 'color': '#1a3a1a'},
788
+ {'range': [200, 400], 'color': '#3a3a1a'},
789
+ {'range': [400, 600], 'color': '#3a1a1a'}
790
+ ]
791
+ }
792
+ ))
793
+ fig_in.update_layout(
794
+ plot_bgcolor='rgba(0,0,0,0)',
795
+ paper_bgcolor='rgba(0,0,0,0)',
796
+ font_color='#888',
797
+ height=250,
798
+ margin=dict(l=20, r=20, t=40, b=20)
799
+ )
800
+ st.plotly_chart(fig_in, use_container_width=True)
801
+
802
+ with col2:
803
+ st.markdown("### πŸ“€ Outgoing Traffic")
804
+ fig_out = go.Figure(go.Indicator(
805
+ mode="gauge+number",
806
+ value=metrics['outgoing_traffic'],
807
+ title={'text': "Gbps", 'font': {'color': '#888'}},
808
+ gauge={
809
+ 'axis': {'range': [0, 600], 'tickcolor': '#888'},
810
+ 'bar': {'color': '#2ed573'},
811
+ 'bgcolor': '#1a1a2e',
812
+ 'bordercolor': '#333',
813
+ 'steps': [
814
+ {'range': [0, 200], 'color': '#1a3a1a'},
815
+ {'range': [200, 400], 'color': '#3a3a1a'},
816
+ {'range': [400, 600], 'color': '#3a1a1a'}
817
+ ]
818
+ }
819
+ ))
820
+ fig_out.update_layout(
821
+ plot_bgcolor='rgba(0,0,0,0)',
822
+ paper_bgcolor='rgba(0,0,0,0)',
823
+ font_color='#888',
824
+ height=250,
825
+ margin=dict(l=20, r=20, t=40, b=20)
826
+ )
827
+ st.plotly_chart(fig_out, use_container_width=True)
828
+
829
+ # Hourly traffic pattern
830
+ st.markdown("### πŸ“Š Hourly Traffic Pattern")
831
+ df_hourly = df.copy()
832
+ df_hourly['hour'] = df_hourly['timestamp'].dt.hour
833
+ hourly_counts = df_hourly.groupby('hour').size().reset_index(name='attacks')
834
+
835
+ fig_hourly = px.line(
836
+ hourly_counts,
837
+ x='hour',
838
+ y='attacks',
839
+ markers=True
840
+ )
841
+ fig_hourly.update_traces(line_color='#00ffff', marker_color='#00ffff')
842
+ fig_hourly.update_layout(
843
+ plot_bgcolor='rgba(0,0,0,0)',
844
+ paper_bgcolor='rgba(0,0,0,0)',
845
+ font_color='#888',
846
+ margin=dict(l=0, r=0, t=10, b=0),
847
+ xaxis=dict(gridcolor='#1a1a2e', title='Hour of Day', dtick=2),
848
+ yaxis=dict(gridcolor='#1a1a2e', title='Number of Attacks')
849
+ )
850
+ st.plotly_chart(fig_hourly, use_container_width=True)
851
+
852
+
853
+ def alerts_page(df):
854
+ """Alerts and notifications page"""
855
+
856
+ st.markdown("## 🚨 Security Alerts")
857
+ st.markdown("Critical and high-severity alerts requiring immediate attention")
858
+
859
+ # Alert summary
860
+ critical_alerts = df[df['severity'] == 'Critical']
861
+ high_alerts = df[df['severity'] == 'High']
862
+ active_alerts = df[df['status'] == 'Active']
863
+
864
+ col1, col2, col3, col4 = st.columns(4)
865
+
866
+ with col1:
867
+ st.markdown(f"""
868
+ <div class='metric-card'>
869
+ <div class='metric-value metric-critical'>{len(critical_alerts)}</div>
870
+ <div class='metric-label'>Critical Alerts</div>
871
+ </div>
872
+ """, unsafe_allow_html=True)
873
+
874
+ with col2:
875
+ st.markdown(f"""
876
+ <div class='metric-card'>
877
+ <div class='metric-value metric-high'>{len(high_alerts)}</div>
878
+ <div class='metric-label'>High Alerts</div>
879
+ </div>
880
+ """, unsafe_allow_html=True)
881
+
882
+ with col3:
883
+ st.markdown(f"""
884
+ <div class='metric-card'>
885
+ <div class='metric-value' style='color: #ff6b6b;'>{len(active_alerts)}</div>
886
+ <div class='metric-label'>Active Threats</div>
887
+ </div>
888
+ """, unsafe_allow_html=True)
889
+
890
+ with col4:
891
+ mitigated = len(df[df['status'] == 'Mitigated'])
892
+ st.markdown(f"""
893
+ <div class='metric-card'>
894
+ <div class='metric-value metric-low'>{mitigated}</div>
895
+ <div class='metric-label'>Mitigated</div>
896
+ </div>
897
+ """, unsafe_allow_html=True)
898
+
899
+ st.markdown("<br>", unsafe_allow_html=True)
900
+
901
+ # Critical alerts list
902
+ st.markdown("### πŸ”΄ Critical Alerts")
903
+ critical_list = critical_alerts.sort_values('timestamp', ascending=False).head(15)
904
+
905
+ for _, alert in critical_list.iterrows():
906
+ with st.expander(f"⚠️ {alert['id']} - {alert['attack_type']} | {alert['timestamp'].strftime('%Y-%m-%d %H:%M:%S')}"):
907
+ col1, col2, col3 = st.columns(3)
908
+ with col1:
909
+ st.markdown(f"""
910
+ **Source IP:** {alert['source_ip']}
911
+ **Country:** {alert['source_country']}
912
+ **Protocol:** {alert['protocol']}
913
+ """)
914
+ with col2:
915
+ st.markdown(f"""
916
+ **Target Port:** {alert['port']}
917
+ **Target Country:** {alert['target_country']}
918
+ **Destination IP:** {alert['destination_ip']}
919
+ """)
920
+ with col3:
921
+ st.markdown(f"""
922
+ **Status:** {alert['status']}
923
+ **Confidence:** {alert['confidence']}%
924
+ **Packets:** {alert['packets']:,}
925
+ """)
926
+
927
+ st.progress(alert['confidence'] / 100)
928
+
929
+ col1, col2, col3 = st.columns(3)
930
+ with col1:
931
+ st.button("πŸ›‘οΈ Block IP", key=f"block_{alert['id']}")
932
+ with col2:
933
+ st.button("πŸ” Investigate", key=f"inv_{alert['id']}")
934
+ with col3:
935
+ st.button("βœ… Mark Resolved", key=f"resolve_{alert['id']}")
936
+
937
+ st.markdown("---")
938
+
939
+ # High severity alerts
940
+ st.markdown("### 🟠 High Severity Alerts")
941
+ high_list = high_alerts.sort_values('timestamp', ascending=False).head(10)
942
+
943
+ for _, alert in high_list.iterrows():
944
+ st.markdown(f"""
945
+ <div class='alert-high'>
946
+ <strong>{alert['id']}</strong> | {alert['attack_type']} |
947
+ Source: {alert['source_ip']} ({alert['source_country']}) β†’
948
+ Port {alert['port']} | Status: {alert['status']} |
949
+ {alert['timestamp'].strftime('%Y-%m-%d %H:%M:%S')}
950
+ </div>
951
+ """, unsafe_allow_html=True)
952
+
953
+
954
+ # ============== MAIN APP ==============
955
+
956
+ def main():
957
+ # Get sidebar selections
958
+ page, date_range, severity_filter, attack_filter = render_sidebar()
959
+
960
+ # Generate data
961
+ df = generate_threat_data(500)
962
+ metrics = generate_network_metrics()
963
+
964
+ # Apply filters
965
+ if len(date_range) == 2:
966
+ start_date, end_date = date_range
967
+ df = df[(df['timestamp'].dt.date >= start_date) & (df['timestamp'].dt.date <= end_date)]
968
+
969
+ df = df[df['severity'].isin(severity_filter)]
970
+ df = df[df['attack_type'].isin(attack_filter)]
971
+
972
+ # Render selected page
973
+ if page == "🏠 Overview":
974
+ overview_page(df, metrics)
975
+ elif page == "πŸ“Š Threat Feed":
976
+ threat_feed_page(df)
977
+ elif page == "🌍 Geographic Analysis":
978
+ geographic_page(df)
979
+ elif page == "πŸ”Œ Network Analysis":
980
+ network_page(df, metrics)
981
+ elif page == "🚨 Alerts":
982
+ alerts_page(df)
983
+
984
+ if __name__ == "__main__":
985
+ main()
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ streamlit==1.31.0
2
+ pandas==2.2.0
3
+ numpy==1.26.4
4
+ plotly==5.18.0