关于ICMP“需要分段,DF位设置"或 ICMP 数据包太大消息 [英] Regarding ICMP "Fragmentation needed, DF bit set" or ICMP packet too big message

查看:204
本文介绍了关于ICMP“需要分段,DF位设置"或 ICMP 数据包太大消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将 ICMP需要分段,DF 位设置"注入服务器,理想情况下,服务器应该开始发送 ICMP 中下一跳 MTU"字段中提到的大小的数据包.但这不起作用.

I'm injecting ICMP "Fragmentation needed, DF bit set" into the server and ideally server should start sending packets with the size mentioned in the field 'next-hop MTU' in ICMP. But this is not working.

这是服务器代码:

#!/usr/bin/env python 
import socket               # Import socket module
import time
import os

range= [1,2,3,4,5,6,7,8,9]
s = socket.socket()         # Create a socket object
host = '192.168.0.17'                   # Get local machine name
port = 12349               # Reserve a port for your service.
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))        # Bind to the port
rand_string = os.urandom(1600)

s.listen(5)                 # Now wait for client connection.
while True:
   c, addr = s.accept()     # Establish connection with client.
   print 'Got connection from', addr
   for i in range:
    c.sendall(rand_string)
        time.sleep(5)
   c.close()

这是客户端代码:

#!/usr/bin/python           # This is client.py file

import socket               # Import socket module

s = socket.socket()         # Create a socket object
host = '192.168.0.17' # Get local machine name
port = 12348              # Reserve a port for your service.
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.connect((host, port))
while 1:
    print s.recv(1024)
s.close()

Scapy 注入 ICMP:

Scapy to inject ICMP:

###[ IP ]###
  version= 4
  ihl= None
  tos= 0x0
  len= None
  id= 1
  flags= DF
  frag= 0
  ttl= 64
  proto= ip
  chksum= None
  src= 192.168.0.45
  dst= 192.168.0.17
  \options\
###[ ICMP ]###
  type= dest-unreach
  code= fragmentation-needed
  chksum= None
  unused= 1300

Send(ip/icmp)

未使用的字段在wireshark 中显示为下一跳MTU.服务器是否足够智能以检查在与客户端通信时未设置 DF 位并且它仍在接收 ICMP需要分片,DF 位设置"消息?如果不是,那么为什么服务器不将其数据包大小从 1500 减少到 1300?

Unused field shows as next-hop MTU in wireshark. Is server smart enough to check that DF Bit was not set when it was communicating with client and it is still receiving ICMP "Fragmentation needed, DF bit set" message? If it is not then why is server not reducing its packet size from 1500 to 1300?

推荐答案

首先,让我们回答您的第一个问题(ICMP 是否通过 TCP 发送?).

First of all, let's answer your first question (is ICMP sent over TCP?).

ICMP 直接通过 IP 运行,如 RFC 792 中所述:

ICMP runs directly over IP, as specified in RFC 792:

ICMP 消息使用基本 IP 标头发送.

ICMP messages are sent using the basic IP header.

这可能有点令人困惑,因为 ICMP 被归类为网络层协议而不是传输层协议,但它考虑到它只是承载错误、路由和控制消息和数据的 IP 的补充,这是有道理的.因此,它不能依赖 TCP 层来传输自身,因为 TCP 层依赖于 ICMP 帮助管理和排除故障的 IP 层.

This can be a bit confusing as ICMP is classified as a network layer protocol rather than a transport layer protocol but it makes sense when taking into account that it's merely an addition to IP to carry error, routing and control messages and data. Thus, it can't rely on the TCP layer to transfer itself since the TCP layer depends on the IP layer which ICMP helps to manage and troubleshoot.

现在,让我们处理您的第二个问题(如果 ICMP 不是通过 TCP 发送的,TCP 如何知道 MTU?).我试图根据我的理解来回答这个问题,依赖于官方规范,但也许最好的方法是分析一些开源网络堆栈实现,以了解真正发生了什么......

