Linux下Libpcap源碼分析和包過濾機制 (1)

當設備找到後,下一步工作就是打開設備以準備捕獲數據包。Libpcap的包捕獲是建立在具體的操作系統所提供的捕獲機制上,而Linux系統隨着版本的不同,所支持的捕獲機制也有所不同。
libpcap是unix/Linux平臺下的網絡數據包捕獲函數包,大多數網絡監控軟件都以它爲基礎。libpcap可以在絕大多數類unix平臺下工作,本文分析了libpcapLinux 下的源代碼實現,其中重點是Linux的底層包捕獲機制和過濾器設置方式,同時也簡要的討論了 libpcap使用的包過濾機制 BPF。

網絡監控

絕大多數的現代操作系統都提供了對底層網絡數據包捕獲的機制,在捕獲機制之上可以建立網絡監控(Network Monitoring)應用軟件。網絡監控也常簡稱爲sniffer,其最初的目的在於對網絡通信情況進行監控,以對網絡的一些異常情況進行調試處理。但隨着互連網的快速普及和網絡攻擊行爲的頻繁出現,保護網絡的運行安全也成爲監控軟件的另一個重要目的。例如,網絡監控在路由器,防火牆、入侵檢查等方面使用也很廣泛。除此而外,它也是一種比較有效的黑客手段,例如,美國政府安全部門的"肉食動物"計劃。

包捕獲機制

從廣義的角度上看,一個包捕獲機制包含三個主要部分:最底層是針對特定操作系統的包捕獲機制,最高層是針對用戶程序的接口,第三部分是包過濾機制。

不同的操作系統實現的底層包捕獲機制可能是不一樣的,但從形式上看大同小異。數據包常規的傳輸路徑依次爲網卡、設備驅動層、數據鏈路層、IP層、傳輸層、最後到達應用程序。而包捕獲機制是在數據鏈路層增加一個旁路處理,對發送和接收到的數據包做過濾/緩衝等相關處理,最後直接傳遞到應用程序。值得注意的是,包捕獲機制並不影響操作系統對數據包的網絡棧處理。對用戶程序而言,包捕獲機制提供了一個統一的接口,使用戶程序只需要簡單的調用若干函數就能獲得所期望的數據包。這樣一來,針對特定操作系統的捕獲機制對用戶透明,使用戶程序有比較好的可移植性。包過濾機制是對所捕獲到的數據包根據用戶的要求進行篩選,最終只把滿足過濾條件的數據包傳遞給用戶程序。

libpcap應用程序框架

libpcap提供了系統獨立的用戶級別網絡數據包捕獲接口,並充分考慮到應用程序的可移植性。libpcap可以在絕大多數類unix平臺下工作,參考資料 A 中是對基於 libpcap 的網絡應用程序的一個詳細列表。在windows平臺下,一個與libpcap 很類似的函數包 winpcap 提供捕獲功能,其官方網站是http://winpcap.polito.it/。

libpcap 軟件包可從 http://www.tcpdump.org/ 下載,然後依此執行下列三條命令即可安裝,但如果希望libpcap能在Linux上正常工作,則必須使內核支持"packet"協議,也即在編譯內核時打開配置選項 CONFIG_PACKET(選項缺省爲打開)。


./configure
./make
./make install


libpcap源代碼由20多個C文件構成,但在Linux系統下並不是所有文件都用到。可以通過查看命令make的輸出瞭解實際所用的文件。本文所針對的libpcap版本號爲0.8.3,網絡類型爲常規以太網。libpcap應用程序從形式上看很簡單,下面是一個簡單的程序框架:


char * device; /* 用來捕獲數據包的網絡接口的名稱 */
pcap_t * p; /* 捕獲數據包句柄,最重要的數據結構 */
struct bpf_program fcode; /* BPF 過濾代碼結構 */

/* 第一步:查找可以捕獲數據包的設備 */
device = pcap_lookupdev(errbuf);

/* 第二步:創建捕獲句柄,準備進行捕獲 */
p = pcap_open_live(device, 8000, 1, 500, errbuf);

/* 第三步:如果用戶設置了過濾條件,則編譯和安裝過濾代碼 */
pcap_compile(p, &fcode, filter_string, 0, netmask);
pcap_setfilter(p, &fcode);

/* 第四步:進入(死)循環,反覆捕獲數據包 */
for( ; ; )
{
while((ptr = (char *)(pcap_next(p, &hdr))) == NULL);
		
/* 第五步:對捕獲的數據進行類型轉換,轉化成以太數據包類型 */
eth = (struct libnet_ethernet_hdr *)ptr;

/* 第六步:對以太頭部進行分析,判斷所包含的數據包類型,做進一步的處理 */
if(eth->ether_type == ntohs(ETHERTYPE_IP)) 
…………
if(eth->ether_type == ntohs(ETHERTYPE_ARP)) 
…………
}
	
/* 最後一步:關閉捕獲句柄,一個簡單技巧是在程序初始化時增加信號處理函數,
以便在程序退出前執行本條代碼 */
pcap_close(p);


檢查網絡設備

libpcap 程序的第一步通常是在系統中找到合適的網絡接口設備。網絡接口在Linux網絡體系中是一個很重要的概念,它是對具體網絡硬件設備的一個抽象,在它的下面是具體的網卡驅動程序,而其上則是網絡協議層。Linux中最常見的接口設備名eth0和lo。Lo 稱爲迴路設備,是一種邏輯意義上的設備,其主要目的是爲了調試網絡程序之間的通訊功能。eth0對應了實際的物理網卡,在真實網絡環境下,數據包的發送和接收都要通過 eht0。如果計算機有多個網卡,則還可以有更多的網絡接口,如eth1,eth2 等等。調用命令ifconfig可以列出當前所有活躍的接口及相關信息,注意對eth0的描述中既有物理網卡的MAC地址,也有網絡協議的IP地址。查看文件/proc/net/dev也可獲得接口信息。

 
libpcap調用pcap_lookupdev()函數獲得可用網絡接口的設備名。首先利用函數 getifaddrs() 獲得所有網絡接口的地址,以及對應的網絡掩碼、廣播地址、目標地址等相關信息,再利用 add_addr_to_iflist()、add_or_find_if()、get_instance() 把網絡接口的信息增加到結構鏈表 pcap_if 中,最後從鏈表中提取第一個接口作爲捕獲設備。其中 get_instanced()的功能是從設備名開始,找第一個是數字的字符,做爲接口的實例號。網絡接口的設備號越小,則排在鏈表的越前面,因此,通常函數最後返回的設備名爲 eth0。雖然 libpcap 可以工作在迴路接口上,但顯然libpcap 開發者認爲捕獲本機進程之間的數據包沒有多大意義。在檢查網絡設備操作中,主要用到的數據結構和代碼如下:


	/* libpcap 自定義的接口信息鏈表 [pcap.h] */
struct pcap_if 
{
struct pcap_if *next; 
char *name; /* 接口設備名 */
char *description; /* 接口描述 */
		
/*接口的 IP 地址, 地址掩碼, 廣播地址,目的地址 */
struct pcap_addr addresses; 
bpf_u_int32 flags;	/* 接口的參數 */
};

char * pcap_lookupdev(register char * errbuf)
{
	pcap_if_t *alldevs;
	……
		pcap_findalldevs(&alldevs, errbuf);
		……
		strlcpy(device, alldevs->name, sizeof(device));
	}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章