Python 在 scapy 中发送 ICMP 数据包并选择正确的接口
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26274524/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
sending ICMP packets in scapy and choosing the correct interface
提问by Pradeep
Can we use the srp() function for a Layer 3 ICMP packet? I see that when we craft an ICMP echo-request packet and use the sr() to send/receive, we do NOT see it getting sent out of the interface , hence no response from the destination. But the same packet if we use the srp() function we see the response. When should we use sr() and when srp()? In the documentation it states sr() is to be used for L3 packet and srp() to be used for L2? But in my case I am not sure why sr() is not working for an ICMP packet? Can some experts please help me understand?
我们可以将 srp() 函数用于第 3 层 ICMP 数据包吗?我看到当我们制作 ICMP 回声请求数据包并使用 sr() 发送/接收时,我们没有看到它从接口发送出去,因此没有来自目的地的响应。但是如果我们使用 srp() 函数,我们会看到相同的数据包响应。我们什么时候应该使用 sr(),什么时候应该使用 srp()?在文档中,它指出 sr() 用于 L3 数据包,而 srp() 用于 L2?但就我而言,我不确定为什么 sr() 不适用于 ICMP 数据包?请高手帮我理解一下?
Also can someone let me know if "iface" argument is needed always. Without that how will scapy know through which interface its supposed to send the packet?
也有人可以让我知道是否总是需要“iface”参数。没有它,scapy 如何知道它应该通过哪个接口发送数据包?
Case 1: sr() function with iface as argument:
案例 1: sr() 函数以 iface 作为参数:
sr(icmp,iface="eth0")
Begin emission:
开始发射:
WARNING: Mac address to reach destination not found. Using broadcast.
Finished to send 1 packets.
^C
Received 0 packets, got 0 answers, remaining 1 packets
(<Results: TCP:0 UDP:0 ICMP:0 Other:0>, <Unanswered: TCP:0 UDP:0 ICMP:1 Other:0>)
Above I do NOT see any ICMP response from the IP 192.168.25.1
上面我没有看到来自 IP 192.168.25.1 的任何 ICMP 响应
Case 2: sr() function without iface:
情况 2:没有 iface 的 sr() 函数:
sr(icmp)
.Begin emission:
......WARNING: Mac address to reach destination not found. Using broadcast.
.Finished to send 1 packets.
...............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................^C
Received 887 packets, got 0 answers, remaining 1 packets
(<Results: TCP:0 UDP:0 ICMP:0 Other:0>, <Unanswered: TCP:0 UDP:0 ICMP:1 Other:0>)
If you see above the received packets is more but I do not see any ICMP response.
如果您在上面看到收到的数据包更多,但我没有看到任何 ICMP 响应。
Case 3: Sending the ICMP packet with srp() instead of sr():
情况 3:使用 srp() 而不是 sr() 发送 ICMP 数据包:
srp(icmp,iface="eth0")
Begin emission:
Finished to send 1 packets.
*
Received 1 packets, got 1 answers, remaining 0 packets
(<Results: TCP:0 UDP:0 ICMP:1 Other:0>, <Unanswered: TCP:0 UDP:0 ICMP:0 Other:0>)
Here I used the srp() function instead of sr() function and now I see that the ICMP echo request was sent properly and I received the response also.
在这里,我使用了 srp() 函数而不是 sr() 函数,现在我看到 ICMP 回显请求已正确发送并且我也收到了响应。
>>> icmp.show2()
###[ Ethernet ]###
dst: 02:00:00:11:01:03
src: 02:00:20:ee:64:01
type: 0x800
###[ IP ]###
version: 4L
ihl: 5L
tos: 0x0
len: 28
id: 1
flags:
frag: 0L
ttl: 64
proto: icmp
chksum: 0xc78c
src: 192.168.25.2
dst: 192.168.25.1
\options\
###[ ICMP ]###
type: echo-request
code: 0
chksum: 0xf7ff
id: 0x0
seq: 0x0
>>>
采纳答案by Yoel
The srfunction per the official API documentation:
根据官方 API 文档的sr功能:
sr(pkts, filter=None, iface=None, timeout=2, inter=0, verbose=None, chainCC=0, retry=0, multi=0)Send and receive packets at layer 3 using the
conf.L3socketsupersocket.
sr(pkts, filter=None, iface=None, timeout=2, inter=0, verbose=None, chainCC=0, retry=0, multi=0)使用
conf.L3socket超级套接字在第 3 层发送和接收数据包。
The srpfunction:
该srp函数:
srp(pkts, filter=None, iface=None, timeout=2, inter=0, verbose=None, chainCC=0, retry=0, multi=0, iface hint=None)Same as
srpbut for working at layer 2 withconf.L2socketsupersocket.
srp(pkts, filter=None, iface=None, timeout=2, inter=0, verbose=None, chainCC=0, retry=0, multi=0, iface hint=None)与
srp使用conf.L2socket超级套接字在第 2 层工作的情况相同。
Since your ICMPpacket has its layer 2 fields filled as well, as shown by the output of ICMP.show2(), you should use the srpfunction. Had you left them untouched, as done in this tutorial, you could have used the srfunction.
由于您的ICMP数据包也填充了第 2 层字段,如 的输出所示ICMP.show2(),您应该使用该srp函数。如果您像本教程中那样保持原样,您就可以使用该sr功能。
Now, regarding your question about ICMP's classification as a layer 2 protocol or a layer 3 protocol. Many think it's a layer 3 protocol, such as here, since it uses the IPheader and "sits" on top of it. However, others consider it to be a layer 2 protocol such as here. This is a questionwith some good answers on this issue, but note that they refer to the OSImodel so the layering scheme numbering is a bit different. This is the best I've managed to locate, from here:
现在,关于您关于将ICMP分类为第 2 层协议还是第 3 层协议的问题。许多人认为它是第 3 层协议,例如此处,因为它使用IP标头并“位于”其顶部。但是,其他人认为它是第 2 层协议,例如此处。这是一个在这个问题上有一些很好答案的问题,但请注意,它们指的是OSI模型,因此分层方案编号略有不同。这是我设法找到的最好的,从这里:
IP itself has no mechanism for establishing and maintaining a connection, or even containing data as a direct payload. Internet Control Messaging Protocol is merely an addition to IP to carry error, routing and control messages and data, and is often considered as a protocol of the network layer.
IP 本身没有建立和维护连接的机制,甚至没有包含数据作为直接有效载荷的机制。Internet 控制消息协议只是IP 的附加,用于承载错误、路由和控制消息和数据,通常被认为是网络层的协议。
EDIT - I've just encountered this link, and thought it's worth a mention:
编辑 - 我刚刚遇到这个链接,并认为值得一提:
ICMP is a protocol within the TCP/IP stack that exist basically to provide control, troubleshooting, and error messages. It runs over IP, like TCP and UDP do, but is a network-layer protocol, like IP, rather than a transport layer protocol like TCP and UDP are. (Yes, this is kind of weird, that ICMP is encapsulated within IP while being on the same layer as IP. But then again, you can encapsulate IP within IP as well.)
ICMP 是 TCP/IP 堆栈中的一个协议,它的存在主要是为了提供控制、故障排除和错误消息。它运行在 IP 上,就像 TCP 和 UDP 一样,但它是一个网络层协议,就像 IP,而不是像 TCP 和 UDP 那样的传输层协议。(是的,这有点奇怪,ICMP 被封装在 IP 中,同时与 IP 位于同一层。但话又说回来,您也可以将 IP 封装在 IP 中。)
RFC 792is also pretty explicit:
RFC 792也非常明确:
ICMP, uses the basic support of IP as if it were a higher level protocol, however, ICMP is actually an integral part of IP.
ICMP,使用IP的基本支持,就好像它是一个更高级别的协议,然而,ICMP实际上是IP的一个组成部分。
And so is RFC 1122:
RFC 1122也是如此:
ICMP is a control protocol that is considered to be an integral part of IP, although it is architecturally layered upon IP, i.e., it uses IP to carry its data end-to-end just as a transport protocol like TCP or UDP does.
...
Although ICMP messages are encapsulated within IP datagrams, ICMP processing is considered to be (and is typically implemented as) part of the IP layer.
ICMP 是一种控制协议,被认为是 IP 的一个组成部分,尽管它在架构上是基于 IP 的,即它使用 IP 来端到端地承载其数据,就像 TCP 或 UDP 之类的传输协议一样。
...
虽然 ICMP 消息封装在 IP 数据报中,但 ICMP 处理被认为是(并且通常被实现为)IP 层的一部分。
Regarding your last question about explicitly specifying the interface, see scapy's tutorial:
关于您关于明确指定接口的最后一个问题,请参阅scapy的教程:
The
send()function will send packets at layer 3. That is to say it will handle routing and layer 2 for you. Thesendp()function will work at layer 2. It's up to you to choose the right interface and the right link layer protocol.
该
send()函数将在第 3 层发送数据包。也就是说,它将为您处理路由和第 2 层。该sendp()功能将在第 2 层工作。由您选择正确的接口和正确的链路层协议。
The official API documentation is a bit more detailed:
官方 API 文档更详细一点:
When Scapy is launched, its routing tables are synchronized with the host's routing table. For a packet sent at layer 3, the destination IP determines the output interface, source address and gateway to be used. For a layer 2 packet, the output interface can be precised, or an hint can be given in the form of an IP to determine the output interface. If no output interface nor hint are given,
conf.ifaceis used.
当 Scapy 启动时,它的路由表与主机的路由表同步。对于在第 3 层发送的数据包,目标 IP 确定要使用的输出接口、源地址和网关。对于二层报文,可以精确输出接口,也可以通过IP的形式提示确定输出接口。如果没有给出输出接口或提示,
conf.iface则使用。
Specifically, the ifaceparameter is used for setting the input interface (but sets also the output interface, if iface_hintis not used):
具体来说,该iface参数用于设置输入接口(但也设置输出接口,如果iface_hint不使用):
iface: listen answers only on the provided interface
iface:仅在提供的界面上收听答案
For hinting on the outputinterface, use iface_hintfor the layer 2 functions:
对于output界面提示,请使用iface_hint第 2 层函数:
There is also an additional parameter,
iface_hint, which give an hint that can help choosing the right output interface. By default, if not specified byiface,conf.ifaceis chosen. The hint takes the form of an IP to which the layer 2 packet might be destinated. The Scapy routing table (conf.route) is used to determine which interface to use to reach this IP.
还有一个附加参数 ,
iface_hint它提供了一个提示,可以帮助选择正确的输出接口。默认情况下,如果未指定iface,conf.iface则选择。提示采用第 2 层数据包可能目的地的 IP 的形式。Scapy 路由表 (conf.route) 用于确定使用哪个接口来访问此 IP。

