Amass專案原始碼閱讀 整體架構

2022-02-23 17:56:15 字數 2195 閱讀 1835

本文寫於 amass v3.11.2,可能後續有過更多變更,但是應該整體邏輯不會有十分大的變動了

首先鋪墊下在 amass 用到的兩大設計模式:

發布訂閱模式

流水線(pipeline)模式

在 4432dbd 該提交之前,即 v3.11.0 版本前,其實並沒有流水線模式,並且採用的是 golang 來寫外掛程式,在此之後,專案負責人 jeff foley 對該專案進行了一次大的重構,把他自己寫的 eventbus 和 service 全部抽離了出來成為了獨立的庫,並且引入了他自己實現的 pipeline 庫來實現整個子網域名稱收集的流水線作業。同時,原本採用 golang 編寫的資料來源外掛程式,通過引入第三方庫 gopher-lua 賦予了指令碼編寫外掛程式的能力,實現了外掛程式系統與主程式的剝離。

我這裡把專案區分為 v3.11.0 前和後

在 v3.11.0 之前,整個專案執行,從入口函式進入後,經過簡單處理後,開始經過所有的資料來源服務外掛程式,其中所有的資料來源服務外掛程式都需要實現services.service介面,通過覆寫結構體方法來進行呼叫。

經過所有的資料來源服務外掛程式前,有乙個步驟是註冊所有的訊息訂閱者,然後資料來源服務外掛程式發現新的子域後,發布訊息到事件匯流排(或者說訊息佇列)中,然後訊息訂閱者獲取到資料後進行後續處理,比如輸出日誌,入庫,判斷是否為泛解析,ip解析等等

其中的發布訂閱模式是乙個簡易的訊息佇列實現,這裡面有幾個概念:

訊息發布

訊息訂閱處理

訊息頻道(路由/topic)

首先需要把訊息訂閱者(處理函式)註冊到系統中,採用的是 hash 表,即 golang 中的 map,不同的topic定義為不同的鍵,處理函式設定為值,然後發布者發布訊息到對應的路由,封裝好對應的路由和資料後塞進佇列,另外有協程一直在從佇列中取出元素,根據所得到的路由和資料引數呼叫不同的處理函式。

總體是乙個樹狀發散的,即有可能處理的資料會繼續發布到匯流排給其他的處理函式處理。

這樣會導致兩個問題:

因為發布訊息的結束標識無法獲知,訂閱訊息的結束標識也是無法獲知,整體的樹狀發散更導致定義任務結束愈發困難

就像上面說的,有些處理函式是有乙個處理流程的,比如先給誰處理,再給處理,全部移交到訊息匯流排,再由各自的訂閱處理,導致整體的資料流動極為晦澀,如果不通讀所有處理函式的原始碼很難梳理明白處理函式之間的先後關係

針對問題1, amass 採用的解決方案是使用乙個協程來監控dns請求的速率,假如多少秒不活躍(即無新資料),並且每秒 dns 請求小於幾個,即判斷為結束,這個方案只能說是乙個相對好用的解決手段,因為架構的問題導致本身就很難以去判斷結束

針對問題2,可能開發者想讓整個專案的資料流動更清晰一些,所以採用了 pipeline模式,然後使用扇入扇出加快整個處理流程

設定了一條訊息匯流排,其中定義了兩個路由:newname(子網域名稱)和newaddr(ip位址),其他的路由比如日誌我們暫時不用關心,這兩個路由所對接的是資料來源服務外掛程式(包含小部分golang外掛程式,大部分lua外掛程式),通過資料來源來產生新子域,發布到匯流排中,然後這兩個路由所註冊的訂閱處理函式的功能是把資料重定向到 pipeline 的起點,pipeline的資料處理通過預先設定好的幾個階段,每個階段可以根據個人的需求控制併發數

其中匯流排的所有的新資料會進入source,然後後面的stage都是可以動態擴容的,最後資料經過乙個乙個階段的處理,最後到達sink。

通過 pipeline,把整個流程清晰化了起來。

目前還保有 golang 的外掛程式,但是目前看起來 golang 的外掛程式是可以用 lua 去實現的,所以目前來看應該是還沒有遷移完畢。

目前所使用的 pipeline 庫也是 amass 專案負責人 jeff foley 寫的,其中大致上有這麼幾個功能:

入口處理

出口處理

階段處理

固定協程數量的協程池(單一任務)

動態協程數量並可設定上限的協程池(單一任務)

單管道(單一任務)

廣播(多工,不等待該階段所有任務完成,有任務完成即進入下一階段)

平行(多工,等待該階段所有任務完成再進入下一階段)

目前來看的話,廣播和平行都沒有都沒有用到,其實比較困惑的一點是,整個流水線模式是可以應對子網域名稱收集的,但是目前還是保留有匯流排的概念,猜測可能後面會使用廣播或平行對資料來源的外掛程式進行執行,因為每個外掛程式可以看作乙個 task,恰好是滿足他自己的設計的

webpy原始碼閱讀 1 初見整體

最近閒來無事,準備看看web.py的原始碼,一開始直接看現在的原始碼,發現比較吃力,後來想起從github上clone下來後checkout到2006年的那個第乙個版本開始,700多次commit,準備一次次的看,記錄下自己的閱讀所得 最開始版本的web.py就乙個web.py檔案,一共1000行多...

一 Spring原始碼閱讀 整體概況

一 spring能幹啥 1.進行物件的管理,物件的建立和銷毀,不用使用new來進行物件建立了 準備寫第二條的,發現spring核心內容就是物件管理,那為什麼必須是spring呢?2.如果僅僅是物件管理,那其實很容易實現,關鍵是其還有豐富的生態圈,基於spring會有很多的元件,這些元件可以在spri...

《原始碼閱讀》原始碼閱讀技巧,原始碼閱讀工具

檢視某個類的完整繼承關係 選中類的名稱,然後按f4 quick type hierarchy quick type hierarchy可以顯示出類的繼承結構,包括它的父類和子類 supertype hierarchy supertype hierarchy可以顯示出類的繼承和實現結構,包括它的父類和...