Now, let's deal with your second question (How does TCP come to know about the MTU if ICMP isn't sent over TCP?). I've tried to answer this question to the best of my understanding, with reliance on official specifications, but perhaps the best approach would be to analyze some open source network stack implementation in order to see what's really going on...

即使 ICMP 消息未分层在 TCP 上,TCP 层也可能会知道路径的 MTU 值.由操作系统的网络堆栈实现通知 MTU 的 TCP 层,以便它可以使用此值更新其 MSS 值.

The TCP layer may come to know of the path's MTU value even though the ICMP message is not layered upon TCP. It's up to the implementation of OS the network stack to notify the TCP layer of the MTU so it can then use this value to update its MSS value.

RFC 1122 要求 ICMP 消息包括 IP 标头以及前 8 个触发该 ICMP 消息的有问题的数据报的字节数:

RFC 1122 requires that the ICMP message includes the IP header as well as the first 8 bytes of the problematic datagram that triggered that ICMP message:

每条 ICMP 错误消息都包含 Internet 报头和触发错误的数据报的至少前 8 个数据八位字节;可以发送超过 8 个八位字节;与接收到的数据报相比,此标头和数据必须保持不变.

Every ICMP error message includes the Internet header and at least the first 8 data octets of the datagram that triggered the error; more than 8 octets MAY be sent; this header and data MUST be unchanged from the received datagram.

在 Internet 层需要将 ICMP 错误消息传递给传输层的情况下,必须从原始标头中提取 IP 协议编号,并用于选择合适的传输协议实体来处理错误.

In those cases where the Internet layer is required to pass an ICMP error message to the transport layer, the IP protocol number MUST be extracted from the original header and used to select the appropriate transport protocol entity to handle the error.

这说明了操作系统如何确定应更新其 MSS 的 TCP 连接,因为这 8 个字节包括源端口和目标端口.

This illustrates how the OS can pinpoint the TCP connection whose MSS should be updated, as these 8 bytes include the source and destination ports.

RFC 1122 还声明必须有一种机制,通过该机制传输层可以了解可以为给定的 {source, destination, TOS} 三元组发送的最大传输层消息大小.因此,我假设一旦收到 ICMP Fragmentation needed and DF set 错误消息,MTU 值就会以某种方式提供给 TCP 层,TCP 层可以使用它来更新其 MSS 值.

RFC 1122 also states that there MUST be a mechanism by which the transport layer can learn the maximum transport-layer message size that may be sent for a given {source, destination, TOS} triplet. Therefore, I assume that once an ICMP Fragmentation needed and DF set error message is received, the MTU value is somehow made available to the TCP layer that can use it to update its MSS value.

此外,我认为实例化 TCP 连接并使用它的应用层也可以处理此类消息并在更高级别对数据包进行分段.应用程序可以打开一个接收 ICMP 消息的套接字,并在收到这些消息时采取相应的行动.然而,在应用层分片数据包对 TCP & 是完全透明的.IP层.请注意,大多数应用程序将允许 TCP &IP层自行处理这种情况.

Furthermore, I think that the application layer that instantiated the TCP connection and taking use of it may handle such messages as well and fragment the packets at a higher level. The application may open a socket that expects ICMP messages and act accordingly when such are received. However, fragmenting packets at the application layer is totally transparent to the TCP & IP layers. Note that most applications would allow the TCP & IP layers to handle this situation by themselves.

然而,一旦主机收到ICMP Fragmentation required and DF set错误消息,它的行为由较低层决定,就不是决定性的.

However, once an ICMP Fragmentation needed and DF set error message is received by a host, its behavior as dictated by the lower layers is not conclusive.

RFC 5927,第 2.2 节指的是 RFC 1122,第 4.2 节.3.9 规定当从 IP 层传递ICMP Fragmentation and DF set错误消息时,TCP 应该中止连接,因为它表示硬错误条件.RFC 声明主机应该实现此行为,但这不是必须的(第 4.2.5 节).该 RFC 还在第 3.2.2.1 节中声明,必须将接收到的 Destination Unreachable 消息报告给 TCP 层.当在该连接上接收到 ICMP Fragmentation and DF set 错误消息时,实现这两个将导致 TCP 连接的破坏,这没有任何意义,并且显然不是所需的行为.

