0

我的 Ubuntu 虚拟机的 IP 地址是 192.168.1.110。其他一切看起来都很好。我不知道代码有什么问题。也许我使用了错误的包头结构?下面是我的代码和输出。同样,我的主机 IP 应该是 192.168.1.110 并且端口现在肯定是错误的。

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;
}
4

2 回答 2

2

如果您处于混杂模式,Pcap 将显示系统以外的其他流量。为什么您会看到未从您的系统发送或接收的特定数据包将取决于您的网络配置。如果某些以太网交换机不确定它们应该去哪里等,它们偶尔会泄漏发往其他系统的数据包。

您还需要在字节顺序之间进行转换。在现在最常见的情况下,“网络字节顺序”与您机器的字节顺序不同。要打印出端口号,您需要执行以下操作:

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

此外,您可能想尝试struct iphdr而不是struct ip. 我以前见过这样的例子,ip在标题中命名的结构有多个定义,但iphdr对我来说总是正确的。

请记住,您始终可以tcpdump在另一个窗口中运行以查看实际进入的数据包,您可能会收到比预期更多的流量。

于 2012-11-21T23:28:57.260 回答
0

首先,在调用之后pcap_open_live(),调用pcap_datalink()handle如果它没有返回DLT_EN10MB,则退出或重写你的程序,以便它可以处理它返回的值。请参阅tcpdump.org 链接层标头类型页面,了解pcap_datalink().

其次,不要假设数据包是 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)。

于 2012-11-22T19:00:40.933 回答