【原創】網絡報文抓取研究


1     引言

網絡報文抓取是指通過對主機網絡設備的探測,實現獲取該網絡當前傳輸的所有信息,並根據信息的源主機、目標主機、服務協議和端口等信息簡單過濾掉不關心數據,然后提交給上層應用程序進行進一步處理。

2     網絡數據包捕獲原理

一個包捕獲機制包含三個主要部分

1) 包捕獲機制

不同的操作系統實現的底層包捕獲機制可能是不一樣的,但從形式上看大同小異。數據包常規的傳輸路徑依次為網卡、設備驅動層、數據鏈路層、IP層、傳輸層、最后到達應用程序。而包捕獲機制是在數據鏈路層增加一個旁路處理,對發送和接收到的數據包做過濾/緩沖等相關處理,最后直接傳遞到應用程序。

2) 包過濾機制

包過濾機制是對所捕獲到的數據包根據用戶的要求進行篩選,最終只把滿足過濾條件的數據包傳遞給用戶程序。

3) 用戶程序的接口

對用戶程序而言,包捕獲機制提供了一個統一的接口,使用戶程序只需要簡單的調用若干函數就能獲得所期望的數據包。這樣一來,針對特定操作系統的捕獲機制對用戶透明。

3     網絡數據包捕獲主要實現技術介紹

3.1    SOCK_RAW  原始套接字

我們常用的網絡編程都是在應用層的報文的收發操作,也就是流式套接字(SOCK_STREAM)和數據包式套接字(SOCK_DGRAM)。而這些數據包都是由系統提供的協議棧實現,用戶只需要填充應用層報文即可,由系統完成底層報文頭的填充並發送。

原始套接字(SOCK_RAW)是一種不同於SOCK_STREAM、SOCK_DGRAM的套接字,它實現於系統核心。可以處理特殊的IPv4、ICMP、IGMP等網絡報文。總體來說,SOCK_RAW可以處理普通的網絡報文之外,還可以處理一些特殊協議報文以及操作IP層及其以上的數據。

3.1.1    SOCK_RAW 抓包實現

1)    利用PF_INET協議族創建RAW SOCKET

socket(PF_INET,SOCK_RAW,IPPROTO_TCP|IPPROTO_UDP)

采用這樣的方法接收到的數據都是發往本機的數據,不能接受從本機發出去的數據。第三個參數協議若是指定,只能接受符合指定協議的數據包:

IPPROTO_TCP:接收采用tcp傳輸的數據包。

IPPROTO_UDP:接受采用udp傳輸的數據包。

2)     利用PF_PACKET協議族創建RAW SOCKET

socket(PF_PACKET,SOCK_RAW, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ARP|ETH|RARP))

這種方法創建的套接字是在數據鏈路層直接抓取以太網幀。可以接收到發往本機和本機發出的數據,第三個參數的協議類型有:

ETH_P_IP 0x0800   :只接收發往本機mac的ip類型的數據幀

ETH_P_ARP 0x0806  :只接受發往本機mac的arp類型的數據幀

ETH_P_RARP 0x8035 :只接受發往本機mac的rarp類型的數據幀

ETH_P_ALL 0x0003 :接收發往本機mac的所有類型的數據幀, 和從本機發出的所有類型的數據幀。

3.2    Libpcap

Libpcap是Packet Capture library的英文縮寫,是Unix/Linux平台下的網絡數據包捕獲函數庫,該庫提供的C函數接口用於捕獲經過指定網絡接口(通過將網卡設置為混雜模式,可以捕獲所有經過該網絡接口的數據包)的數據包。

Libpcap提供的接口函數主要實現和封裝了與數據包的采集、構造、發送等有關的功能。著名的tcpdump就是在Libpcap的基礎上開發完成的。

3.2.1    Libpcap 工作原理

Libpcap是一個獨立於系統的用戶級數據包捕獲API接口,為底層網絡監測提供了一個可以移植的框架。

Libpcap庫主要由三個部分組成,網絡分接頭、數據包過濾器和用戶API。

1)     網絡分接頭

