PhilipL commited on
Commit
bbeffd6
·
unverified ·
1 Parent(s): 3e3f2b0

change evaluate ip way

Browse files
Files changed (1) hide show
  1. app.py +28 -23
app.py CHANGED
@@ -53,10 +53,19 @@ ACTION_MAP = {
53
  log_history = []
54
  initial_df_abn = pd.DataFrame(columns=["timestamp", "ip_address", "cookie_id", "account", "role", "action", "status"])
55
 
 
 
 
 
 
 
 
 
 
56
  # --- 1. 載入模型與歷史資料 ---
57
  try:
58
  le_action = joblib.load('le_action.pkl')
59
- le_ip = joblib.load('le_ip.pkl')
60
 
61
  print("📂 正在處理靜態訓練基底資料...")
62
  static_file = 'static_train_data.csv'
@@ -103,11 +112,8 @@ try:
103
  baseline_df['day'] = baseline_df['timestamp'].dt.day
104
  baseline_df['hour'] = baseline_df['timestamp'].dt.hour
105
 
106
- clean_ips = baseline_df['clean_ip'].values
107
- known_ips = set(le_ip.classes_)
108
- unknown_ips = set(clean_ips) - known_ips
109
- if unknown_ips:
110
- le_ip.classes_ = np.append(le_ip.classes_, list(unknown_ips))
111
 
112
  actions = baseline_df['action'].astype(str).values
113
  known_actions = set(le_action.classes_)
@@ -115,16 +121,17 @@ try:
115
  if unknown_actions:
116
  le_action.classes_ = np.append(le_action.classes_, list(unknown_actions))
117
 
 
118
  baseline_X = np.column_stack((
119
  baseline_df['month'].values,
120
  baseline_df['day'].values,
121
  baseline_df['hour'].values,
122
- le_ip.transform(clean_ips),
123
  le_action.transform(actions)
124
  ))
125
 
126
  AI_READY = True
127
- print("✅ AI 模組與動態歷史基準資料載入成功!")
128
  except Exception as e:
129
  AI_READY = False
130
  global_stats["total_count"] = 0
@@ -277,17 +284,16 @@ def explain_abnormal_log(log_text):
277
  except Exception as e: return f"⚠️ 呼叫 API 發生錯誤: {str(e)}"
278
 
279
  # --- 2. 核心邏輯與真實 HDBSCAN 異常偵測 ---
280
- # 🌟 修改:加入 gw (地理), fw (頻率) 接收參數
281
  def check_anomaly(ip, action, log_time, ow, tw, iw, dw, gw, fw):
282
  if not AI_READY: return "success"
283
  if action in ["login_attempt", "logout"]: return "success"
284
 
285
  try:
286
  ow, tw, iw, dw = float(ow), float(tw), float(iw), float(dw)
287
- gw, fw = float(gw), float(fw) # 將新增的地理與頻率參數轉為 float,供未來擴充使用
288
 
289
- clean_ip = str(ip).split(" ")[0]
290
- ip_code = float(le_ip.transform([clean_ip])[0])
291
  action_code = float(le_action.transform([action])[0])
292
 
293
  current_time = pd.to_datetime(str(log_time))
@@ -335,9 +341,11 @@ def check_anomaly(ip, action, log_time, ow, tw, iw, dw, gw, fw):
335
  min_distance = np.min(distances)
336
  max_tolerance_distance = time_multiplier * 15.0 + 1.0
337
 
338
- # 💡 暫時實作:若為國外異常 IP (45.33.22.11),根據敏感度(gw)縮小容忍度
339
- if "45.33" in clean_ip:
340
- max_tolerance_distance *= (1 - (gw / 100.0))
 
 
341
 
342
  if min_distance > max_tolerance_distance:
343
  return "⚠️異常_作息或行為不符"
@@ -369,11 +377,10 @@ def record_log(ip, cookie, account, role, action, status, time_mode, custom_time
369
  if status == "success" and AI_READY:
370
  try:
371
  current_time = pd.to_datetime(str(log_time))
372
- clean_ip = str(ip).split(" ")[0]
373
- if clean_ip not in le_ip.classes_: le_ip.classes_ = np.append(le_ip.classes_, clean_ip)
374
  if action not in le_action.classes_: le_action.classes_ = np.append(le_action.classes_, action)
375
-
376
- new_row = np.array([[float(current_time.month), float(current_time.day), float(current_time.hour), float(le_ip.transform([clean_ip])[0]), float(le_action.transform([action])[0])]], dtype=float)
 
377
  baseline_X = np.vstack((baseline_X, new_row))
378
  except: pass
379
 
@@ -528,12 +535,12 @@ with gr.Blocks(title="模擬校園入口與資安防護系統") as demo:
528
  action_plot = gr.Plot(show_label=False)
529
 
530
  with gr.Accordion("▼ 防護強度微調 (AI 敏感度)", open=True, elem_classes="weight-card"):
531
- gr.Markdown("<span style='color:gray; font-size:0.9em;'>手動輸入 0~100 的數值。系統尚未完成地理與頻率的訓練架構,目前的數值調整僅為 UI 預留介面與簡易模擬,須待架構升級後才能完整發揮。</span>")
532
  with gr.Row():
533
  overall_weight = gr.Number(label="總體防護強度 (%)", value=75, minimum=0, maximum=100)
534
  time_weight = gr.Number(label="時間特徵權重 (%)", value=80, minimum=0, maximum=100)
 
535
  ip_weight = gr.Number(label="IP 聲譽權重 (%)", value=65, minimum=0, maximum=100)
536
- # 🌟 新增:將使用者要求的「地理偏移敏感度」與「行為頻率敏感度」加入介面中
537
  with gr.Row():
538
  device_weight = gr.Number(label="裝置指紋/行為權重 (%)", value=45, minimum=0, maximum=100)
539
  geo_weight = gr.Number(label="🌍 地理偏移敏感度 (%)", value=50, minimum=0, maximum=100)
@@ -584,7 +591,6 @@ with gr.Blocks(title="模擬校園入口與資安防護系統") as demo:
584
  time_mode.change(fn=toggle_time_input, inputs=time_mode, outputs=custom_time_input)
585
  btn_explain_log.click(fn=explain_abnormal_log, inputs=[abnormal_log_input], outputs=[ai_explanation_output])
586
 
587
- # 🌟 修改:將 geo_weight 與 freq_weight 正式加入全域的輸入變數清單
588
  weight_inputs = [overall_weight, time_weight, ip_weight, device_weight, geo_weight, freq_weight]
589
  update_outputs = [main_router, role_tabs, login_msg, welcome_text, store_df_all, store_df_abn, abnormal_log_input]
590
 
@@ -594,7 +600,6 @@ with gr.Blocks(title="模擬校園入口與資安防護系統") as demo:
594
  fast_inputs = [mock_ip, mock_cookie, time_mode, custom_time_input] + weight_inputs
595
  fast_outputs = update_outputs + [acc_input]
596
 
597
- # 🌟 修改:更新所有按鈕的 Lambda 函式以接住並傳遞 gw, fw 參數
598
  btn_fast_student.click(fn=lambda ip, c, tm, ct, ow, tw, iw, dw, gw, fw: fast_login("student", ip, c, tm, ct, ow, tw, iw, dw, gw, fw), inputs=fast_inputs, outputs=fast_outputs)
599
  btn_fast_admin.click(fn=lambda ip, c, tm, ct, ow, tw, iw, dw, gw, fw: fast_login("admin", ip, c, tm, ct, ow, tw, iw, dw, gw, fw), inputs=fast_inputs, outputs=fast_outputs)
600
  btn_toggle_role.click(fn=toggle_role, inputs=[acc_input, mock_ip, mock_cookie, time_mode, custom_time_input] + weight_inputs, outputs=[role_tabs, welcome_text, store_df_all, store_df_abn, abnormal_log_input, acc_input])
 
53
  log_history = []
54
  initial_df_abn = pd.DataFrame(columns=["timestamp", "ip_address", "cookie_id", "account", "role", "action", "status"])
55
 
56
+ # --- 🌟 新增:網段標籤轉換器 (Rule-based Feature Engineering) ---
57
+ def get_ip_category(ip_str):
58
+ ip = str(ip_str).split(" ")[0]
59
+ if ip.startswith("140.124."): return 0.0 # 信任網段:校內/宿舍
60
+ elif ip.startswith("61.228."): return 1.0 # 一般網段:國內家用
61
+ elif ip.startswith("210.61."): return 2.0 # 一般網段:公共場所
62
+ elif ip.startswith("45.33."): return 3.0 # 高風險網段:已知國外異常
63
+ else: return 4.0 # 未知網段:新出現的 IP
64
+
65
  # --- 1. 載入模型與歷史資料 ---
66
  try:
67
  le_action = joblib.load('le_action.pkl')
68
+ # 🛑 移除舊的 le_ip = joblib.load('le_ip.pkl'),改用上方的新轉換器
69
 
70
  print("📂 正在處理靜態訓練基底資料...")
71
  static_file = 'static_train_data.csv'
 
112
  baseline_df['day'] = baseline_df['timestamp'].dt.day
113
  baseline_df['hour'] = baseline_df['timestamp'].dt.hour
114
 
115
+ # 🌟 修改:即時將資料表內的 IP 轉換為「網段標籤」陣列
116
+ ip_codes = np.array([get_ip_category(ip) for ip in baseline_df['clean_ip'].values])
 
 
 
117
 
118
  actions = baseline_df['action'].astype(str).values
119
  known_actions = set(le_action.classes_)
 
121
  if unknown_actions:
122
  le_action.classes_ = np.append(le_action.classes_, list(unknown_actions))
123
 
124
+ # 🌟 修改:將網段標籤組合進 AI 特徵矩陣中
125
  baseline_X = np.column_stack((
126
  baseline_df['month'].values,
127
  baseline_df['day'].values,
128
  baseline_df['hour'].values,
129
+ ip_codes,
130
  le_action.transform(actions)
131
  ))
132
 
133
  AI_READY = True
134
+ print("✅ AI 模組與動態歷史基準資料載入成功 (已套用智慧網段標籤)!")
135
  except Exception as e:
136
  AI_READY = False
137
  global_stats["total_count"] = 0
 
284
  except Exception as e: return f"⚠️ 呼叫 API 發生錯誤: {str(e)}"
285
 
286
  # --- 2. 核心邏輯與真實 HDBSCAN 異常偵測 ---
 
287
  def check_anomaly(ip, action, log_time, ow, tw, iw, dw, gw, fw):
288
  if not AI_READY: return "success"
289
  if action in ["login_attempt", "logout"]: return "success"
290
 
291
  try:
292
  ow, tw, iw, dw = float(ow), float(tw), float(iw), float(dw)
293
+ gw, fw = float(gw), float(fw)
294
 
295
+ # 🌟 修改:直接將輸入的 IP 透過函式轉成分類標籤
296
+ ip_code = float(get_ip_category(ip))
297
  action_code = float(le_action.transform([action])[0])
298
 
299
  current_time = pd.to_datetime(str(log_time))
 
341
  min_distance = np.min(distances)
342
  max_tolerance_distance = time_multiplier * 15.0 + 1.0
343
 
344
+ # 🌟 完成功能:將「IP 聲譽權重 (iw)」與網段標籤完美綁定!
345
+ # 如果是國外異常或未知 IP (標籤 3.0 或 4.0),且管理員調高了 iw
346
+ # 系統會嚴格縮減對它的距離容忍度,迫使它更容易被判定為異常
347
+ if ip_code >= 3.0:
348
+ max_tolerance_distance *= (1 - (iw / 100.0) * 0.6)
349
 
350
  if min_distance > max_tolerance_distance:
351
  return "⚠️異常_作息或行為不符"
 
377
  if status == "success" and AI_READY:
378
  try:
379
  current_time = pd.to_datetime(str(log_time))
 
 
380
  if action not in le_action.classes_: le_action.classes_ = np.append(le_action.classes_, action)
381
+
382
+ # 🌟 修改:寫入基準資料時,轉換為網段標籤
383
+ new_row = np.array([[float(current_time.month), float(current_time.day), float(current_time.hour), float(get_ip_category(ip)), float(le_action.transform([action])[0])]], dtype=float)
384
  baseline_X = np.vstack((baseline_X, new_row))
385
  except: pass
386
 
 
535
  action_plot = gr.Plot(show_label=False)
536
 
537
  with gr.Accordion("▼ 防護強度微調 (AI 敏感度)", open=True, elem_classes="weight-card"):
538
+ gr.Markdown("<span style='color:gray; font-size:0.9em;'>手動輸入 0~100 的數值。系統目前已成功啟用 IP 聲譽權重;地理與頻率的訓練架構僅為預留介面,須待升級後發揮。</span>")
539
  with gr.Row():
540
  overall_weight = gr.Number(label="總體防護強度 (%)", value=75, minimum=0, maximum=100)
541
  time_weight = gr.Number(label="時間特徵權重 (%)", value=80, minimum=0, maximum=100)
542
+ # 🌟 已完成綁定
543
  ip_weight = gr.Number(label="IP 聲譽權重 (%)", value=65, minimum=0, maximum=100)
 
544
  with gr.Row():
545
  device_weight = gr.Number(label="裝置指紋/行為權重 (%)", value=45, minimum=0, maximum=100)
546
  geo_weight = gr.Number(label="🌍 地理偏移敏感度 (%)", value=50, minimum=0, maximum=100)
 
591
  time_mode.change(fn=toggle_time_input, inputs=time_mode, outputs=custom_time_input)
592
  btn_explain_log.click(fn=explain_abnormal_log, inputs=[abnormal_log_input], outputs=[ai_explanation_output])
593
 
 
594
  weight_inputs = [overall_weight, time_weight, ip_weight, device_weight, geo_weight, freq_weight]
595
  update_outputs = [main_router, role_tabs, login_msg, welcome_text, store_df_all, store_df_abn, abnormal_log_input]
596
 
 
600
  fast_inputs = [mock_ip, mock_cookie, time_mode, custom_time_input] + weight_inputs
601
  fast_outputs = update_outputs + [acc_input]
602
 
 
603
  btn_fast_student.click(fn=lambda ip, c, tm, ct, ow, tw, iw, dw, gw, fw: fast_login("student", ip, c, tm, ct, ow, tw, iw, dw, gw, fw), inputs=fast_inputs, outputs=fast_outputs)
604
  btn_fast_admin.click(fn=lambda ip, c, tm, ct, ow, tw, iw, dw, gw, fw: fast_login("admin", ip, c, tm, ct, ow, tw, iw, dw, gw, fw), inputs=fast_inputs, outputs=fast_outputs)
605
  btn_toggle_role.click(fn=toggle_role, inputs=[acc_input, mock_ip, mock_cookie, time_mode, custom_time_input] + weight_inputs, outputs=[role_tabs, welcome_text, store_df_all, store_df_abn, abnormal_log_input, acc_input])