我们目前正在开发一款旨在“桥接”的原型。 Linux中的本地虚拟接口,用于使用专有硬件发送/接收以太网数据包的API。最终的想法是使用这种专有硬件透明地使用标准库和工具。
作为确保我们想做的事情确实可行的第一步,我们制作了第一个版本的原型,使用libpcap将虚拟接口桥接到实际的以太网接口。以下是我们的所作所为:
当监视PC1上的虚拟接口时,我们会观察到ICMP请求和响应,因此桥接程序可以正常工作,但ping工具无法在应用程序级别获得ICMP响应。
我猜测我们在内核路由过程中太晚注入数据包......或其他什么。
你知道如何正确地做到这一点吗?也许使用替代类型的虚拟接口? (bridge,tun / tap ...)它不能是一个完整的系统/命令行解决方案,因为最终我们想要将数据包桥接到专有API而不是以太网接口,所以我们需要以编程方式访问数据包(因此libpcap的)。
提前感谢您的帮助。
答案 0 :(得分:0)
Linux中的虚拟模块接口无法实现这一点。它们只能从内核向网络硬件设备“向下”传输数据包。并且,与虚拟接口的情况一样,没有硬件设备,当数据包到达此路径的底部时(dummy_xmit
函数),数据包将被丢弃。您可以将其视为单向接收器。
这是调用图:
[applications]
[tcp/ip stack]
|
|
v
pcap_sendpacket -> tpacket_snd -> dev_queue_xmit -> dev_hard_start_xmit -> xmit_one -> netdev_start_xmit -> ndo_start_xmit -> dummy_xmit -> dev_kfree_skb
|
|
pcap_next <- tpacket_rcv <- prot_hook.func <- deliver_skb <-dev_queue_xmit_nit <-----
因此,在您的情况下,来自ping应用程序的ping请求进入设备传输路径。它们在此路径的末尾被丢弃,但在此之前,它们被复制并且这些副本将被传递到在接口上侦听的pcap桥。 Bridge应用程序将它们转发到PC2。 PC2应答ping请求并将响应发送回桥接应用程序。桥接应用程序将这些响应注入设备传输路径,它们向下传输并被丢弃。但在此之前,它们被复制到所有pcap监听器,包括用于间谍和观察流量的tcpdump,但不包括注入它们的桥接应用程序:
++ net/core/dev.c
@@ void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
...
/* Never send packets back to the socket
* they originated from - MvS (miquels@drinkel.ow.org)
*/
if (skb_loop_sk(ptype, skb))
continue;
这就是您看到请求和响应的原因。但是响应没有传递给内核TCP / IP堆栈和ping应用程序,因为虚拟接口无法做到这一点。它们向下传输到dummy_xmit
并被丢弃。
因此,在您的情况下,您应该使用TAP接口,或者,如果您仍想使用pcap来交换数据包,请使用虚拟链接。