網絡分接頭(Network Tap)一種鏈路層旁路機制,負責采集網卡數據包。

libpcap的包捕獲機制就是在數據鏈路層加一個旁路處理。當一個數據包到達網絡接口時,libpcap首先利用已經創建的Socket從鏈路層驅動程序中獲得該數據包的拷貝,再通過Tap函數將數據包發給BPF過濾器。

2)     數據包過濾器

數據包過濾器(Packet Filter) 針對數據包的一種過濾機制,在Libpcap中采用BPF(BSDPacket Filter)算法對數據包執行過濾操作,這種算法的基本思想就是基於規則匹配,對符合條件的數據包進行放行。

3)    用戶API

用戶API是Libpcap面向上層應用程序提供的編程接口,用戶通過調用相關的函數實現數據包的捕獲或者發送。

其具體的工作流程如下圖所示:

 

3.2.2    Libpcap 抓包框架

由於Libpcap是一種與系統無關,采用分組捕獲機制的分組捕獲函數庫,用於訪問數據鏈路層,在不同的平台上采用統一的編程接口,使用LibPcap編寫的程序可以自由地跨平台使用。

Libpcap具體抓包流程如下圖所示:

 

3.2.3    Libpcap 庫主要抓包函數

1)     打開設備進行嗅探

pcap_t*pcap_open_live(char *device, int snaplen, int promisc,

 int to_ms, char *ebuf)

2)     編譯過濾規則

int pcap_compile ( pcap_t * p, struct bpf_program * fp, char * str,

int optimize, bpf_u_int32 netmask )

3)     設置編譯后的過濾規則

intpcap_setfilter(pcap_t *p, struct bpf_program *fp)

4)     抓包

intpcap_loop(pcap_t *p, int cnt, pcap_handler callback,

u_char*user)

5)     回調函數

voidgot_packet(u_char *args, const struct pcap_pkthdr *header, const u_char*packet)

6)     關閉會話

voidpcap_close(pcap_t *p)

3.3    WinPcap

WinPcap是LibPcap的Windows版本,它是一個基於Win32的捕獲數據包和網絡分析的體系結構,它包括一個內核級的包過濾器,一個底層的動態鏈接庫(Packet.dll),一個高層並且與系統無關的庫(WPcap.dll,基於LibPcap0.6.2版本)。WinPcap是集成於Windows95,98,ME,NT,2000和XP操作系統的設備驅動程序,它可以從網卡捕獲或者發送原始數據,同時能夠過濾並且倉儲數據包。開發WinPcap這個項目的目的在於為Win32應用程序提供訪問網絡底層的能力。

3.3.1  WinPcap內部結構

Winpcap是針對Win32平台上的抓包和網絡分析的一個架構,它由內核級的網絡組包過濾器(Netgroup Packet Filter,NPF)、用戶級的動態鏈接庫Packet.dll和Wpcap.dlI等 3個模塊組成[7]。

1)網絡組包過濾器。它是運行於操作系統內核中的驅動程序,它直接與網卡驅動程序進行交互,獲取在網絡上傳輸的原始數據包。NPF與操作系統有關,WinPcap開發組針對不同的Windows操作系統提供了不同版本的NPF。在Win95/98/ME系統中,它以VXD文件形式存在,在WindowsNT和Windows 2000系統中,它以SYS文件形式存在。該模塊提供了抓取數據包以及發送數據包的基本功能,此外還提供了一些高級功能,如數據包過濾系統和檢測引擎。

2)低級動態鏈接庫。Pactet.dll用於在Win32平台上為數據包驅動程序提供一個公共的接口。不同的Windows版本在用戶態和內核態之間提供互不相同的接口,而Pactet.dll可以屏蔽這些接口區別,提供一個與系統無關的API。基於Pactet.dll開發的數據包截獲程序可以運行於不同的Win32平台而不必重新進行編譯。Pactet.dll可以執行如獲取適配器名稱、動態驅動器加載以及獲得主機掩碼及以太網沖突次數等低級操作。

