原始套接字

2021-06-06 21:08:44 字數 3117 閱讀 4481

資料出處:

實際上,我們常用的網路程式設計都是在應用層的報文的收發操作,也就是大多數程式設計師接觸到的流式套接字(sock_stream)

和資料報式套接字

(sock_dgram)

。而這些資料報都是由系統提供的協議棧實現,使用者只需要填充應用層報文即可,由系統完成底層報文頭的填充並傳送。然而在某些情況下需要執行更底層的操作,比如修改報文頭、避開系統協議棧等。這個時候就需要使用其他的方式來實現。

原始套接字

(sock_raw)

是一種不同於

sock_stream

、sock_dgram

的套接字,它實現於系統核心。然而,原始套接字能做什麼呢?首先來說,普通的套接字無法處理

icmp

、igmp

等網路報文,而

sock_raw

可以;其次,

sock_raw

也可以處理特殊的

ipv4

報文;此外,利用原始套接字,可以通過

ip_hdrincl

套接字選項由使用者構造

ip頭。總體來說,

sock_raw

可以處理普通的網路報文之外,還可以處理一些特殊協議報文以及操作

ip層及其以上的資料。

既然sock_raw

有以上特性,所以在某些處理流程上它區別於普通套接字。

· 若設定ip_hdrincl

選項,sock_raw

可以操作

ip頭資料(也就是使用者需用填充

ip頭及其以上的

payload

);否則

sock_raw

無法操作

ip頭資料

· 埠對於sock_raw

而言沒有任何意義

· 如果使用bind

函式繫結本地

ip,那麼如果

ip_hdrincl

未設定,則用此

ip填充源

ip位址;若不呼叫

bind

則將源ip

位址設定為外出介面的主

ip位址

· 如果使用connect

函式設定目標

ip,則可以使用

send

或者write

函式傳送報文,而不需要使用

sendto

函式· 

核心處理流程: · 

接收到的tcp

、udp

分組不會傳遞給任何

sock_raw

· icmp、

igmp

報文分組傳遞給

sock_raw

· 核心不識別的ip

報文傳遞給

sock_raw

· sock_raw是否接收報文:

· protocol指定型別需要匹配,否則不傳遞給該

sock_raw

· 如果使用bind

函式繫結了源

ip,則報文目的

ip必須和繫結的

ip匹配,否則不傳遞給該

sock_raw

· 如果使用connect

函式繫結了目的

ip,則報文源

ip必須和指定的

ip匹配,否則不傳遞給該

sock_raw 

綜上所述,原始套接字處理的只是ip

層及其以上的資料,比如實現

syn flood

攻擊、處理

ping

報文等。當需要操作更底層的資料的時候,就需要採用其他的方式。

如果需要從鏈路層處理報文,那麼就需要採用更加底層的套接字。還是先看下套接字函式的原型吧:

#include 

int socket(int domain, int type, int protocol);

這個函式中,domain

表示協議簇,

type

表示套接字型別,而

protocol

表示的是處理的協議型別。在

linux

下提供了多種底層套接字。下面分別進行簡單介紹。

通過pf_inet

可以構造原始套接字,如下所示:

int fd = socket (pf_inet, sock_raw, ipproto_tcp);

正如前面所講的,它工作在ip

層及其以上各層協議上(當然是在使用

ip_hdrincl

選項之後才能操作

ip層資料啦),但是這種套接字無法接收從本地傳送出去的報文。而使用

sock_packet

型別的套接字,則可以操作鏈路層資料了:

int fd = socket (pf_inet, sock_packet, ipproto_tcp);

不過據說這種方式存在一定的缺陷,而且也不能保證後續版本的系統上一定支援這種方式,因此不推薦使用

pf_packet協議簇是用來取代

sock_packet

的一種程式設計介面。作為一種協議簇,它可以對應兩種不同的套接字型別:

sock_raw

和sock_dgram

。當使用

sock_raw

時,使用者操作鏈路層資料,但是如果使用後者,則由系統處理鏈路層協議頭。這種套接字支援四種協議(

eth_p_ip

、eth_p_arp

、eth_p_rarp

、eth_p_all

)(未確認)

int fd = socket (pf_packet, sock_raw, ipproto_tcp);

int fd = socket (pf_packet, sock_dgram, ipproto_tcp);

這種方式是使用者模式和kernel的ip

網路配置之間的推薦介面

綜上所述,真正能夠實現操作鏈路層資料的只有三種方式:

int fd = socket (pf_inet, sock_packet, ipproto_tcp);

int fd = socket (pf_packet, sock_raw, ipproto_tcp);

int fd = socket (pf_packet, sock_dgram, ipproto_tcp);

原始套接字

參考1 原始套接字能幹什麼?參考2 原始套接字抓包實踐 參考3 各層頭結構 通過原始套接字,我們可以抓取所有傳送到本機的ip包 包括ip頭和tcp udp icmp包頭 也可以抓取所有本機收到的幀 包括資料鏈路層協議頭 普通的套接字無法處理icmp igmp等網路報文,而sock raw可以。利用原...

原始套接字

利用原始套接字實現乙個tcp syn flooding 程式 要求 客戶端不斷向攻擊端傳送syn連線請求 客戶端在傳送資料時,通過源位址隨機位址的方式隱藏自己的 位址 檢驗 在shell下通過 netstat tn 檢查syn recv連線數檢驗自己的程式是否成功 好像有點問題。不能偽造mac位址。...

原始套接字

用於tcp通訊的流式套接字 用於udp通訊報式套接字 特點是 我們傳送資料報只需要組應用層的資料報文,收到的資料報也只有應用層的資料 也就是說明,鏈路層,網路層,傳輸層的資料是由底層協議棧自動幫我們組的 如果想要自己從鏈路層,網路層,傳輸層到應用層組乙個資料報,這個時候需要使用原始套接字 原始套接字...