简体   繁体   English

使用原始套接字捕获传入和传出数据包

[英]capturing both incoming and outgoing packets using raw socket

I am writing a tool in C for logging data usage of different applications running on my Linux system. 我正在用C编写一个工具,用于记录Linux系统上运行的不同应用程序的数据使用情况。 For this i had created a raw socket and then I bind it with "eth0" which is the name of my interface. 为此,我创建了一个原始套接字,然后将其与接口名称“ eth0”绑定。 But my problem is that, this sockets captures only incoming packets (ie: packets with destination MAC address as my system's MAC address). 但是我的问题是,此套接字仅捕获传入的数据包(即:将目标MAC地址作为我的系统的MAC地址的数据包)。 I can't find any packets that has source MAC address as my system's MAC address. 我找不到任何具有源MAC地址作为系统MAC地址的数据包。 So it means packets written by my own machine are not captured by the raw socket. 因此,这意味着由我自己的机器写入的数据包不会被原始套接字捕获。 But i want to capture packets in both directions for identifying uploaded and downloaded data size. 但是我想双向捕获数据包,以识别上传和下载的数据大小。 Can anybody help? 有人可以帮忙吗?

int main()
{
    int rs,len;
    struct sockaddr_ll addr;
    char buf[65535];

    rs = socket(PF_PACKET,SOCK_RAW,htons(ETH_ALL));
    setsockopt(rs,SOL_SOCKET,SO_BINDDEVICE,"eth0",4);
    while(recvfrom(rs,buf,65535,&addr,&len) > 0){
        //print packets
    }
    return 0;
}

I have found this while searching over your problem. 我在搜索您的问题时发现了这个问题。 I haven't tried this. 我没有尝试过。 May be this will work. 也许这会工作。

  int v=0;
    v = PACKET_MASK_ANY & ~(1<<PACKET_OUTGOING) & ~(1 << PACKET_LOOPBACK);
    setsockopt( raw_sock, SOL_PACKET, PACKET_RECV_TYPE, &v, sizeof(v));

From socket(7) : socket(7)

SO_BINDTODEVICE SO_BINDTODEVICE

Bind this socket to a particular device like “eth0”, as specified in the passed interface name. 将此套接字绑定到特定的设备(如“ eth0”),如传递的接口名称中所指定。 [...] Note that this works only for some socket types, particularly AF_INET sockets. [...] 注意,这仅适用于某些套接字类型,尤其是AF_INET套接字。 It is not supported for packet sockets (use normal bind(2) there). 数据包套接字不支持此功能(在那里使用普通的bind(2))。

You should be looking at the packet(7) man page for this. 您应该在此查看packet(7)手册页。

It may be instructive to download the libpcap library source and look at what it's doing (if you can't just use libpcap instead of rolling your own). 下载libpcap库源代码并查看其功能可能很有帮助(如果您不能只使用libpcap而不是自己滚动库)。 It definitely gets outgoing packets as well as incoming ones. 它肯定会获得传出数据包以及传入数据包。

It appears to make these calls (there are many supported options and configurations so you have to wend through a myriad of ifdefs to discover exactly what's going on -- see pcap-linux.c ): 似乎可以进行这些调用(有许多受支持的选项和配置,因此您必须遍历无数的ifdefs才能发现正在发生的事情-请参阅pcap-linux.c ):

fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL);
...
struct sockaddr_ll sll;
memset(&sll, 0, sizeof(sll));
sll.sll_family          = AF_PACKET;
sll.sll_ifindex         = ifindex;   // Interface index from SIOCGIFINDEX
sll.sll_protocol        = htons(ETH_P_ALL);
bind(fd, (struct sockaddr *) &sll, sizeof(sll));
...
struct packet_mreq      mr;
memset(&mr, 0, sizeof(mr));
mr.mr_ifindex = handlep->ifindex;
mr.mr_type    = PACKET_MR_PROMISC;
setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr))

One other thing to keep in mind. 要记住的另一件事。 When receiving packets sent by your own box, it is frequently the case that the checksums (IP, TCP, and UDP) in the outgoing packets will be incorrect. 当接收到由您自己的盒子发送的数据包时,经常会出现传出数据包中的校验和(IP,TCP和UDP)不正确的情况。 That's because most modern network controllers support checksum offload. 这是因为大多数现代网络控制器都支持校验和卸载。 That means the card will calculate the checksums after the packets have been DMA'd into card memory. 这意味着在将数据包DMA到卡内存后,卡将计算校验和。 Hence, those for outgoing packets will not be correct in your program's buffer (which is filled by the kernel from local memory). 因此,用于传出数据包的那些在程序的缓冲区(由内核从本地内存填充)中将是不正确的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM