問題描述
將傳入數據包注入網絡接口 (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(ð);
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 GabeL、abligh、user1643650、Neil Stephens)