在 scapy 中发送 ICMP 数据包并选择正确的接口 [英] sending ICMP packets in scapy and choosing the correct interface

查看:209
本文介绍了在 scapy 中发送 ICMP 数据包并选择正确的接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们可以将 srp() 函数用于第 3 层 ICMP 数据包吗?我看到当我们制作 ICMP 回声请求数据包并使用 sr() 发送/接收时,我们没有看到它从接口发送出去,因此没有来自目的地的响应.但是如果我们使用 srp() 函数,我们会看到相同的数据包响应.我们什么时候应该使用 sr(),什么时候应该使用 srp()?在文档中,它指出 sr() 用于 L3 数据包,而 srp() 用于 L2?但就我而言,我不确定为什么 sr() 不适用于 ICMP 数据包?请高手帮我理解一下?

也有人可以让我知道是否总是需要iface"参数.没有它,scapy 如何知道它应该通过哪个接口发送数据包?

案例 1:sr() 函数以 iface 作为参数:

sr(icmp,iface="eth0")

开始发射:

警告:未找到到达目的地的 Mac 地址.使用广播.发完1个包.^C收到 0 个数据包,得到 0 个回答,剩余 1 个数据包(<结果:TCP:0 UDP:0 ICMP:0 Other:0>,<未应答:TCP:0 UDP:0 ICMP:1 Other:0>)

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

情况 2:没有 iface 的 sr() 函数:

sr(icmp).开始排放:......警告:未找到到达目的地的 Mac 地址.使用广播..完成发送1个数据包.…………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………...................................^C收到 887 个数据包,得到 0 个回答,剩余 1 个数据包(<结果:TCP:0 UDP:0 ICMP:0 Other:0>,<未应答:TCP:0 UDP:0 ICMP:1 Other:0>)

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

案例 3:使用 srp() 而不是 sr() 发送 ICMP 数据包:

srp(icmp,iface="eth0")开始发射:发完1个包.*收到 1 个数据包,得到 1 个答案,剩余 0 个数据包(<结果:TCP:0 UDP:0 ICMP:1 Other:0>,<未应答:TCP:0 UDP:0 ICMP:0 Other:0>)

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

<预><代码>>>>icmp.show2()###[以太网]###夏令时:02:00:00:11:01:03源代码:02:00:20:ee:64:01类型:0x800###[ IP ]###版本:4L国际标准:5L托斯:0x0长度:28编号:1标志:碎片:0L电话号码:64原型:icmp校验和:0xc78c源代码:192.168.25.2夏令时:192.168.25.1\选项\###[ICMP]###类型:回声请求代码:0校验和:0xf7ff编号:0x0序列:0x0>>>

解决方案

sr 函数根据 官方 API 文档:

<块引用>

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,它给出了一个提示,可以帮助选择正确的输出接口.默认情况下,如果iface 未指定,则选择conf.iface.提示采用第 2 层数据包可能目的地的 IP 的形式.Scapy 路由表 (conf.route) 用于确定使用哪个接口来访问此 IP.

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?

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?

Case 1: sr() function with iface as argument:

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

Case 2: sr() function without iface:

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.

Case 3: Sending the ICMP packet with srp() instead of sr():

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.

>>> 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
>>>                  

解决方案

The sr function per the official API documentation:

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.L3socket supersocket.

The srp function:

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

Same as srp but for working at layer 2 with conf.L2socket supersocket.

Since your ICMP packet has its layer 2 fields filled as well, as shown by the output of ICMP.show2(), you should use the srp function. Had you left them untouched, as done in this tutorial, you could have used the sr function.


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 IP header and "sits" on top of it. However, others consider it to be a layer 2 protocol such as here. This is a question with some good answers on this issue, but note that they refer to the OSI model so the layering scheme numbering is a bit different. This is the best I've managed to locate, from here:

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.

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.)

RFC 792 is also pretty explicit:

ICMP, uses the basic support of IP as if it were a higher level protocol, however, ICMP is actually an integral part of IP.

And so is 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.


Regarding your last question about explicitly specifying the interface, see scapy's tutorial:

The send() function will send packets at layer 3. That is to say it will handle routing and layer 2 for you. The sendp() function will work at layer 2. It’s up to you to choose the right interface and the right link layer protocol.

The official API documentation is a bit more detailed:

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.iface is used.

Specifically, the iface parameter is used for setting the input interface (but sets also the output interface, if iface_hint is not used):

iface: listen answers only on the provided interface

For hinting on the output interface, use iface_hint for the layer 2 functions:

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 by iface, conf.iface is 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.

这篇关于在 scapy 中发送 ICMP 数据包并选择正确的接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