在scapy中发送ICMP数据包并选择正确的接口

Pra*_*eep 7 python scapy

我们可以将srp()函数用于第3层ICMP数据包吗?我看到当我们制作ICMP echo-r​​equest数据包并使用sr()发送/接收时,我们看不到它被发送出接口,因此没有来自目的地的响应.但是如果我们使用srp()函数,我们会看到相同的数据包响应.什么时候应该使用sr()和srp()?在文档中,它声明sr()将用于L3数据包,而srp()将用于L2?但在我的情况下,我不确定为什么sr()不适用于ICMP数据包?有些专家可以帮我理解吗?

如果总是需要"iface"论证,也有人可以告诉我.没有它,scapy将如何知道它应该发送数据包的接口?

情况1:使用iface作为参数的sr()函数:

sr(icmp,iface="eth0")
Run Code Online (Sandbox Code Playgroud)

开始排放:

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>)
Run Code Online (Sandbox Code Playgroud)

上面我没有看到来自IP 192.168.25.1的任何ICMP响应

案例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>)
Run Code Online (Sandbox Code Playgroud)

如果你看到上面收到的数据包更多,但我没有看到任何ICMP响应.

情况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>)
Run Code Online (Sandbox Code Playgroud)

这里我使用了srp()函数而不是sr()函数,现在我看到ICMP echo请求已正确发送,我也收到了响应.

>>> 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
>>>                  
Run Code Online (Sandbox Code Playgroud)

Yoe*_*oel 5

根据官方 API 文档sr功能:

sr(pkts, filter=None, iface=None, timeout=2, inter=0, verbose=None, chainCC=0, retry=0, multi=0)

使用conf.L3socket超级套接字在第 3 层发送和接收数据包。

srp函数:

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 层工作的情况相同。

由于您的ICMP数据包也填充了第 2 层字段,如 的输出所示ICMP.show2(),您应该使用该srp函数。如果您像本教程中那样保持原样,您就可以使用该sr功能。


现在,关于您关于将ICMP分类为第 2 层协议还是第 3 层协议的问题。许多人认为它是第 3 层协议,例如此处,因为它使用IP标头并“位于”其顶部。但是,其他人认为它是第 2 层协议,例如此处这是一个在这个问题上有一些很好答案的问题,但请注意,它们指的是OSI模型,因此分层方案编号略有不同。这是我设法找到的最好的,从这里

IP 本身没有建立和维护连接的机制,甚至没有包含数据作为直接有效载荷的机制。Internet 控制消息协议只是IP 的附加,用于承载错误、路由和控制消息和数据,通常被认为是网络层的协议。

编辑 - 我刚刚遇到这个链接,并认为值得一提:

ICMP 是 TCP/IP 堆栈中的一个协议,它的存在主要是为了提供控制、故障排除和错误消息。它运行在 IP 上,就像 TCP 和 UDP 一样,但它是一个网络层协议,就像 IP,而不是像 TCP 和 UDP 那样的传输层协议。(是的,这有点奇怪,ICMP 被封装在 IP 中,同时与 IP 位于同一层。但话又说回来,您也可以将 IP 封装在 IP 中。)

RFC 792也非常明确:

ICMP,使用IP的基本支持,就好像它是一个更高级别的协议,然而,ICMP实际上是IP的一个组成部分。

RFC 1122也是如此:

ICMP 是一种控制协议,被认为是 IP 的一个组成部分,尽管它在架构上是基于 IP 的,即它使用 IP 来端到端地承载其数据,就像 TCP 或 UDP 之类的传输协议一样。
...
虽然 ICMP 消息封装在 IP 数据报中,但 ICMP 处理被认为是(并且通常被实现为)IP 层的一部分。


关于您关于明确指定接口的最后一个问题,请参阅scapy的教程

send()函数将在第 3 层发送数据包。也就是说,它将为您处理路由和第 2 层。该sendp()功能将在第 2 层工作。由您选择正确的接口和正确的链路层协议。

官方 API 文档更详细一点:

当 Scapy 启动时,它的路由表与主机的路由表同步。对于在第 3 层发送的数据包,目标 IP 确定要使用的输出接口、源地址和网关。对于二层报文,可以精确输出接口,也可以通过IP的形式提示确定输出接口。如果没有给出输出接口或提示,conf.iface则使用。

具体来说,该iface参数用于设置输入接口(但也设置输出接口,如果iface_hint不使用):

iface:仅在提供的界面上收听答案

对于output界面提示,请使用iface_hint第 2 层函数:

还有一个附加参数 ,iface_hint它提供了一个提示,可以帮助选择正确的输出接口。默认情况下,如果未指定ifaceconf.iface则选择。提示采用第 2 层数据包可能目的地的 IP 的形式。Scapy 路由表 ( conf.route) 用于确定使用哪个接口来访问此 IP。