繁体   English   中英

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

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

我正在用C编写一个工具,用于记录Linux系统上运行的不同应用程序的数据使用情况。 为此,我创建了一个原始套接字,然后将其与接口名称“ eth0”绑定。 但是我的问题是,此套接字仅捕获传入的数据包(即:将目标MAC地址作为我的系统的MAC地址的数据包)。 我找不到任何具有源MAC地址作为系统MAC地址的数据包。 因此,这意味着由我自己的机器写入的数据包不会被原始套接字捕获。 但是我想双向捕获数据包,以识别上传和下载的数据大小。 有人可以帮忙吗?

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

我在搜索您的问题时发现了这个问题。 我没有尝试过。 也许这会工作。

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

socket(7)

SO_BINDTODEVICE

将此套接字绑定到特定的设备(如“ eth0”),如传递的接口名称中所指定。 [...] 注意,这仅适用于某些套接字类型,尤其是AF_INET套接字。 数据包套接字不支持此功能(在那里使用普通的bind(2))。

您应该在此查看packet(7)手册页。

下载libpcap库源代码并查看其功能可能很有帮助(如果您不能只使用libpcap而不是自己滚动库)。 它肯定会获得传出数据包以及传入数据包。

似乎可以进行这些调用(有许多受支持的选项和配置,因此您必须遍历无数的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))

要记住的另一件事。 当接收到由您自己的盒子发送的数据包时,经常会出现传出数据包中的校验和(IP,TCP和UDP)不正确的情况。 这是因为大多数现代网络控制器都支持校验和卸载。 这意味着在将数据包DMA到卡内存后,卡将计算校验和。 因此,用于传出数据包的那些在程序的缓冲区(由内核从本地内存填充)中将是不正确的。

暂无
暂无

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

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