重建数据包以通过pcap注入

情况就是这样:在我的场景中,我有3台电脑,A,B和C.

计算机A将数据发送到计算机B.计算机B使用pcap捕获这些数据包,附加标头,重做校验和,然后将另一个以太网接口注入计算机C.所以基本上A发送到C,尽管从C的角度来看,数据来自计算机B.

我的问题是:在TCPDUMP关于剖析捕获的数据包的教程之后,我学会了计算偏移并使用类型转换来获取以太网,ip和tcp头结构。 这样做的方法如下所示:

ethernet = (struct sniff_ethernet*)(packet); ip = (struct sniff_ip*)(packet + SIZE_ETHERNET); size_ip = IP_HL(ip)*4; if (size_ip < 20) { printf(" * Invalid IP header length: %u bytes\n", size_ip); return; } tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip); size_tcp = TH_OFF(tcp)*4; if (size_tcp < 20) { printf(" * Invalid TCP header length: %u bytes\n", size_tcp); return; } payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + size_tcp); 

因为我想注入捕获的数据包以将其从计算机B发送到计算机C,所以我必须修改一些源/目标信息并在完成后重新计算校验和。 但是,我的问题是,由于此数据现在分为以太网头,IP头和TCP头的结构,我如何将它重新组合成pcap_inject可以使用的pcap_inject

可以在这里进行某种连接吗?

从我在这里看到的代码中,你实际上并没有解析libpcap为你捕获的内存。 每个转换操作只是告诉编译器你打算如何处理从指针开始的字节 – 这些对象的大小,找到哪些数据的偏移量以及它们的长度。

如果你通过这些指针修改这个内存,你已经在进程内存中修改了它的唯一副本 – 并且可以使用一些“更基本”的指针将整个内存块交给sendmsg(2)或者无需重新组装数据 – 你永远不会把它分开。

更新

要将数据包注入网络,您需要使用raw(7)套接字类型; IPPROTO_RAW套接字选项是通过raw(7)套接字发送TCP数据包所必需的 – 否则, 所有 TCP数据包将被定向到您打开的raw(7)套接字,使得机器上的网络难以使用。

raw(7)套接字将为您执行一些重新计算任务:

  A protocol of IPPROTO_RAW implies enabled IP_HDRINCL and is able to send any IP protocol that is specified in the passed header. Receiving of all IP protocols via IPPROTO_RAW is not possible using raw sockets. ┌───────────────────────────────────────────────────┐ │IP Header fields modified on sending by IP_HDRINCL │ ├──────────────────────┬────────────────────────────┤ │IP Checksum │Always filled in. │ ├──────────────────────┼────────────────────────────┤ │Source Address │Filled in when zero. │ ├──────────────────────┼────────────────────────────┤ │Packet Id │Filled in when zero. │ ├──────────────────────┼────────────────────────────┤ │Total Length │Always filled in. │ └──────────────────────+────────────────────────────┘ If IP_HDRINCL is specified and the IP header has a nonzero destination address then the destination address of the socket is used to route the packet. When MSG_DONTROUTE is specified, the destination address should refer to a local interface, otherwise a routing table lookup is done anyway but gatewayed routes are ignored. If IP_HDRINCL isn't set, then IP header options can be set on raw sockets with setsockopt(2); see ip(7) for more information. 

让内核重新计算它愿意为你做的任何事情。