2012-11-21 143 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)。