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系統調用。
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類