將傳入數據包注入網絡接口 (Injecting an incoming packet to a network interface)


問題描述

將傳入數據包注入網絡接口 (Injecting an incoming packet to a network interface)

我希望能夠模擬某個物理網絡接口上的傳入數據包。

具體來說,給定一個字節數組和一個接口名稱,我希望能夠使該接口認為包含這些字節的數據包從另一個接口(很可能在另一台機器上)到達。

我已經實現了準備數據包的代碼,但我不確定下一步是什麼。

我應該指出,我實際上需要用我的字節來提供接口,而不是使用可能在其他機器上產生類似結果的解決方法(我已經看到其他問題的答案提到環回接口和外部工具)。此代碼應該模擬一台機器上的流量,該機器期望通過特定接口從某些來源接收流量。


參考解法

方法 1:

I'm going to stick my neck out and say this is not possible without kernel modifications, and possibly driver modifications. Note that:

  • There are plenty of ways of generating egress packets through a particular interface, including libpcap. But you want to generate ingress packets.

  • There are plenty of ways of generating ingress packets that are not through a physical interface ‑ this is what tap/tun devices are for.

If you modify the kernel to allow direct injection of packets into a device's receive queue, that may have unexpected effects, and is still not going to be an accurate simulation of the packets arriving in hardware (e.g. they will not be constrained to the same MTU etc). Perhaps you can build an iptables extension that fools the kernel into thinking the packet came from a different interface; I'm not sure that will do what you need though.

If all you need is simulation (and you are happy with a complete simulation), build a tap/tun driver, and rename the tap interface to eth0 or similar.

方法 2:

Another solution is to create a new dummy network device driver, which will have the same functionality as the loopback interface (i.e. it will be dummy). After that you can wrap up a creation of simple tcp packet and specify in the source and destination addresses the addresses of the two network devices.

It sounds a little hard but it's worth trying ‑ you'll learn a lot for the networking and tcp/ip stack in linux.

方法 3:

Depending on which network layer you're trying to simulate, there may be a work‑around.

I have had success getting ip packets into the ingress queue with an ethernet 'hairpin'. That is, by setting the source and destination MAC address to the local interface, sending the packet results in it first appearing as an egress packet, then being 'hairpinned' and also appearing as an ingress packet.

This at least works under linux using pcapplusplus (libpcap under the hood), with my wireless interface. Your millage may vary.

This will obviously only suit your needs if you're OK with modifying the ethernet header, ie only simulating a higher layer.

Here is a snippet of c++ where I spoof a rst tcp packet for a local socket:

        //always use the actual device source MAC, even if we're spoofing the remote rst
        //  this produces a 'hairpin' from the egress to the ingress on the interface so the tcp stack actually processes the packet
        //  required because the tcp stack doesn't process egress packets (at least on a linux wireless interface)
        pcpp::EthLayer eth(localMAC,localMAC);
        pcpp::IPv4Layer ip(remoteIP, localIP);
        pcpp::TcpLayer tcp(remotePort, localPort);
        pcpp::Packet pac(60);

        ip.getIPv4Header()‑>timeToLive = 255;
        tcp.getTcpHeader()‑>rstFlag = 1;
        tcp.getTcpHeader()‑>ackFlag = 1;
        tcp.getTcpHeader()‑>ackNumber = pcpp::hostToNet32(src.Ack);
        tcp.getTcpHeader()‑>sequenceNumber = pcpp::hostToNet32(src.Seq);

        pac.addLayer(&eth);
        pac.addLayer(&ip);
        pac.addLayer(&tcp);

        pac.computeCalculateFields();
        dev‑>sendPacket(&pac);

EDIT: the same code works on windows on an ethernet interface. It doesn't seem to do the same 'hairpin' judging from wireshark, but the tcp stack does process the packets.

(by GabeLablighuser1643650Neil Stephens)

參考文件

  1. Injecting an incoming packet to a network interface (CC BY‑SA 2.5/3.0/4.0)

#linux-kernel #C






相關問題

選擇 Linux I/O 調度程序 (Selecting a Linux I/O Scheduler)

Android可加載內核模塊錯誤:賦值使指針從沒有強制轉換的整數 (Android Loadable Kernel Module Error: assignment makes integer from pointer without a cast)

文件描述符中實際存儲了多少信息? (How much information is actually stored in a file descriptor?)

hrtimer mengulangi tugas di kernel Linux (hrtimer repeating task in the Linux kernel)

我可以在 C 代碼中使用 LKM 內核代碼中的“getpwuid”嗎? (Can I use "getpwuid" from kernel code in LKM in c code?)

將傳入數據包注入網絡接口 (Injecting an incoming packet to a network interface)

無法從 D3 睡眠狀態喚醒 pci 總線 (Unable to wake pci bus form D3 sleep satate)

在 Linux 中使用 DMA 的最簡單方法 (Easiest way to use DMA in Linux)

Linux I2C 通信問題 (Linux I2C communication issues)

理解 perf stat 輸出中的數字 (Make sense of numbers in perf stat output)

我如何在 amazon Linux AMI 上找到我的 Linux 發行版? (How i could find my Linux distribution on amazon Linux AMI?)

將參數傳遞給系統調用 (Passing arguments to system calls)







留言討論