描述
原始套接字具有廣泛的用途,特別是用于自定義協(xié)議(標(biāo)準(zhǔn)協(xié)議TCP、UDP和ICMP等外)的數(shù)據(jù)收發(fā)。在Linux下攔截套接字IO的一般方法是攔截對應(yīng)的套接字系統(tǒng)調(diào)用,對于發(fā)送為sendmsg和sendto,對于接收為recvmsg和recvfrom。這種方法雖然也能攔截原始套接字IO,但要先判斷套接字的類型,如果為SOCK_RAW(原始套接字類型),那么進(jìn)行攔截處理,這樣一來由于每次IO都要判斷套接字類型,性能就比較低了。因此為了直接針對原始套接字來攔截,提高性能,發(fā)明了本方法。
本方法可用于防火墻或主機(jī)防護(hù)系統(tǒng)中,丟棄接收和發(fā)送的攻擊或病毒數(shù)據(jù)包。
特點
運行在內(nèi)核態(tài),直接攔截所有進(jìn)程的原始套接字IO,支持IPv4和IPv6。
實現(xiàn)
原理
在Linux內(nèi)核網(wǎng)絡(luò)子系統(tǒng)中,struct proto_ops結(jié)構(gòu)提供了協(xié)議無關(guān)的套接字層到協(xié)議相關(guān)的傳輸層的轉(zhuǎn)接,而IPv4協(xié)議族中內(nèi)置的inet_sockraw_ops為它的一個實例,對應(yīng)著原始套接字。因此先找到inet_sockraw_ops,再替換它的成員函數(shù)指針recvmsg和sendmsg,就可以實現(xiàn)攔截了。下面以IPv4為例(IPv6同理),說明幾個流程。
搜索inet_sockraw_ops
該流程在掛鉤IO前進(jìn)行。由于inet_sockraw_ops為Linux內(nèi)核未導(dǎo)出的內(nèi)部符號,因此需要通過特別的方法找到它,該特別的方法基于這樣的一個事實:
◆ 所有原始套接字接口均存放在以SOCK_RAW為索引的雙向循環(huán)鏈表中,而inet_sockraw_ops就在該鏈表的末尾。
◆ 內(nèi)核提供了注冊套接字接口的API inet_register_protosw,對于原始套接字類型,該API將輸入的套接字接口插入到鏈表頭后面。
算法如下
注冊p前或注銷p后,鏈表如下
注冊p后,鏈表如下
掛鉤IO
該流程在內(nèi)核模塊啟動時進(jìn)行。
卸鉤IO
該流程在內(nèi)核模塊退出時進(jìn)行。
運行部署
該方法實現(xiàn)在Linux內(nèi)核模塊中,為了防止其它內(nèi)核模塊可能也注冊了原始套接字接口,因此需要在操作系統(tǒng)啟動時優(yōu)先加載。
posted on 2016-07-14 10:27
春秋十二月 閱讀(2558)
評論(3) 編輯 收藏 引用 所屬分類:
Network