【发布时间】:2015-08-15 18:34:45
【问题描述】:
我是网络新手,尤其是 TCP(我一直在用 UDP 愚弄一下,但仅此而已)。 我正在开发一个基于在两个端点之间交换消息的简单协议。这些消息需要经过认证,所以我实现了一个加密层来处理这个问题。然而,虽然 UDP 对构成一次可以传输的最小单元的数据包有一个合理的定义,但 TCP 协议(据我的理解)是完全面向流的。
现在,这让我有点困惑。交换消息时,我如何知道一个从哪里开始,另一个在哪里结束?原则上,我显然可以传达固定长度的消息,或者首先在某个标头中传达每条消息的大小。然而,这可能会受到攻击:虽然不可能扭曲或确定通信的内容,但上述技术只需在中间添加一个字节就可以很容易地完全破坏我的通信。
假设我需要传输一条 1234567 字节长的消息。首先,我用一个表示消息大小的整数传递 4 个字节。好的。然后我开始发送实际消息。该消息被分成几个数据包,分别接收。现在,攻击者只是发送一个额外的数据包,假装它是对话的一部分。它可以只有一个字节长:这完全破坏了我实现的任何同步机制!消息中间有一个虚假字节,它没有成功解码。不仅如此,第一条消息的最后一个字节破坏了第二条消息的对齐方式,依此类推:连接被破坏,而且攻击很简单!无论如何,这种攻击的可能性和可行性有多大?
所以我想知道:一次可以传输的最大数据单元是多少?我知道发送调用与接收调用不对应:消息可以分成不同的块。如何以某种方式将数据包组合在一起,以便我知道它们被打包在一起?有没有办法定义一个更高级别的消息,该消息被重新构建和对齐并触发对类似接收函数的单个调用?如果没有,我还能找到哪些其他解决方案来让我的通信即使在攻击者面前也能重新对齐?
【问题讨论】:
-
ietf.org/rfc/rfc2385.txt 与您描述的内容非常相关。 (并且一些操作系统支持 TCP-MD5 签名,通常通过调用 setsockopt() 来启用)
-
1) TCP 有序列号;你不能注入几个字节到流中而不会使通信混乱。 2)没有消息边界;您必须在应用程序级协议中实现自己的边界,或者通过使用固定长度的消息,或者通过在 messages 前加上标头(期望什么)或通过 messages 来分隔它们i>消息结束字符,例如
\n。 -
@wildplasser 实际上,您可能可以将几个字节注入流中,因为活跃的 MITM 攻击者也可以修改 SEQ/ACK。对于某些网络堆栈,由于它们对out-of-band data 的(错误)处理,它甚至更容易。