繼續趣事分享。
上回聊到了大學里用一根網線發起攻擊,今天接著往后講。
不過這次講的正好相反 —— 不是攻擊,而是防御。一個奇葩防火墻的開發經歷。
第二學期大家都帶了電腦,于是可以用更高端的方法斷網了。但設備先進反而沒有了 GEEK 的感覺。于是,決定做些其他更有意義的事。
一天,幾個好友在吐槽,他們的游戲服務器又被打垮了,接著討論起各種防護方案。
在過去,每當聽到防火墻軟件時,就覺得毫無卵用。巨大的流量一來,帶寬都堵死了,軟件又有何用。
不過,大家仍對其寄以厚望。而且還有不少廠商在做,看來,效果總是有一點的。
討論討論著,不免又有些蠢蠢欲動。要不,做個防火墻吧,做一個思路完全不同的!
當然,這不是第一次嘗試。
初學那會,沒有固定的目標。每看見一個小 demo,就想搞個大程序。比如看了 DirectX 就有做游戲的沖動,但不出幾天就不了了之。
有段時間對驅動程序產生了興趣,琢磨起 Windows DDK 里的 demo。當看見 NDIS 中間件這玩意時,頓時起了精神。這不就是一個最底層的包過濾器嗎,用來做防火墻,性能自然是極好的。
于是心血來潮,照著其中的樣例,改造出一個最簡單的 IP 過濾防火墻。為了凸顯高性能,硬著頭皮看了本數據結構,依樣畫葫蘆寫了個哈希表,來更快查詢。
然而快歸快,沒有實際用途,不過是個玩具罷了。
現實中的防火墻,也不可能這么簡單的邏輯。肯定還需更高層的協議分析,復雜的策略判斷,大量的數據積累。。。當然還少不了無數次的藍屏調試。
想到這,立馬就沒有了繼續。
然而這一次,決定不再糾結技術層面,而是做一個“另類”的 —— 用最簡單的技術,加上巧妙的想法,配合一些獨門絕技,來獲得出其不意的效果。
考慮到傳統的開發人員,對系統、網絡都已經非常熟悉,和他們比拼這些,就毫無優勢了。
而當時的我,點滿了一個和安全毫不相干的技能 —— 網頁腳本特效,以及一堆“前端黑魔法”。
但是。。。這。。和網絡防御。。。有什么關系?
沒有半點關系~~ 想多了。還是考慮正經的吧。
首先想到的,是改造游戲的服務端程序。
畢竟這是“開源”的,肯定能通過修改程序,來加強那脆弱的網絡系統。
然而,當看到那密密麻麻的代碼、從未用過的語言、完全不熟的調試器,興致蕩然無存。
沒興趣就沒想法,果斷放棄。
既然如此,那就從客戶端試試。
這一次,抱著探索的心情,打開程序,細細揣摩起來。
正當毫無頭緒時,突然傳來親切的嚓嚓聲 —— 敏感的神經怎能放過,這不是 ie 的專屬聲音嗎。
這才猛然意識到,登錄器中內嵌的,不正是一個大大的網頁!
有網頁,不就可以運行腳本了!
從沒想到,居然打起了這個內嵌框的主意~~ 但總算把腳本扯到一起了。
越想越興奮。現有的防火墻,幾乎都是純服務端的數據分析,能讓客戶端參與的,應該還很少吧。
“只要在登錄器的網頁里引一個腳本,就能...”
大家聽了,表示可以接受。
有腳本,就可以盡情發揮了。
我們必須讓用戶運行腳本,才能連上游戲服務器;沒運行過腳本的 IP,就一律阻攔。
于是開始構思、整理:
當腳本運行時,發送一個請求給 “授權服務器”
“授權服務器”驗證參數之后,將用戶 IP 通知給“游戲服務器”上的防火墻,添加到白名單
“游戲服務器”只允許白名單的 IP 通過(“授權服務器”默認在白名單)
正常用戶,這并沒影響;但攻擊器不會執行腳本,也就無法進入白名單 —— 無論發送什么數據包,都會被攔截。
這樣,防火墻的策略,也變得極其簡單:僅僅判斷數據包的 IP 是否在白名單里。
于是,之前那個簡陋的 demo 驅動又被翻了出來。因為功能單一,保證了穩定性。而且是在網卡鏈路層上攔截,所以有超高的性能。
到此,一個 JavaScript 參與的網絡防火墻原型誕生了!
也許你會說,這只是轉移了風險而已。把游戲服務器的風險,轉移到了網站上。要是網站被打垮,同樣無法進游戲。
的確如此。不過相比普通的網絡程序,Web 有更多成熟的防御方案,甚至用現成的 CDN,就可以緩解。
因此將普通的 C/S 網絡防御,掛靠在了更穩定的 B/S 之上,就無需再造輪子了,節省大量成本。
當然這只是基本雛形。實際應用,還有不少需要考慮的地方。
例如,白名單不能無限增加,得有過期時間;客戶端的腳本,也不能只運行一次,得定期觸發激活。
....
不過,由于無需考慮兼容性問題,使得開發十分順利。服務器都是 Win2003;網頁運行在 WebBrowser 控件里,都是 ie67 的內核。
幾天后功能完成。接著做了個簡單的界面程序,將方案進行包裝,就開始試用了。
上線后,效果很理想!任何與玩家無關的流量,都進行了攔截。雖然大流量攻擊仍無能為力,但各種 CC 攻擊就能輕松抵擋住了!
不過,攻擊者也絕不會罷休。
況且,前端的一切都是公開的,這個秘密早晚會被發現。
對抗 v1
平靜了幾個月后,一大波僵尸又來了。
日志顯示,短時間內白名單進了大量 IP,這絕不是正常用戶的。
顯然,已有人發現了這個秘密!
事實上,第一版做的非常簡單,甚至連腳本都沒混淆。
他們把腳本邏輯,移植到了攻擊器里。這樣不訪問網頁,也能變成合法用戶了。
至于他們是如何發現的,無從得知。但腦補發現后的心情,一定是這樣的:臥槽,原來是在這里,居然這么猥瑣~~~~
當然,這是意料之中的事。
新版本早已準備就緒,“前端黑魔法” 也躍躍欲試,決定進行反擊。
這次,將腳本進行了加密。
不,不是網上流傳的那種加密,而是特殊構造的。雖然看起來差不多:整個程序,套在一個 eval 之中。
懂點 JS 的都知道,把 eval 換成 console.log 之類的,代碼就原形畢現了。相信 99% 的人會這么做。
于是,利用大家這個心理,在代碼中埋下一陷阱:如果只解密,不 eval,就會出現意外的后果。
eval(
(function() {
...
T = setTimeout(die, 1)
...
code += 'clearTimeout(T)'
...
return code
})()
)
在解密過程中,偷偷開啟一個定時器:1 毫秒后,進入自殺模式 —— 死循環內存申請!
正常情況下,這并不會觸發 —— 因為隨后 eval 的代碼里,會解除這個定時器;但如果把 eval 換成其他的,就無法執行解除了 —— 炸彈觸發!
當時的主流內存還是 1~2G,這會瞬間被吞光,卡到硬盤吱吱作響。
為滿足好奇心,想看看有多少人栽進去,因此在死循環之前,還加了日志上報的功能。
那段時間,正好在琢磨一個短信接口。于是,這日志就成了測試內容。
每當有人試圖破解腳本時,手機就立即收到了消息,體驗了回“盡在掌控中”的感覺:)
當然,就這樣結束了嗎?
不,還早著呢。
文章列表