TCP通信中的消息定义



我是一个网络新手,特别是TCP(我一直在愚弄UDP,但仅此而已)。我正在开发一个基于在两个端点之间交换消息的简单协议。这些消息需要经过认证,所以我实现了一个加密层来处理这个问题。然而,尽管UDP对数据包有一个合理的定义,它构成了一次可以传输的最小单元,TCP协议(就我的理解而言)是完全面向流的。

现在,这让我有点困惑。在交换消息时,我如何知道一个消息的开始和另一个消息的结束?原则上,我显然可以通信固定长度的消息,或者首先在某些报头中通信每个消息的大小。然而,这可能会受到攻击:虽然当然不可能扭曲或确定通信的内容,但上述技术可以很容易地通过在中间添加单个字节来完全破坏我的通信。

假设我需要传输一条1234567字节长的消息。首先,我用一个表示消息大小的整数通信4个字节。好吧。然后我开始发送真正的信息。该消息被分成几个包,分别被接收。现在,攻击者只需发送一个额外的数据包,假装它是对话的一部分。它可以只有一个字节长:这完全破坏了我实现的任何同步机制!该消息中间有一个伪字节,因此无法成功解码。不仅如此,第一条消息的最后一个字节破坏了第二条消息的对齐,以此类推:连接被破坏了,而且是通过一个简单、简单的攻击!这次袭击的可能性和可行性到底有多大?

所以我想知道:一次可以传输的最大数据单位是多少?我知道发送的呼叫并不对应于接收的呼叫:消息可以分成不同的块。我如何将这些包以某种方式组合在一起,以便我知道它们被打包在一起?是否有一种方法来定义一个更高级别的消息,该消息被重建和对齐在一起,并触发对类似接收的函数的单个调用?如果不是,我可以找到什么其他解决方案来保持我的通信重新对齐,即使存在攻击者?

基本上很难控制操作系统将流划分为TCP数据包的方式(定义TCP协议的RFC声明TCP堆栈应该允许客户端通过使用推送函数强制发送缓冲数据,但它没有定义应该生成多少数据包)。毕竟攻击者可以修改它们中的任何一个)。

并且这些TCP数据包在通过网络的过程中可以被更多地划分为IP片段(可以通过"不分片"IP标志选择退出-但这个标志可能导致您的数据包根本不交付)。

我认为你的问题不在于将数据包引入流协议,而在于保护它

IPSec在您的场景中可能非常有用,因为它在网络层上运行。

它为发送的每个数据包提供完整性,因此在线上的任何修改都会被检测到,并且丢弃无效的数据包。在TCP的情况下,被丢弃的数据包会自动重传。

(几乎)所有的事情都是由操作系统自动完成的——所以你不需要担心它(并且在这样做时犯错误)。

保密性也可以得到保证(同样的好处是不用重新发明轮子)。

IPSec应该为你提供一个可靠的传输协议,在这个协议之上你可以使用任何你喜欢的帧格式。

另一种选择是在TCP会话之上使用SSL/TLS,这是不那么健壮的(因为它会在完整性错误时关闭整个连接)。

现在,攻击者只是发送一个额外的数据包,假装它是对话的一部分。它可以只有一个字节长:这完全破坏了我实现的任何同步机制!

阻止这样的注入问题是通过保护流来解决的。创建一个加密流并通过它发送数据包。 当然,加密的流本身也有这个问题;它的信息可能被破坏。但是这些消息有安全的完整性检查。问题被检测到,并且可以断开连接并重新建立连接以重新同步它。

同时,在消息之间可以使用一些固定长度的同步/帧位序列:一些特定的位模式。该模式是否意外地出现在消息中并不重要,因为我们只会在出现问题(接收到损坏的消息)时专门查找该模式,否则我们跳过该序列。如果接收到损坏的消息,那么我们将接收字节,直到看到同步模式,并假设它后面的内容是消息的开始(长度后跟有效负载)。如果失败,我们重复该过程。当我们收到正确的消息时,我们回复对等体,对等体将重新发送我们没有收到的任何信息。

这次攻击的可能性和可行性有多大?

TCP连接由四项标识:源IP和目的IP,源端口号和目的端口号。攻击者必须伪造一个在这四个标识符中与您的流匹配的数据包,并使该数据包通过攻击者和接收机器之间的所有路由器和防火墙。攻击者还必须在TCP序列号方面处于正确的范围内。

基本上,攻击者C几乎不可能对网络上远离C的端点A和B进行攻击。假的源IP在C到达目的地之前就会被拒绝。更有可能是内部工作(包括恶意软件):C接近A和b。

最新更新