由于traceroute只能診斷UDP通信的包路由,不能確定TCP通信的實際路由(可能變換),因此編寫了本文。為方便描述,下面的IP、MAC和端口均為示例,實際診斷中可更換為具體的值
1. 如何判斷客戶端到服務器的TCP包,是否經過了網關
在客戶端執行 tcpdump -i eno16777728 ether dst b0:b9:8a:69:65:3e and host 192.168.0.26 and tcp port 80 抓取經過網關且往返服務器的TCP端口為80的包
eno16777728 接口名稱;ether 以太網鏈路,dst 目標(src表示源);b0:b9:8a:69:65:3e 網關MAC地址;192.168.0.26 服務器IP地址,80 監聽端口
輸出結果分析
● 有輸出,則表示經過了網關
● 有部分輸出而TCP通信還在進行,則表示先前的包經過了網關,后來路由表項緩存被重定向更新,沒經過網關了
● 不斷輸出,則表示一直經過網關
2. 如何判斷路由表項緩存被重定向更新
在客戶端執行 tcpdump -i eno16777728 src 192.168.1.1 and dst 192.168.1.45 and icmp 抓取來自網關和到達客戶端的所有icmp包
192.168.1.1 網關IP;192.168.1.45 客戶端(出口)IP
輸出結果分析
● 沒有輸出,則表示沒有收到rerdirect包,路由表項緩存不變
● 有輸出類似ICMP redirect 192.168.0.26 to host 192.168.0.26(前面一個IP表示到達服務器的直接路由IP,后一個表示服務器IP)
● 則表示收到了ICMP重定向包,內核會更新路由表項及緩存網關為192.168.0.26,下次通信時就直接發往192.168.0.26了
3. 如何控制接收ICMP重定向
● echo 0 | tee /proc/sys/net/ipv4/conf/*/accept_redirects 禁止所有網卡接收,可避免路由表項緩存被修改
● echo 1 | tee /proc/sys/net/ipv4/conf/*/accept_redirects 啟用所有網卡接收ICMP重定向消息
4. 查看、刷新路由表項緩存
● ip route get 192.168.0.26 可以從輸出中看到通住目標IP的實際路由
● ip route flush cache 清空路由表項緩存,下次通信時內核會查main表(即命令route輸出的表)以確定路由
posted @
2017-12-29 17:24 春秋十二月 閱讀(1976) |
評論 (0) |
編輯 收藏
前言
近期有機會,深入了SSL/TLS協議原理與細節,并分析了相關密碼學內容,心得頗多,歷經半月,終于寫成了這份文檔。
本人水平尚有限,錯誤難免,歡迎指正,不勝感激。
目錄