3)高級動態鏈接庫。Wpcap.dll模塊與Unix系統下的BSD截獲架構提供的Libpcap庫完全兼容。它提供了一組功能強大且跨平台的函數,利用這些函數可以不去關心適配器和操作系統的類型。Wpcap.dll含有諸如產生過濾器、定義用戶級緩沖以及包注入等高級功能。編程人員既可以使用包含在Pactet.dll中的低級函數直接進入內核級調用,也可以使用由Wpcap.dll提供的高級函數調用,這樣功能更強,使用也更為方便。Wpcap.dll的函數調用會自動調用Pactet.dll中的低級函數,並且可能被轉換成若干個NPF系統調用。

3.3.2  WinPcap的主要函數庫

Winpcap函數庫主要有如下函數:
1)int  pcap_findalldevs (pcap_if_t **,char *)
用來獲得網卡的列表
2)voidpcap_freealldevs (pcap_if_t *)   
與int pcap_findalldevs (pcap_if_t **,char *)配套使用,當不需要網卡列表時,用此函數釋放空間
3)pcap_t     *pcap_open_live(const char *, int, int,int, char *)
用來得到一個包抓取得描述符
4)Int  pcap_loop(pcap_t *, int, pcap_handler, u_char*)
捕獲數據包,不會響應pcap_open_live()中設置的超時時間
5)int     pcap_dispatch(pcap_t *, int, pcap_handler,u_char *)
捕獲數據包。可以不被阻塞
6)int          pcap_next_ex(pcap_t *, structpcap_pkthdr **, const u_char **)
捕獲數據包
7)int          pcap_compile(pcap_t *, structbpf_program *, const char *, int,  bpf_u_int32)
編譯一個過濾設備,與pcap _ setfilter () 配合使用
8)int     pcap_setfilter(pcap_t *, struct bpf_program*)
用來聯系一個在內核驅動上過濾的過濾器,這時所有網絡數據包都將流經過濾器,並拷貝到應用程序中。

3.4    JPcap

JPcap是一個能夠捕獲,發送網絡數據包的Java類庫包。這個包用到了LibPcap和WinPcap。使用時需要安裝LibPcap(UNIX平台) 或者WinPcap(Windows平台)庫。

目前JPcap在FreeBSD 3.x,Linux RedHat 6.1,Solaris和Microsoft Windows 2000/XP系統上已經做過測試,並且支持Ethernet,IPv4,IPv6,ARP/RARP,TCP,UDP,ICMPv4協議。JPcap是一個Java類集合,它為網絡數據包的捕獲提供接口和系統支持。JPCAP的類庫結構

Jpcap0.4版本共有1個接口14個類,分別簡介如下:

1、 接口綜述

JpcapHandler:這個接口用來定義分析被捕獲數據包的方法

2、 類綜述

ARPPacket:這個類描述了ARP/RARP包,繼承了Packet類 

DatalinkPacket:這個抽象類描述了數據鏈路層的包,它繼承了java.lang.Object

EthernetPacket:這個類描述了以太幀包,繼承DatalinkPacket類

ICMPPacket:這個類描述了ICMP包,繼承了IPPacket類

IPAddress:繼承了java.lang.Object,這個類描述了IPv4和IPv6地址,其中也包含了將IP地址轉換為域名的方法

IPPacket:這個類描述了IP包,繼承了Packet類,支持IPv4和IPv6

IPv6Option:它繼承了java.lang.Object,這個類描述了IPv6選項報頭

Jpcap:它用來捕獲數據包,繼承了java.lang.Object

Jpcap.JpcapInfo:Jpcap的內部類,它包含被捕獲數據包的信息(在jpcap0.4修改部分BUG之后不再使用這個類)

JpcapSender:它用來發送一個數據包,繼承了java.lang.Object

JpcapWriter:它用來將一個被捕獲的數據包保存到文件,繼承了java.lang.Object

Packet:這個類是所有被捕獲的數據包的基類,繼承了java.lang.Object

TCPPacket:這個類描述TCP包,繼承了IPPacket類

UDPPacket:這個類描述了UDP包,繼承了IPPacket類

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM