TCP SYN握手报文可以传输数据吗-CSDN博客

TCP握手期间可以传输数据吗?我不是说第三次握手的ACK是否能携带数据,显而易见是可以的,也是简单的。我是在问,client发往server的第一个SYN报文,以及server回复client的第二个SYN/ACK报文,能携带数据吗?

可以!不过声明,本文的内容与TCP Fast Open无关,说的是原始TCP。亦与安全无关,安全的归安全。

依据如经典RFC793 3.4节所示:

Several examples of connection initiation follow. Although these examples do not show connection synchronization using data-carrying segments, this is perfectly legitimate, so long as the receiving TCP doesn’t deliver the data to the user until it is clear the data is valid (i.e., the data must be buffered at the receiver until the connection reaches the ESTABLISHED state). The three-way handshake reduces the possibility of false connections. It is the implementation of a trade-off between memory and messages to provide information for this checking.

此外,《TCP/IP详解(第二版) 卷1》13.2节有如下Note:
在这里插入图片描述
诸如“TCP为什么要3次握手,2次可以吗?”,“TCP握手的必要性”等,亦参考RFC793 3.4节,两三页胜过大书特书。比如本文不会解释3次握手是为了初始化双向的序列号这种众所周知的事。

没人在SYN报文中携带数据的原因是sockets API不支持这么做,进而TCP协议的实现也就没了支持的必要,以下是Linux TCP处理SYN报文的实现片段:

static void tcp_openreq_init(struct request_sock *req,
                             const struct tcp_options_received *rx_opt,
                             struct sk_buff *skb, const struct sock *sk)
{
        struct inet_request_sock *ireq = inet_rsk(req);
        ...
        tcp_rsk(req)->rcv_isn = TCP_SKB_CB(skb)->seq;
        tcp_rsk(req)->rcv_nxt = TCP_SKB_CB(skb)->seq + 1;
        ...

Linux TCP server处理SYN报文时忽略了携带的数据。但如RFC 793所述,SYN报文是可以“捎带”数据的,为什么不呢?怎么想都是可以的。

也许MSS尚未协商,也许rwin尚未知晓,但依TCP语义,receiver可尽力接收,只需回复正确的ACK指示sender的UNA。

唯一问题在于内存开销。

若syncookie未启用,TCP在握手尚未完结前,需缓存任何收到的数据,待连接ESTABLISH之后方可push至应用层,期间,过多sender假冒过量连接,将很容易使receiver内存溢出,表现攻击特征。

但安全的归安全,TCP的归TCP。

至少可做配置开关,在额外机制保证安全的情形下支持SYN携带数据。2022年,安全早就从TCP协议分离了,指望TCP协议本身保证安全,属实不现实。

若死活不支持SYN携带数据,便减少了很多可能:
在这里插入图片描述
起初是sockets API,导致各TCP实现均不支持SYN携带数据,这反使人们偏见于HTTP,TCP握手带来的额外RTT开销让HTTP协议饱受诟病!最终QUIC宣称的0RTT反而成了一个广而告之的新鲜特征。

握手开销无关HTTP,亦无关TCP协议,而是原生于sockets API约束的TCP实现问题。握手开销竟成TCP污点。

基因决定了死亡方式。TCP有很多致命缺陷,滑动窗口,自时钟都是,但握手开销不是。

关于TCP SYN报文携带Payload的有趣玩法,参见前年写的一篇短文:
https://blog.csdn.net/dog250/article/details/108540823

提到TCP和UDP的性能对比,总有人提到TCP有三次握手开销,说的就好像这三次握手是什么正事儿都没干,平白浪费的一样,这些人也是不懂装懂。如果你要建立一个可靠,保序的UDP连接,比如QUIC,你照样逃避不了握手,只不过这些都在UDP上层做了而已。有人说QUIC的0-RTT,TCP对此完全无力,但事实上并不是。0-RTT并非凭空的,背后依然是一次建立多次使用的理念,实质上还是一种cache,类似TCP的Fast Open,但其实无论是TCP还是Self-Defined-Protocol,都是可以无cache直接传输数据的,都是天然的支持0-RTT。那为什么都不能直接传数据,还是因为“一旦出错,代价太大”,trade-off之后,加入纯握手,减少出错代价(比如避免有意为之的攻击),在此基础上用最最传统的cache思路优化,就有了QUIC 0-RTT,以及TCP Fast Open。牵扯太多,写篇小文。

浙江温州皮鞋湿,下雨进水不会胖。

原文链接: https://blog.csdn.net/dog250/article/details/122995484

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    TCP SYN握手报文可以传输数据吗-CSDN博客

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/405597

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月26日 上午9:18
下一篇 2023年4月26日 上午9:18

相关推荐