2012-11-21 142 views
0

我的Ubuntu虛擬機的IP地址是192.168.1.110。其他一切都很好。我不知道代碼有什麼問題。也許我正在使用錯誤的包頭結構? 下面是我的代碼和輸出。我的主機IP應該是192.168.1.110,現在的端口肯定是錯誤的。從libpcap捕獲的數據包中獲取錯誤的ip和端口號

sudo ./sniffall 0 
84.72.137.105:38055 192.168.1.105:56652 
192.168.1.105:56652 174.141.213.124:28073 
84.72.137.105:38055 192.168.1.105:56652 
192.168.1.105:56652 174.141.213.124:28073 
84.72.137.105:38055 192.168.1.105:56652 


#include <pcap.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netinet/ip.h> 
#include <netinet/if_ether.h> 
#include <netinet/ether.h> 
#include <sys/socket.h> 
#include <netinet/tcp.h> 

void getPacket(u_char *args, const struct pcap_pkthdr *pkthdr, const u_char *packet){ 
    struct ip *ip; 
    struct tcphdr *tcp; 
    ip = (struct ip*)(packet+sizeof(struct ether_header)); 
    tcp = (struct tcphdr*)(packet+sizeof(struct ether_header)+sizeof(struct ip)); 

    char* src = inet_ntoa(ip->ip_src); 

    printf("%s:%d ",src,tcp->source); 
    char* dst = inet_ntoa(ip->ip_dst); 
    printf(" %s:%d\n", dst, tcp->dest); 

} 

int main(int argc, char *argv[]){ 
    char errbuf[PCAP_ERRBUF_SIZE], *device; 
    device = argv[1]; 
    pcap_t *handle; 
    handle = pcap_open_live(device, BUFSIZ, 1, 1000, errbuf); 
    if(!handle){ 
     device = pcap_lookupdev(errbuf); 
     handle = pcap_open_live(device, BUFSIZ, 1, 1000, errbuf); 
     if(!handle){ 
       printf("Couldn't open device %s: %s\n", device, errbuf); 
     } 
    } 

    pcap_loop(handle, 5, getPacket, NULL); 
    return 0; 
} 
+0

您正在打開混雜模式下的pcap手柄。也許你看到電線上的其他交通? – pilcrow

+0

這看起來不像你程序的輸出。它不是打印':'後面跟着端口號。您還應該使用'ntohs'將端口號從網絡轉換爲主機字節順序。 – Barmar

+1

你有一大塊代碼被註釋掉了。如果不需要的話,那對於試圖幫助回答你的問題的人來說只是噪音:-)只是一個友好的筆記! – corsiKa

回答

2

如果您處於混雜模式,Pcap將顯示除系統之外的其他流量。爲什麼你看到特定的數據包沒有被髮送或從你的系統收到將取決於你的網絡配置。有些以太網交換機偶爾會將流向其他系統的數據包泄漏,如果他們不確定應該去哪裏等。

您還需要在字節順序之間進行轉換。在現在最常見的情況下,「網絡字節順序」與您的機器的字節順序不同。要打印的端口號,你需要做的是這樣的:

printf("%s:%d ",src,ntohs(tcp->source)); 

此外,你可能想嘗試struct iphdr而不是struct ip。我在前面看到了一些實例,其中標題中有一個名爲ip的結構有多個定義,但iphdr總是適合我。

請記住,您始終可以在另一個窗口中運行tcpdump以查看實際進入的數據包,這可能是您收到的流量超出了您的預期。

0

首先,調用pcap_open_live()後,呼籲handlepcap_datalink(),如果它不返回DLT_EN10MB,要麼退出或重新編寫程序,以便它可以處理它返回的值。有關pcap_datalink()支持的值的說明,請參閱the tcpdump.org link-layer header types page

二,做好假定該數據包是IPv4報文,除非你要麼安裝的"ip"過濾器或已檢查數據包的類型(例如,在以太網頭類型字段),以確保數據包是一個IPv4數據包。

三,做不是假設一個IPv4數據包的標題正好是sizeof(struct ip)字節長。我假設sizeof(struct ip)將是20,這是最小 IPv4頭的長度,但頭可能包括選項 - 檢查IPv4頭的「頭長度」字段(它是以4字節單詞爲單位,所以一個值爲5意味着「20字節」)並將其用作報頭的長度(確保它至少爲5--如果小於5,則報文無效 - 然後乘以4得到報頭的長度)。

四,不要假設包是TCP包,除非你有兩種安裝的"ip and tcp"或只是"tcp"過濾器(後者,你仍然需要檢查自己,看看它是否是IPv4數據包)或者檢查了IPv4報頭的「協議」字段,以確保其值爲6(對於TCP)。