[作者:浩海孤帆]
網絡數據截獲方法
    網絡數據包截獲機制是網絡入侵檢測系統的基礎組件。一般指通過截獲整個網絡的所有信息流量,根據信息源主機,目標主機,服務協議端口等信息簡單過濾掉不關心的數據,再將用戶感興趣的數據發送給更高層的應用程序進行分析。流程圖如下:

圖5.1 網絡數據截獲流程
一方面要,網絡截取模塊要能保證截取到所有網絡上的數據包,尤其是檢測到被分片的數據包(這可能蘊涵著攻擊)。
另方面,數據截取模塊截取數據包的效率也是很重要的。
它直接影響整個入侵檢測系統的運行速度。

5.2
各種數據流截獲方法
5.2.1 利用廣播截取網絡數據流
數據包的截取技術是依賴網卡的。而網卡可以通過廣播監聽到以太網絡上的數據包,這就是數據包截取技術的基礎。
要想截獲不是給自己數據流,就必須繞開系統正常工作的機制,直接通過網卡的混雜模式,使之可以接受目標地址不是自己的MAC地址的數據包,直接訪問數據鏈路層,取數據。
5.2.2各系統截取數據包機制
Linux系統為用戶提供一種在理論上是數據鏈路層的,基于網卡驅動程序的,可以不用操作系統自身協議棧的接口(也稱套接字)-SockPacket. 這種套接字可以從數據鏈路層(就是網線)上直接截取所有鏈路層數據包。而Unix則是通過Libpcap庫直接與內核交互,實現網絡截取。如:Libpcap,Tcpdump等。如圖:

圖5.2 Unix系統監聽機制

BSD Packet Filter(BPF)機制來截取數據包。BPF可以說是各系統中最棒的截獲方式。很多開源嗅探工具就是基于它而開發的。Windows系統也有類似情況,如:win系列上有*.vxd (VxD,VirtualDeviceDrive)(packet*.vxd) 和 網卡.sys(為網卡芯片所開發)來驅動網卡截取數據包。

圖5.3 Windows系統監聽機制
5.2.3 BPF過濾
Unix&Linux系統有兩種數據鏈路層截取機制,分別是BSD系列系統(NetBSD,OpenBSD,FreeBSD等)的BPF和Linux的SOCKET_PACKET。
BPF過濾
BPF主要由兩大部分組成:
網絡頭接口
數據包過濾器。
網絡頭接口從網絡設備驅動程序處收集數據包復制(在提交給系統協議棧之前),并傳遞給正在截獲數據包的應用程序。而過濾器決定某一數據包是被接受或者拒絕以及如果被接受,數據包的那些部分會被復制給應用程序。BPF結構圖如下:

圖5.4 BPF結構示意圖
如:TCPDump注:(1), Libpcap, Sniffer, eeye,等。一般情況,網卡驅動通過網卡把網絡上的電平信號轉化成數據包,再把截取到的數據傳給系統自帶的協議棧,然后在交由系統處理。這種方式與Unix下的BPF不同,它使得網卡驅動在把從網絡截取的數據提交給系統之前,先拷貝一份給BPF,再由BPF 決定是否符合規則,不符合則丟棄,符合則存放到內存指定區,等待處理。
當然,BPF對網卡驅動交給系統協議棧的數據包不做任何干涉。
注1:TCPDump是伯克利實驗室的Van Jacobson,Craig Leres和Stenven McCanne為分析TCP性能問題而寫的跨平臺的監聽程序。

5.3
基于Libpcap庫的通用數據截獲技術
Libpcap是用戶態的數據包截獲API函數接口,有獨立和可移植行。最初,Libpcap是為了強大的,健壯TCPDump而編寫的。它支持BPF過濾機制。Snort就是依賴于libpcap庫進行數據包截取的程序之一(還有Ethereal,eeye等)。 它的優點是可以從任何Unix內核平臺上截取數據包,而不考慮什么芯片類型的網卡和驅動程序。更重要的是,它可以使開發人員編寫自己的解碼,顯示,記錄等程序。

5.2.2.1 Libpcap庫主要函數
1. 頭文件特征(pcap.h)
Libpcap庫(數據流存儲頭文件<Pcap.h>的結構定義如下圖)。前半部分是數據庫存儲文件頭的數據結構定義。

