原始套接字SOCK RAW

2021-07-07 07:01:23 字數 3071 閱讀 9899

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

原始套接字SOCK RAW

實際上,我們常用的網路程式設計都是在應用層的報文的收發操作,也就是大多數程式設計師接觸到的流式套接字 sock stream 和資料報式套接字 sock dgram 而這些資料報都是由系統提供的協議棧實現,使用者只需要填充應用層報文即可,由系統完成底層報文頭的填充並傳送。然而在某些情況下需要執行更底...

LWIP 原始套接字(SOCK RAW)

收錄於 lwip lwip協議 相關知識彙總 lwip學習筆記 通常情況下我們接觸到的套接字為兩類 1 位元組流套接字 sock stream 面向連線的socket套接字,用於tcp服務應用。2 資料報套接字 sock dgram 無連線 不可靠的socket套接字,用於udp服務應用。從使用者的...

UNIX網路程式設計 原始套接字SOCK RAW

實際上,我們常用的網路程式設計都是在應用層的報文的收發操作,也就是大多數程式設計師接觸到的流式套接字 sock stream 和資料報式套接字 sock dgram 而這些資料報都是由系統提供的協議棧實現,使用者只需要填充應用層報文即可,由系統完成底層報文頭的填充並傳送。然而在某些情況下需要執行更底...