原始套接字

2022-08-15 01:54:11 字數 3595 閱讀 3892

標準套接字不能對ip首部或tcp、udp首部進行操作,如果開發底層的應用,比如傳送乙個自定義的ip包、udp包、tcp包、icmp包,偽裝本機ip位址,捕獲所有經過本機的資料報,就要用到原始套接字。

一、面向鏈路層的原始套接字

可以獲取鏈路層的資料報

建立原始套接字

in.h>

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

family:面向鏈路層取pf_packet;type:sock_raw,接收的幀包含mac頭部資訊,傳送幀時也要自己加上mac頭部資訊;sock_dgram,收到的幀無mac頭部資訊,已經經過處理,傳送時也無需新增頭部資訊;protocol:指定要收發的資料報型別,eth_p_ip、eth_p_arp、eth_p_rarp、eth_p_all.注意傳入引數時候,要htons轉換,比如(eth_p_all)。

接收資料

ssize_t recvfrom(int sock, void* buf, size_t len, int flags, struct sockaddr* from, socklen_t* fromlen);

倒數第二個引數傳入時需要的是乙個sockaddr_ll* 型別,

使用如下

struct

sockaddr_ll sa_recv;

recvfrom(fd,buf,

sizeof(buf), (struct sockaddr* )& sarecv, &sa_len)

sockaddr_ll結構體——表示的是乙個與物理裝置無關的物理層位址     p542

struct

sockaddr_ll

sll_ifindex為網路介面型別,單網絡卡時可以為0,表示處理所有介面,對於多網絡卡,則要獲取網絡卡的介面索引然後賦值

struct

sockaddr_ll sll;

struct

ifreq ifr;

strcpy(ifr.ifr_name,

"eth0");

ioctl(sockfd, siocgifindex, &ifr);

sll.sll_ifindex=ifr.ifr_ifindex;

傳送資料sendto

struct

sockaddr_ll sa;

sendto(fd,buf

sizeof(buf), 0, (struct sockaddr* )&sa, sizeof(struct sockaddr_ll);

乙太網幀,標頭檔案p546

struct

ethhdr

獲取網路介面資訊

網路介面請求結構體      p548

struct

ifreq

ifr_ifrn;

union

}

獲取網路介面資訊,一般把網路介面名字傳給ifrn_name,呼叫ioctl來獲取所需要的資訊。

獲取mac位址資訊        p549

struct

sockaddr_ll device;

struct

ifreq ifr;

int sd=socket(pf_packet,sock_dgram, htons(eth_p_all));

memcpy(ifr.ifr_name,

"ens32

",sizeof(struct

ifreq));

ioctl(sd,siocgifhwaddr,&ifr)

unsigned

char dest_mac[6]=;

memcpy(dest_mac,ifr.ifr_hwaddr.sa_data,6);

close(sd);

預設情況下,從任何介面收到的符合指定協議的資料報文都會出傳到原始packet套接字口,而使用bind系統呼叫並以乙個sockaddr_ll結構體物件將packet套接字與某個介面網路像繫結,可以使我們的原始套接字只接收指定介面的資料報文。

繫結網路介面

struct

sockaddr_ll sa;

int fd=socket(pf_packet,sock_raw,htons(0x8902

));//初始化sa

memset(&sa,0,sizeof

(sa));

sa.sll_family=pf_packet;

sa.sll_protocol=htons(0x8902

);strcpy(ifr.ifr_name,if_name);

ioctl(fd,siocgifflages,&ifr);

ioctl(fd,siocgifindex,&ifr);

sa.sll_ifindex=ifr.ifr_ifindex;

//繫結

bind(fd,(

struct sockaddr*)&sa, sizeof(struct sockaddr_ll);

混雜模式

網絡卡工作模式

廣播模式:接收廣播幀

多播模式:不管是不是組內成員,均接收多播幀

直接模式:只接收發給自己的幀

混雜模式:接收所有經過自己網絡卡的幀

無論套接字是否繫結網絡卡,都會全部接收通過本主機(可能有多個網絡卡)所有網絡卡的所有幀。

設定網絡卡混雜模式    p579

struct

ifreq ifr;

strcpy(ifr.ifr_name,if_name);

ioctl(fd,siocgifflags,&ifr);

ifr.ifr_flags|=iff_promisc;

ioctl(fd,siocsifflags,&ifr);

二、面向ip層的原始套接字

可以獲取網路層的資料報

socket(af_inet,sock_raw,protocol);

protocol:ipproto_tcp、ipproto_udp、ipproto_icmp、ipproto_raw,可以多個進行或操作。此處不需要htons,與鏈路層原始套接字不同。

接收包,能接收到完整的ip包,包括ip頭部。

傳送包時,不用ip頭部,核心自動封裝,即傳送從ip後的第乙個位元組開始。除非設定了ip_hdrincl的socket項。不能收到自己傳送出去的包,需要自己組織tcp udp icmp等頭部。

獲取網絡卡ip位址資訊    p598

int sock=socket(af_inet,sock_raw, ipproto_tcp);

strcpy(ifr.ifr_name,

"ens32");

ioctl(sock,siocgifaddr,&ifr);

printf(

"%s\n

",inet_ntoa(((struct sockaddr_in*)&(ifr.ifr_addr))->sin_addr));

原始套接字

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

原始套接字

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

原始套接字

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