圖5.5 頭文件(pcap.h)定義部分截圖
后半部是信息包頭文件數據結構定義。
2. 打開并讀取設備,設置過濾器部分
與最基層設備打交道。有三個函數:pcap_read() pcap_open_live 和 pcap_setfilter()
3. 脫機方式截取數據
及讀取存儲在營盤上的文件。有兩個Pcap_open_offline()和Pcap_offline_read().
4. 本地網絡設置檢測部分
主要檢測網絡設置的函數有幾個,包括Pcap_lookupdev() pcap_lookupnet()等。 因為前面提過,Libpcap可移植。所以各種平臺的Socket借口都是兼容的。
5. 主程序
都在Pcap.c中,該文件定義了讀取數據的統一接口函數pcap_next(),調用此函數獲取下一個數據包。
5.4 Snort調用Libpcap
在Snort運行啟動時,Snort調用Libpcap庫。當調用libpcap函數并初始化接口時,進入截取數據的循環模塊—pcap循環。
在這個主循環—Pcaploop(),當網卡從網絡介質上接收數據開始,Pcap_loop便對采集來的每個數據包都ProcessPacket()函數處理,如果出錯或達到指定的處理包數就退出。(相關代碼如下)
具體就是,Pcap_loop()最后根據數據鏈路類型來選擇數據包,然后由ProcessPacket()來進行協議分析,實施信息流的匹配。
如:ProcessPaceket函數調用DecodeEthPkt函數來對以太網數據進行解碼。其中DecodeEthPkt()函數再調用子函數Decode IP來對IP協議進行解碼……
Libpcap函數功能列舉:
Pcap_open_live(): 獲得數據包通用句柄。
Pcap_lookup_dev(): 指向網絡可用設備。
Pcap_looknet(): 初步判斷網絡設備本身的IP & netmask。
Pcap_Dump(): 基于TCPDump的,將網絡數據包保存成文件。
程序部分代碼如下:
/* Read all packets on the device. Continue until cnt packets read */

pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
register int n;

for (;;) { //for循環
if (p->sf.rfile != NULL) {
n = pcap_offline_read(p, cnt, callback, user);
} else {
// XXX keep reading until we get something
do {
n = p->read_op(p, cnt, callback, user);
} while (n == 0);
}
if (n <= 0)
return (n); //遇錯誤,返回
if (cnt > 0) {
cnt -= n;
if (cnt <= 0)
return (0); //達到制定數量,返回
}
}
}
pcap_loop()有幾個重要參數:
參數是pv.pkt_cnt,表示總共要捕捉的包的數量。在main函數初始化時,缺省設置為-1,成為永真循環,一直捕捉直到程序退出:
/* initialize the packet counter to loop forever */
pv.pkt_cnt = -1;
或者在命令行中設置要捕捉的包的數量。ParseCmdLine函數的調用中,遇到參數n,重新設定pv.pkt_cnt的值。ParseCmdLine中相關語句如下:
case 'n': /* grab x packets and exit */
pv.pkt_cnt = atoi(optarg);
Snort.c主程序中,Pcap_loop()函數有兩種提取數據模式:
打開網卡和打開文件。
/* get the device file descriptor,打開網卡接口 */

pd = pcap_open_live(pv.interface, snaplen,
pv.promisc_flag ? PROMISC : 0, READ_TIMEOUT, errorbuf);
或者
/* open the file,打開文件 */

pd = pcap_open_offline(intf, errorbuf);
只有以上兩種返回情況。
Snort把真實的數據包存儲在內存中指針指向的數據結構中。在decode.h中,定義了所有Snort要使用到的數據結構,包括Tcp,Ip,以太楨,vlan楨等。Snort的這些結構將指針指向截獲的包上來代表相應的協議。如指向以太楨用數據指針使用_EthrHdr頭。
數據結構:
Typededf struct _etherhdr
{
u_int8_t ether_dst[6]; //目的地址;
u_int8_t ether_src[6]; //源地址;
u_int16_t ether_type; //協議類型;
}
typedef struct _Tcphdr
{
u_int16_t th_sport; //源端口;
u_int16_t th_dport; //目端口;
u_int32_t th_seq; //sequence number;
u_int32_t th_ack; //acknowledgement number;
u_int8_t th_offx2; //offset and reserved;
u_int8_t th_flags; //flags;
u_int16_t th_win; //window;
u_int16_t th_sum; //checksum;
u_int16_t th_urp; //urgent pointer;
}
小結
    網絡數據的截取是入侵檢測系統的基礎。本節從網絡數據截取機制開始講,講述了常見的兩種機制。重點講述了Libpcap庫的網絡數據包截取機制。