部分章節預覽
第3章
第5章第4節
第11章第3節
全文
下載地址:
深入理解SSL/TLS技術內幕
posted @
2016-12-15 17:16 春秋十二月 閱讀(1633) |
評論 (0) |
編輯 收藏
算法描述
【公開密鑰】
p是512到1024位的素數
q是160位長,并與p-1互素的因子
g = h^((p-1)/q) mod p,其中h<p-1且g>1
y = g^x mod p
【私有密鑰】
x < q,長160位
【簽名】
k為小于q的隨機數,k^-1為k模q的逆元,m為消息,H為單向散列函數
r = (g^k mod p) mod q
s = (k^-1(H(m)+xr)) mod q
【驗證】
w = s^-1 mod q
u1 = (H(m)w) mod q
u2 = (rw) mod q
v = ((g^u1 * y^u2) mod p) mod q
若v = r,則簽名被驗證
驗簽推導
1. 先證明兩個中間結論
因(h,p)=1(p為素數且h<p,(a1,a1)是數論中的符號,記為a1與a2的最大公約數),故依費馬小定理有h^(p-1)=1 mod p,則對任意整數n,有
g^(nq) mod p = (h^((p-1)/q))^(nq) mod p
= h^(n(p-1)) mod p
= (h^(p-1) mod p)^n mod p
= (1^n) mod p = 1 (1)
對任意整數t、n,可表示為t=nq+z,其中z>0,則有
g^t mod p = g^(nq+z) mod p
= (g^(nq) mod p * (g^z mod p)) mod p
= g^z mod p
= g^(t mod q) mod p (2)
2. 再假設簽名{r,s}和消息m均沒被修改,令H(m)=h,開始推導v
v = ((g^u1 * y^u2) mod p) mod q
= (g^(hw mod q) * ((g^x mod p)^(rw mod q) mod p)) mod q
= ((g^(hw mod q) mod p * ((g^x mod p)^(rw mod q) mod p)) mod p) mod q
= ((g^(hw mod q) mod p * (g^(x * (rw mod q)) mod p)) mod p) mod q
= ((g^(hw) mod p * ((g^(rw mod q) mod p)^x mod p)) mod p) mod q
= ((g^(hw) mod p * ((g^(rw) mod p)^x mod p)) mod p) mod q
= ((g^(hw) mod p * (g^(rwx) mod p)) mod p) mod q
= (g^(hw+rwx) mod p) mod q
= (g^((h+rx)w) mod p) mod q (3)
又因w = s^-1 mod q
故(sw) mod q = 1
=>(((k^-1(h+xr)) mod q)w) mod q = 1
=>((k^-1(h+xr))w) mod q = 1
=>(h+xr)w = k mod q (4)
將(4)式代入(3)式中得
v = (g^(k mod q) mod p) mod q
= (g^k mod p) mod q
= r
3. 最后由(4)式知,若h、r和s任一個有變化(s變化導致w變化),則v ≠ r
posted @
2016-11-24 19:39 春秋十二月 閱讀(5350) |
評論 (0) |
編輯 收藏
算法描述
隨機選擇兩個大的素數 p、q ,且p ≠ q,計算n = pq、r = (p-1)(q-1),依歐拉定理,r即為與n互質的素數個數;選擇一個小于r的整數e(即加密指數),求得e關于模r的逆元d(即解密指數),則{n,e}為公鑰、{n,d}為私鑰;根據模的逆元性質有ed ≡ 1 (mod r);設m為明文,則加密運算為m^e ≡ c (mod n), c即為密文;則解密過程 c^d ≡ m (mod n)。
證明會用到費馬小定理,即
若y為素數且x不為y的倍數, 則 x^(y-1) ≡ 1 (mod y)(費馬小定理的證明需先證明歐拉定理,此處略)。符號≡表示同余,^表示
冪,|表示整除,*表示相乘。
算法證明
第一種證明途徑
因 ed ≡ 1 (mod (p-1)(q-1)),令 ed = k(p-1)(q-1) + 1,其中 k 是整數
則 c^d = (m^e)^d = m^(ed) = m^(k(p-1)(q-1)+1)
1.若m不是p的倍數,也不是q的倍數
則 m^(p-1) ≡ 1 (mod p) (
費馬小定理)
=> m^(k(p-1)(q-1)) ≡ 1 (mod p)
m^(q-1) ≡ 1 (mod q) (
費馬小定理)
=> m^(k(p-1)(q-1)) ≡ 1 (mod q)
故 p、q 均能整除 m^(k(p-1)(q-1)) - 1
=> pq | m^(k(p-1)(q-1)) - 1
即 m^(k(p-1)(q-1)) ≡ 1 (mod pq)
=> m^(k(p-1)(q-1)+1) ≡ m (mod n)
2.若m是p的倍數,但不是q的倍數
則 m^(q-1) ≡ 1 (mod q) (
費馬小定理)
=> m^(k(p-1)(q-1)) ≡ 1 (mod q)
=> m^(k(p-1)(q-1)+1) ≡ m (mod q)
因 p | m
=> m^(k(p-1)(q-1)+1) ≡ 0 (mod p)
=> m^(k(p-1)(q-1)+1) ≡ m (mod p)
故 m^(k(p-1)(q-1)+1) ≡ m (mod pq)
即 m^(k(p-1)(q-1)+1) ≡ m (mod n)
3.若m是q的倍數,但不是p的倍數,證明同上
4.若m同為p和q的倍數時
則 pq | m
=> m^(k(p-1)(q-1)+1) ≡ 0 (mod pq)
=> m^(k(p-1)(q-1)+1) ≡ m (mod pq)
即 m^(k(p-1)(q-1)+1) ≡ m (mod n)
第二種證明途徑
先證明m^ed ≡ m (mod p)恒成立
1.若p為m的因子,則p | m^ed - m顯然成立,即m^ed ≡ m (mod p)
2.若p不為m的因子,令ed = k(p-1)(q-1) + 1,則 m^(ed-1) - 1 = m^(k(p-1)(q-1)) - 1
m^(p-1) ≡ 1 (mod p) (
費馬小定理)
=> m^(k(p-1)) ≡ 1 (mod p)
=> m^(k(p-1)(q-1)) ≡ 1 (mod p)
=> m^(ed-1) ≡ 1 (mod p)
=> m^ed ≡ m (mod p)
同理可證m^ed ≡ m (mod q)
故m^ed ≡ m (mod pq),即m^ed ≡ m (mod n)
又因 c^d = m^e^d = m^(ed)
故 c^d ≡ m (mod n),證畢
總結
第二種比第一種簡單直觀,以上證明途徑對RSA私鑰簽名與驗簽同樣適合。
posted @
2016-11-18 17:05 春秋十二月 閱讀(2642) |
評論 (0) |
編輯 收藏
腳本源碼 由于很多應用項目依賴諸多第三方開源庫,這些開源庫各有不同的核心目錄、庫目標和輸出位置,這里的核心目錄是指
僅產生so庫的工程目錄,庫目標是指
僅產生so庫的make目標,輸出位置是相對于核心目錄的,但不必是子目錄,可用..來回溯到父目錄的某位置,更高層目錄的位置,依次類推。為了統一支持它們,使用了一些技巧,詳見示例腳本如下
1
.PHONY: all clean lib core
2
3
thirdlib=openssl-1.0.1u?build_ssl ACE_wrappers/ace json ncurses-6.0??lib
4
coremod=main
5
6
dir = `echo $@ | awk -F? '{print $$1}'`
7
aim = `echo $@ | awk -F? '{print $$2}'`
8
out = `echo $@ | awk -F? '{print $$3}'`
9
10
copy=\cp -Pf ${dir}/${out}/*.so* output
11
12
define MAKE_SUBDIR
13
echo "${dir},${aim},${out}"; \
14
if [ "$(MAKECMDGOALS)" != "clean" ]; then \
15
$(MAKE) ${aim} -C ${dir}; \
16
if [ "$$is_cp" -eq "1" ]; then \
17
$(copy); \
18
fi \
19
else \
20
$(MAKE) clean -C ${dir}; \
21
fi
22
endef
23
24
all: lib core
25
26
lib: $(thirdlib)
27
28
$(thirdlib)::
29
@is_cp=1; $(MAKE_SUBDIR)
30
31
core: $(coremod)
32
33
$(coremod)::
34
@is_cp=0; $(MAKE_SUBDIR)
35
36
clean: $(thirdlib) $(coremod) 實現技巧 1)使用?作為分隔符,所分隔的3個域依次為核心目錄、庫目標、輸出位置;使用awk來獲取各域,分別為dir、aim和out;在運行過程中,值dir一定非空,而aim為空則表示默認目標,out為空表示輸出位置即為dir目錄。
2)copy為命令變量,功能為每當一個庫編譯完成后,將輸出的so庫拷貝到output下,并保持軟鏈接;對于有的開源庫,需在編譯前,使用對應的選項來調用configure,使其生成so庫。
3)為了重用代碼,定義了MAKE_SUBDIR命令包,參數變量為is_cp,當is_cp為1時,表示當前編譯的是依賴庫,否則是主程序。
4)thirdlib和coremod為依賴文件,使用了雙冒號規則,這樣一來,只要在thirdlib中加入新的依賴庫,指定核心目錄、庫目標和輸出位置即可,其它地方不用改。
posted @
2016-10-19 15:11 春秋十二月 閱讀(3256) |
評論 (0) |
編輯 收藏
腳本概述 當需要在很多(比如幾十至幾百)臺機器上編譯同一程序時,如果一個個地手工拷貝源碼、再編譯,那么效率就很低,為了能大量節省手工、并行地編譯,因此寫了一個腳本,該腳本基于自動化腳本語言expect(expect基于tcl)實現,基本原理是針對每個遠程主機,創建一個子進程,在該子進程內先調用scp拷貝源碼到遠程主機,再用ssh登錄到遠程主機、發送cd、configure和make命令,交互期間的命令輸出多用正則分析,最終的編譯輸出保存到當前目錄output子目錄下。其命令行參數說明如下:
● 第1參數為遠程主機配置文件:一個多行文本文件,每行格式為IP 用戶名 密碼,空格符分隔,支持#注釋。
● 第2參數為本地主機源碼目錄:要求該目錄存在Makefile和configure文件。
● 第3參數為遠程主機目標目錄:用于存放源碼的位置。
腳本實現 拷貝源碼
1
proc copy_file {host user srcdir dstdir passwd {to 10} } {
2
if [catch "spawn scp -rq $srcdir $user@$host:$dstdir" msg] {
3
send_error "failed to spawn scp: $msg\n"
4
exit 1
5
}
6
7
set timeout $to
8
expect_after eof {
9
send_error "$host scp died unexpectedly\n"
10
exit 1
11
}
12
expect {
13
"(yes/no)?" { send "yes\r"; exp_continue }
14
-re "(?:P|p)assword:" { send "$passwd\r" }
15
timeout { do_timeout "$host scp" }
16
}
17
18
expect {
19
full_buffer { exp_continue }
20
timeout { exp_continue }
21
eof
22
}
23
}
第2行調用spawn命令執行scp命令,并用catch捕捉錯誤;當執行成功后,第12行用expect等待遠端輸出(超時默認為10秒),第13、14行自動輸入用戶名和密碼,當過程中網絡連接斷開時,會匹配到第8行的eof;當輸出完成連接關閉時,會匹配到第21行的eof;如果輸出太多超過expect內部的buffer時,會匹配到第19行的full_buffer,這里由于為了提高效率,使用了靜默方式的scp,因些實際會匹配到第20行的timeout,不管匹配到哪種情況,都要繼續直到eof。
執行編譯
1
proc do_make {host user passwd subdir {to 10} } {
2
if [catch {spawn ssh $user@$host} msg ] {
3
send_error "failed to spawn ssh: $msg\n"
4
exit 1
5
}
6
7
set timeout $to
8
expect_after eof {
9
send_error "$host ssh died unexpectedly\n"
10
exit 1
11
}
12
13
expect {
14
"*yes/no" { send "yes\r"; exp_continue }
15
-re "(?:P|p)assword:" { send "$passwd\r" }
16
timeout { do_timeout "$host ssh" }
17
}
18
wait_cmd $spawn_id passwd
19
20
send "cd $subdir\r"
21
wait_cmd $spawn_id cd
22
23
send "source configure\r"
24
wait_cmd $spawn_id configure
25
26
send "make\r"
27
wait_cmd $spawn_id make
28
29
send "exit\r"
30
expect eof
31
}
關于spawn和expect的解釋與上節
拷貝源碼相同,不同的是依次發送命令cd、source configure、make,每個命令須等到命令提示符后(調用自定義函數wait_cmd)再發下一個,最后發送exit退出ssh、導致連接關閉,匹配到最后一行的eof。對于有的項目源碼,可能沒有或不用配置,那么configure文件可以不存在或內容為空,如果不存在導致報錯也沒關系,不影響make;如果configure出錯,那么make也會出錯。這里使用source是為了使配置在當前shell中生效。
主循環
1
set f [open $file r]
2
set curtime [clock seconds]
3
4
log_user 0
5
set s {[:blank:]}
6
set pattern "^(\[^#$s]+)\[$s]+(\[^$s]+)\[$s]+(\[^$s]+)"
7
8
while { [gets $f line] != -1 } {
9
if { ![regexp $pattern [string trimleft $line] ? host user passwd] } {
10
continue
11
}
12
send_user "$host $user $passwd\n"
13
if { ![fork] } {
14
15
set filename output/${host}_[clock format $curtime -format %y.%m.%d_%H.%M.%S].log
16
log_file -noappend -a $filename
17
18
copy_file $host $user $srcdir $dstdir $passwd 30
19
do_make $host $user $passwd $subdir 30
20
21
send_user "$host finish\n"
22
exit
23
}
24
}
打開遠程主機配置文件,讀取每一行直到文件尾,忽略注釋行,用正則提取IP、用戶名和密碼,創建子進程,按IP和當前時間命名log文件(由于前面調用log_user 0關閉了控制臺輸出,因此為了能記錄輸出到日志文件,一定要加-a選項),最后調用函數copy_file和do_make。
完整腳本下載:
autobuild.zip
posted @
2016-09-28 11:04 春秋十二月 閱讀(3850) |
評論 (0) |
編輯 收藏
描述
攔截Linux動態庫API的常規方法,是基于動態符號鏈接覆蓋技術實現的,基本步驟是
1. 重命名要攔截的目標動態庫。
2. 創建新的同名動態庫,定義要攔截的同名API,在API內部調用原動態庫對應的API。這里的同名是指與重命名前動態庫前的名稱相同。
顯而易見,如果要攔截多個不同動態庫中的API,那么必須創建多個對應的同名動態庫,這樣一來不僅繁瑣低效,還必須被優先鏈接到客戶二進制程序中(根據動態庫鏈接原理,對重復ABI符號的處理是選擇優先鏈接的那個動態庫)。 另外在鉤子函數的實現中,若某調用鏈調用到了原API,則會引起死循環而崩潰。本方法通過直接修改ELF文件中的動態庫API入口表項,解決了常規方法的上述問題。
特點
1. 不依賴于動態庫鏈接順序。
2. 能攔截多個不同動態庫中的多個API。
3. 支持運行時動態鏈接的攔截。
4. 鉤子函數內的實現體,若調用到原API,則不會死循環。
實現
攔截映射表
為了支持特點2和3,建立了一個攔截映射表,這個映射表有2級。第1級為ELF文件到它的API鉤子映射表,鍵為ELF文件句柄,值為API鉤子映射表;第2級為API到它的鉤子函數映射表,鍵為API名稱,值為包含最老原函數地址和最新鉤子函數地址的結構體,如下圖
當最先打開ELF文件成功時,會在第1級映射表中插入記錄;反之當最后關閉同一ELF文件時,就會從中移除對應的記錄。當第一次掛鉤動態庫API時,就會在第2級映射表插入記錄;反之卸鉤同一API時,就會從中刪除對應的記錄。
計算ELF文件的映像基地址
計算映像基地址是為了得到ELF中動態符號表和重定位鏈接過程表的內容,因為這些表的位置都是相對于基地址的偏移量,該算法在打開ELF文件時執行,如下圖
EXE文件為可執行文件,DYN文件為動態庫。對于可執行文件,映射基地址為可執行裝載段的虛擬地址;對于動態庫,可通過任一API的地址減去它的偏移量得到,任一API的地址可通過調用libdl.so庫API dlsym得到,偏移量通過查詢動態鏈接符號表得到。
打開ELF文件
為了支持特點2即攔截不同動態庫的多個API,節省每次掛鉤API前要打開并讀文件的開銷,獨立提供了打開ELF文件的接口操作,流程如下圖
若輸入ELF文件名為空,則表示打開當前進程的可執行文件,此時要從偽文件系統/proc/self/exe讀取文件路徑名,以正確調用系統調用open。當同一ELF文件被多次打開時,只須遞增結構elf的引用計數。
掛鉤API
當打開ELF文件后,就可掛鉤API了,流程如下圖
當第一次掛鉤時,需要保存原函數以供后面卸鉤;第二次以后繼續掛鉤同一API時,更新鉤子函數,但原函數不變。
卸鉤API
當打開ELF文件后,就可卸鉤API了,流程如下圖
關閉ELF文件
因為提供了打開ELF文件的接口操作,所以得配有關閉ELF文件的接口操作。當不需要掛鉤API的時候,就可以關閉ELF文件了,流程如下圖
運行時動態攔截裝置
在初始化模塊中打開當前可執行文件,掛鉤libdl.so庫的API dlopen和dlsym;在轉換模塊中,按動態庫句柄和API名稱在攔截映射表中查找鉤子函數,若找到則返回鉤子函數,否則返回調用dlsym的結果;在銷毀模塊中,卸鉤dlopen和dlsym。
當動態庫被進程加載的時候,會調用初始化模塊;當被進程卸載或進程退出的時候,會調用銷毀模塊;當通過dlsym調用API時,則會在dlsym的鉤子函數中調用轉換模塊。通過環境變量LD_PRELOAD將動態庫libhookapi.so設為預加載庫,這樣就能攔截到所有進程對dlopen及dlsym的調用,進而攔截到已掛鉤動態庫API的調用。
posted @
2016-08-25 11:10 春秋十二月 閱讀(2274) |
評論 (0) |
編輯 收藏
描述
云查殺平臺以nginx作為反向代理服務器,作為安全終端與云查詢服務的橋梁。當安全終端需要查詢黑文件時,HTTP請求及其響應都會經過nginx,為了獲取并統計一天24小時查詢的黑文件數量,就得先截獲經過nginx的HTTP響應,再做數據分析。截獲HTTP數據流有多種方法,為了簡單高效,這里使用了掛接HTTP過濾模塊的方法,另外為了不影響nginx本身的IO處理,將HTTP響應實體發送到另一個進程即統計服務,由統計服務來接收并分析HTTP響應,架構如下圖
統計服務由1個接收線程和1個存儲線程構成,其中接收線程負責接收從nginx過濾模塊發來的HTTP響應實體,解析它并提取黑文件MD5,加入共享環形隊列;而存儲線程從共享環形隊列移出黑文件MD5,插入到臨時內存映射文件,于每天定時同步到磁盤文件。
特點
這種架構減少了nginx IO延遲,保證了nginx的穩定高效運行,從而不影響用戶的業務運行;本地連接為非阻塞的,支持了統計服務的獨立運行與升級。
實現
nginx過濾模塊
該流程運行在nginx工作進程。
由于nginx采用了異步IO機制,因此僅當截獲到HTTP響應實體也就是有數據經過時,才有后面的操作;若沒有數據,則什么也不用做。這里每次發送前先判斷是否連接了統計服務,是為了支持統計服務的獨立運行與升級,換句話說,不管統計服務是否運行或崩潰,都不影響nginx的運行。
統計服務
接收線程
這里的接收線程也就是主線程。
存儲線程
存儲線程為另一個工作線程。
同步文件定時器的時間間隔要比新建文件定時器的短,由于定時器到期的事件處理是一種異步執行流,所以將它們當做并行,與“從q頭移出黑文件MD5”操作畫在了同一水平方向。
posted @
2016-08-25 11:10 春秋十二月 閱讀(1091) |
評論 (0) |
編輯 收藏
本方法適用于linux 2.6.x內核。
1. 先獲取dentry所屬文件系統對應的掛載點,基本原理是遍歷文件系統vfsmount樹,找到與dentry有相同超級塊的vfsmount,實現如下
next_mnt函數實現了
先根遍歷法,遍歷以root為根的文件系統掛載點,p為遍歷過程中的當前結點,返回p的下一個掛載點;vfsmnt_lock可通過內核函數kallsyms_on_each_symbol或kallsyms_lookup_name查找獲得。
2. 再調用內核函數d_path,接口封裝如下
posted @
2016-08-24 19:22 春秋十二月 閱讀(5853) |
評論 (0) |
編輯 收藏
描述
原始套接字具有廣泛的用途,特別是用于自定義協議(標準協議TCP、UDP和ICMP等外)的數據收發。在Linux下攔截套接字IO的一般方法是攔截對應的套接字系統調用,對于發送為sendmsg和sendto,對于接收為recvmsg和recvfrom。這種方法雖然也能攔截原始套接字IO,但要先判斷套接字的類型,如果為SOCK_RAW(原始套接字類型),那么進行攔截處理,這樣一來由于每次IO都要判斷套接字類型,性能就比較低了。因此為了直接針對原始套接字來攔截,提高性能,發明了本方法。
本方法可用于防火墻或主機防護系統中,丟棄接收和發送的攻擊或病毒數據包。
特點
運行在內核態,直接攔截所有進程的原始套接字IO,支持IPv4和IPv6。
實現
原理
在Linux內核網絡子系統中,struct proto_ops結構提供了協議無關的套接字層到協議相關的傳輸層的轉接,而IPv4協議族中內置的inet_sockraw_ops為它的一個實例,對應著原始套接字。因此先找到inet_sockraw_ops,再替換它的成員函數指針recvmsg和sendmsg,就可以實現攔截了。下面以IPv4為例(IPv6同理),說明幾個流程。
搜索inet_sockraw_ops
該流程在掛鉤IO前進行。由于inet_sockraw_ops為Linux內核未導出的內部符號,因此需要通過特別的方法找到它,該特別的方法基于這樣的一個事實:
◆ 所有原始套接字接口均存放在以SOCK_RAW為索引的雙向循環鏈表中,而inet_sockraw_ops就在該鏈表的末尾。
◆ 內核提供了注冊套接字接口的API inet_register_protosw,對于原始套接字類型,該API將輸入的套接字接口插入到鏈表頭后面。
算法如下
注冊p前或注銷p后,鏈表如下
注冊p后,鏈表如下
掛鉤IO
該流程在內核模塊啟動時進行。
卸鉤IO
該流程在內核模塊退出時進行。
運行部署
該方法實現在Linux內核模塊中,為了防止其它內核模塊可能也注冊了原始套接字接口,因此需要在操作系統啟動時優先加載。
posted @
2016-07-14 10:27 春秋十二月 閱讀(2559) |
評論 (3) |
編輯 收藏