有一個週一早上打開詢問總表,發現週末多了十九列新資料。點開一看,不是客人,是機器人灌進來的垃圾——內容不外乎免費遊戲點數、加密貨幣錢包、領取三千美金獎金這類東西,還夾帶一串連結。同事一開始還以為是新的行銷活動誤觸發,花了十幾分鐘才確認是灌水攻擊,然後一列一列手動刪掉。
旅行社的官網表單、徵才頁面,都是公開可填的入口,對自動化的灌水程式來說,跟一扇沒鎖的門沒什麼兩樣。這種事不會每天發生,可能一個晚上灌進幾十列,也可能一整個禮拜都風平浪靜——問題就出在這個不規律上,忙的時候根本沒人記得回頭檢查那張表。
最早的做法是每天早上進去看一眼、手動刪掉。人工處理的下場很快就出現:忙的時候忘了刪,資料表裡混著真客人跟假資料,業務要撈名單的時候得先自己肉眼過濾一次,久了沒人敢直接相信那張表是乾淨的。
所以我寫了一支每天凌晨四點跑一次的程式,自動把這類資料清掉。挑凌晨四點是刻意的——這個時間點幾乎不會有真正的客人在填表單,清理動作跟真實流量重疊的機率最低。
判斷哪些是垃圾,用了三層規則,由嚴到寬:
第一層是已知的惡意網域清單,只要文字欄位裡出現清單裡的網域,不管前後文寫什麼,直接判定為垃圾。這一層最硬,因為這些網域幾乎不可能出現在正常的旅遊詢問裡。
第二層是「文字欄位裡有網址、而且同時含有誘餌字眼」才刪——誘餌字眼包括各種變形寫法的免費、中獎、加密貨幣錢包、限時領取之類的詞組。這個「而且」是後來才加上去的關鍵字。最早的版本只要欄位裡有任何網址就判定刪除,結果誤刪了真客人的資料——有些客人會在需求欄位貼自己想去的景點連結、或是想參考的行程網址,那是完全正常、甚至該被珍惜的填寫行為。加上「還要同時含誘餌字」這個條件之後,這類誤刪才停止。
第三層是寄件信箱的格式:長得像系統隨機產生的帳號,例如一串數字加常見免費信箱網域,這種格式在真人填寫的詢問裡極少出現。
除了三層規則,我另外維護一份白名單,裡面是往來同業與合作夥伴的網域。只要某一列的任何一個欄位出現白名單裡的網域,整列就永遠不刪——即使它同時命中了第二層或第三層的規則。
唯一的例外是第一層那個已知惡意網域,白名單擋不住它。理由很現實:如果白名單可以擋掉最硬的那一層規則,攻擊者只要在垃圾內容裡順手塞一個看起來正常的網域字串,就能繞過整套機制,白名單反而變成漏洞。
這個設計背後的取捨講得很直白:**寧可漏刪幾列垃圾讓人自己清掉,也不能誤刪一封真的詢問信。**一列垃圾留著,最多是看了礙眼;一封真客人的詢問被刪掉,那是實實在在的生意沒了,而且你永遠不會知道它曾經存在過——它不會留下任何痕跡讓你發現自己犯了錯。
程式不是直接刪除,是先把整列原封不動備份到另一個分頁,再刪掉原本那列。備份的時候會把裡面的網址去毒處理——把可以直接點擊的連結格式拆解掉,讓內容還能被人讀懂、判斷,但那串網址不會是點一下就會跳轉過去的狀態。
這樣做有兩個理由。一是萬一哪天發現規則誤判了,備份還在,救得回來。二是備份資料本身就是一份觀察樣本,隔一陣子回頭看,會發現灌水的手法慢慢在變——誘餌字的用詞、信箱格式的規律都會演化,規則也要跟著調整,不是設定一次就永遠有效。
通知信也刻意設計成只有抓到東西才寄。如果每天都寄一封「今天沒事」的信,收信的人大概三天後就會養成自動略過的習慣,等到真的有事那天,同樣會被順手滑過去。只在有實際抓到垃圾的那天才發通知,才能維持通知本身的分量。
只要你有公開的表單入口,這件事遲早會發生。動手之前先想清楚誤刪的代價——在旅行社這一行,一封被誤刪的詢問信,比一百列沒清掉的垃圾嚴重得多。先做好備份跟白名單這兩道保險,再談判斷規則要寫得多聰明。