地理偵測
本頁說明 GeoLite2 資料庫如何啟用、IP 位置如何快取,以及四項地理異常偵測(含不可能旅行)的條件。
啟用條件
| 設定 | 結果 |
|---|---|
Filepath.CityDB 與 Filepath.CountryDB 皆空 |
不建立 GeoLite2,地理偵測停用 |
| 兩者皆開啟失敗 | 記錄警告,地理偵測停用 |
只有 CountryDB 成功 |
calcGeo 要求 CityDB 存在,地理偵測整段略過 |
CityDB 成功 |
啟用;City 查詢失敗時才回退 CountryDB |
資料庫需自行從 MaxMind 下載(GeoLite2-City.mmdb),本函式庫不負責更新。
位置查詢與歷史
| 步驟 | 行為 |
|---|---|
| 內網 IP | 不查資料庫,回傳空位置(國家、城市為空,經緯度 0) |
| 快取 | geo:ip:{ip} 保存查詢結果 24 小時 |
| 查不到 | 記錄後跳過,該請求地理分數為 0 |
| 歷史 | geo:locations:{sid} 推入 {ms}:{國家碼}:{城市}:{緯度}:{經度},保留最近 10 筆,TTL 24 小時 |
四項偵測
| Flag | 條件 | 分數 |
|---|---|---|
geo_high_risk |
歷史中出現 HighRiskCountry 列出的國家碼 |
ScoreGeoHighRisk(30) |
geo_hopping |
最近 1 小時內超過 4 個不同國家 | ScoreGeoHopping(15) |
geo_frequent_switching |
最近 1 小時內 >= 4 個城市、>= 5 筆紀錄,且相鄰紀錄城市切換超過 4 次 |
ScoreGeoFrequentSwitch(20) |
rapid_geo_change |
最新兩筆相隔不到 1 小時,且推算時速 > 800 km/h,或 30 分鐘內移動 > 500 km |
ScoreGeoRapidChange(25) |
geo_high_risk 目前因欄位對應錯誤永遠不會觸發,見 已知問題。
不可能旅行(Impossible Travel)
距離以 Haversine 公式、地球半徑 6371 km 計算,時速 = 距離 ÷ 時間差。800 km/h 約為民航機巡航速度,正常移動不會超過;VPN 切換節點、代理池輪換則會。
| 例子 | 距離 | 時間差 | 結果 |
|---|---|---|---|
| 台北 → 東京 | 約 2,100 km | 10 分鐘 | 觸發(時速與 30 分鐘規則皆成立) |
| 台北 → 台中 | 約 140 km | 20 分鐘 | 不觸發(420 km/h) |
| 台北 → 東京 | 約 2,100 km | 3 小時 | 不比對(超過 1 小時) |
邊界
| 情境 | 行為 |
|---|---|
| 同一 Session 交替使用內網與外網 IP | 內網紀錄的經緯度是 (0, 0),切到外網時會被算成從大西洋移動數千公里,可能誤觸 rapid_geo_change |
| GeoLite2 精度 | 城市級位置可能誤差數十公里;同城市不同 IP 只影響城市切換計數 |
| 除錯輸出 | calcGeo 每個請求以標準 log.Print 輸出位置字串,見 已知問題 |