應用程序可以繞過傳輸層而直接使用ipv4和IPv6,這稱為原始套接口(raw socket)。http://www.CUOXin.com/nufangrensheng/p/3583435.html。
原始套接口是一種對原始網絡報文進行處理的套接口。原始套接口主要應用在底層網絡編程上,同時也是網絡黑客的必備手段。例如sniffer、拒絕服務(DoS)、IP地址欺騙等都需要在原始套接字的基礎上實現。
與原始套接字對應,之前的TCP/UDP的套接字稱為標準套接字,如下圖所示,為標準套接字與原始套接字之間的關系。標準套接字與網絡協議棧的TCP、UDP層打交道,而原始套接字則與IP層級網絡協議棧核心打交道。
原始網絡套接口提供普通的TCP和UDP套接口不提供的以下3個功能:
1、有了原始套接口,進程可以讀與寫ICMPv4、IGMPv4和ICMPv6等分組。
2、有了原始套接口,進程可以讀與寫內核不處理其協議字段的IPv4數據報。
3、有了原始套接口,進程還可以使用IP_HDRINCL套接口選項自行構造IPv4頭部。
創建一個原始套接口涉及如下步驟:
1、把第2個參數指定為SOCK_RAW調用socket函數,以創建一個原始套接口。第3個參數(協議類型)通常不為0。
只有超級用戶才能創建原始套接口。
2、可以在這個原始套接口上如下開啟IP_HDRINCL套接口選項:
const int on = 1;if(setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) 出錯處理
3、可以在這個原始套接口上調用bind函數,不過比較少見。bind函數僅僅設置本地地址,因為原始套接口不存在端口的概念。
4、可以在這個原始套接口上調用connect函數,不過也比較少見。connect函數僅僅設置遠地地址,同樣因為原始套接字不存在端口的概念。
原始套接口的輸出遵循以下規則:
1、普通輸出通過調用sendto或sendmsg并指定宿IP地址完成。如果套接口已經連接,那么也可以調用write、writev或send。
2、如果IP_HDRINCL套接口選項未開啟,那么由進程讓內核發送的數據的起始地址指的是IP頭部之后的第一個字節,因為內核將構造IP頭部并把它置于來自進程的數據之前。內核把所構造的IPv4頭部的協議字段設置成來自socket調用的第3個參數。
3、如果IP_HDRINCL套接口選項已開啟,那么由進程讓內核發送的數據的起始地址指的是IP頭部的第一個字節。進程調用輸出函數寫出的數據量必須包括IP頭部的大小。整個IP頭部由進程構造,不過:(a)IPv4標識字段可置為0,從而告知內核設置該值;(b)IPv4頭部校驗和字段總是由內核計算并存儲;(c)IPv4選項字段是可選的。
4、內核對于超出外出接口MTU的原始分組執行分片。
原始套接口輸入遵循以下規則:
1、接收到的UDP分組和TCP分組絕不傳遞到任何原始套接口。如果一個進程想要讀取含有UDP分組或TCP分組的IP數據報,它就必須在數據鏈路層讀取這些分組。
2、大多數ICMP分組在內核完成處理其中的ICMP消息后傳遞到原始套接口。
3、所有IGMP分組在內核完成處理其中的IGMP消息后傳遞到原始套接口。
4、內核不認識其協議字段的所有IP數據報傳遞到原始套接口。內核對這些分組執行的唯一處理是針對某些IP頭部字段的最小驗證:IP版本、IPv4頭部校驗和、頭部長度以及宿IP地址。
5、如果某個數據報以片段形式到達,那么在它的所有片段均到達且重組出該數據報之前,不傳遞任何片段分組到原始套接口。
新聞熱點
疑難解答