RFC 5927, section 2.2 refers to RFC 1122, section 4.2.3.9 which states that TCP should abort the connection when an ICMP Fragmentation needed and DF set error message is passed up from the IP layer, since it signifies a hard error condition. The RFC states that the host should implement this behavior, but it is not a must (section 4.2.5). This RFC also states in section 3.2.2.1 that a Destination Unreachable message that is received MUST be reported to the TCP layer. Implementing both of these would result in the destruction of a TCP connection when an ICMP Fragmentation needed and DF set error message is received on that connection, which doesn't make any sense, and is clearly not the desired behavior.

另一方面,RFC 1191 声明 this 关于所需的行为:

On the other hand, RFC 1191 states this in regard to the required behavior:

RFC 1191 未概述发送方预期的特定行为主机,因为不同的应用程序可能有不同的要求,并且不同的实现架构可能有利于不同的策略 [这为这种方法留有余地-OA].

RFC 1191 does not outline a specific behavior that is expected from the sending host, because different applications may have different requirements, and different implementation architectures may favor different strategies [This leaves a room for this method-OA].

唯一需要的行为是主机必须尝试避免发送更多在不久的将来具有相同 PMTU 值的消息.主机可以停止在 IP 标头中设置 Don't Fragment 位(并允许由路由器分段)或减少数据报大小.这更好的策略是降低消息大小,因为碎片会导致更多的流量并消耗更多的互联网资源.

The only required behavior is that a host must attempt to avoid sending more messages with the same PMTU value in the near future. A host can either cease setting the Don't Fragment bit in the IP header (and allow fragmentation by the routers in the way) or reduce the datagram size. The better strategy would be to lower the message size because fragmentation will cause more traffic and consume more Internet resources.

作为结论,我认为该规范对于接收到 ICMP Fragmentation needed and DF set 错误消息后主机所需的行为而言并不明确.我的猜测是两层(IP 和 TCP)都收到消息通知,以便更新它们的 MTU 和 TCP.MSS 值,其中之一负责以较小的块重传有问题的数据包.

For conclusion, I think that the specification is not definitive in regard to the required behavior from a host upon receipt of an ICMP Fragmentation needed and DF set error message. My guess is that both layers (IP & TCP) are notified of the message in order to update their MTU & MSS values, respectively and that one of them takes upon the responsibility of retransmitting the problematic packet in smaller chunks.

最后,关于您的实现,我认为为了完全符合 RFC 1122,您应该更新 ICMP 消息以包含有问题的数据包的 IP 标头,以及接下来的 8 个字节(尽管您可能包含的不仅仅是前 8 个字节).此外,您应该验证在 ICMP 消息所引用的数据包的相应 ACK 之前收到 ICMP 消息.事实上,为了保险起见,我会完全取消那个ACK.

Lastly, regarding your implementation, I think that for full compliance with RFC 1122, you should update the ICMP message to include the IP header of the problematic packet, as well as its next 8 bytes (though you may include more than just the first 8 bytes). Moreover, you should verify that the ICMP message is received before the corresponding ACK for the packet to which that ICMP message refers. In fact, just in order to be on the safe side, I would abolish that ACK altogether.

这里是ICMP消息应该如何实现的示例被建造.如果发送 ICMP 消息作为对其中一个 TCP 数据包的响应失败,我建议您尝试在接收与其相关的 TCP 数据包之前发送 ICMP 消息,以确保在 ACK 之前收到它.仅当同样失败时,尝试完全取消 ACK.

Here is a sample implementation of how the ICMP message should be built. If sending the ICMP message as a response to one of the TCP packets fails, I suggest you try sending the ICMP message before even receiving the TCP packet to which it relates at first, in order to assure it is received before the ACK. Only if that fails as well, try abolishing the ACK altogether.

这篇关于关于ICMP“需要分段,DF位设置"或 ICMP 数据包太大消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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