TCP Fast Open定义
TCP Fast Open(TFO)是用来加速连续TCP连接的数据交互的TCP协议扩展,原理如下:在TCP三次握手的过程中,当用户首次访问Server时,发送SYN包,Server根据用户IP生成Cookie(已加密),并与SYN-ACK一同发回Client;当Client随后重连时,在SYN包携带TCP Cookie;如果Server校验合法,则在用户回复ACK前就可以直接发送数据;否则按照正常三次握手进行。
起源
由Google于2011年的论文(http://conferences.sigcomm.org/co-next/2011/papers/1569470463.pdf)中提出,IPV4的TFO已经合入Linux Kernel Mainline,Client内核版本为3.6;Server内核版本为3.7。
Google研究发现TCP三次握手是页面延迟时间的重要组成部分,所以他们提出了TFO:在TCP握手期间交换数据,这样可以减少一次RTT。根据测试数据,TFO可以减少15%的HTTP传输延迟,全页面的下载时间平均节省10%,最高可达40%。
目前互联网上页面平均大小为300KB,单个object平均大小及中值大小分别为7.3KB及2.4KB。所以在这种情况下,多一次RTT无疑会造成很大延迟。
2011年6月,对Google webServer进行连续7天数十亿次针对80端口的请求分析,包括搜索、Gmail、图片等多个服务。其中cold requests为:新连接上的请求;warm requests为已有连接上的请求;All requests为所有连接上的请求(cold requests + warm requests)。cold requests及all requests中TCP握手时间在整个延迟时间中的占比如图 1 所示
图 1 Cold Req及All Req的三次握手在整个连接生命周期的时间百分比
分析结果显示,在cold requests中,TCP握手时间占延迟时间的8%-28%;即使统计所有的请求,TCP握手时间也占到了延迟时间的5%-7%。
谷歌对谷歌浏览器的进行了28天的连续数据分析(通过了用户授权):数据不仅仅是针对谷歌服务,也涉及到所有网站的请求。通过对上十亿条记录的分析,发现即使使用了Http1.1的keep-alive功能,依然有33%的请求是在新连接上发起的。可能原因:为了加快下载速度,新建数10个连接;主机和NAT也会主动断开闲置的keep-alive连接;为了省电,手机浏览器关闭闲置的连接。
为了理解TCP的三次握手对整个连接交互的影响,将分析数据进行绘图,如图 2所示
图 2 Http请求延时的累积分布函数图(CDF)
其中,X轴为网络交互延时(单位为s), Y轴为以百分比表示的HTTP请求的累积分布;All Req为三次握手在所有请求中的时间占比; Cold Req为新连接上的三次握手的时间占比; Cold Req no Hsk代表去除了三次握手时间的Cold Req的时间占比。
Cold Req基本比All Req慢50%(DNS查找、慢启动、SSL握手、TCP握手导致),而TCP握手时间在Cold Req延迟时间中往往占比了25%。
因此,Google设计了TCP Fast Open.
详解
TCP Fast Open流程图如图 3所示
图 3 TCP Fast Open 流程图
如图 3所示,TFO的的流程如下:
- 用户向Server发送SYN包并请求TFO Cookie;
- Server根据用户的IP加密生成Cookie,随SYN-ACK发给用户
- 用户储存TFO Cookie
当连接断掉,重连后的流程如下:
- 用户向Server发送SYN包(携带TCP Cookie),同时附带请求;
- Server校验Cookie(解密Cookie以及比对IP地址或者重新加密IP地址以和接收到的Cookie进行对比)。
如果验证成功,向用户发送SYN+ACK,在用户回复ACK之前,便可以向用户传输数据;
如果验证失败,则丢弃此TFO请求携带的数据,回复SYN-ACK确认SYN Seq,完成正常的三次握手。
如果Cookie在网络传输的过程中被丢弃,Client在RTO后,发起普通的TCP连接,流程如图 4所示
图 4 Cookie被网络丢弃
3. 如果在SYN包中的数据被接受,那么Server可以在收到Client的ACK之前回复该请求的响应报文
4. ClientACKServer的SYN。如果Client的数据没有得到Server的ACK,那么Client会通过ACK重传该请求。
5. 随后的操作和普通的TCP连接一致
建立了TFO连接而又没有完成TCP连接的请求在Server端被称为pending TFO connection,当pending的连接超过上限值,Server会关闭TFO,后续的请求会按正常的三次握手处理。
如果一个带有TFO的SYN请求如果在一段时间内没有收到回应,用户会重新发送一个标准的SYN请求,不带任何其他数据。
Cookie是用来验证Client的IP所有权的加密字符串。Server负责产生及验证Cookie。Client缓存Cookie以及在随后的连接初始化阶段将Cookie返回给Server。
Server通过加密Client的源IP产生16字节长度的Cookie(通过AES-128算法)。加密和解密Cookie很快,可以和正常的SYN及SYN-ACK包的处理时间差不多。
为了确保安全及用户IP会变(如DHCP),Cookie值会隔一段时间变化一次。
Cookie结构如图 5 所示
图5 Cookie结构
如图 5所示,如果没有Cookie或者Cookie值为空,则表明是Client向Server请求Cookie;如果Cookie有值,表明是Server向Client发送Cookie或者Client通过TFO执行Fast Opem.
通过Wireshark抓包可以看TFO流程,如图6所示:
图6 Wireshark抓包与TFO
Fast Open Cookie选项在TCP Options中,从No.7包中可以看到,Fast Open Cookie的Kind为34, 长度为10,Cookie为0x1a39d8e2100b247e。
- 首先Client发起TCP连接(端口为57520),在SYN包中带有一个FOC选项,向Server请求Cookie(No.1号报文)
- Server端回复SYN-ACK包,其中携带一个FOC选项,Cookie域为0x1a39d8e2100b247e(No.7号报文)
- Client发送一个"hello"消息后关闭连接(No.5号报文),Server端也断开连接(No.6号报文)
- Client通过57522端口向Server发起TFO的SYN,携带Cookie及数据(No.7号报文)
- Server回复SYN-ACK(No.9号报文)
- Client回复ACK(No.10报文)
在Linux支持TFO的内核版本下(Client内核版本为3.6;Server内核版本为3.7),在sysctl.config(vim /etc/sysctl.conf)中添加:
net.ipv4.tcp_fastopen = 3
其中1表示客户端开启,2表示服务端开启,3表示客户端和服务器同时开启
Server主要代码:
-
sfd = socket(AF_INET, SOCK_STREAM, 0); // Create socket
-
bind(sfd, ...); // Bind to well known address
-
int qlen = 5; // Value to be chosen by application
-
setsockopt(sfd, SOL_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen));
-
listen(sfd, ...); // Mark socket to receive connections
-
cfd = accept(sfd, NULL, 0); // Accept connection on new socket
-
// read and write data on connected socket cfd
-
close(cfd);
注意:Server需要设置TCP_FASTOPEN属性
Client主要代码
-
sfd = socket(AF_INET, SOCK_STREAM, 0);
-
sendto(sfd, data, data_len, MSG_FASTOPEN, (struct sockaddr *) &server_addr, addr_len);
-
// Replaces connect() + send()/write()
-
// read and write further data on connected socket sfd
-
close(sfd);
注意:Client不能用connect,只能用sendto及sendmsg
TFO性能
为了验证TFO的性能,Google做了一些实验。
Google对amazon.com、nytimes.com、wsj.com、TCP Wikipedia page等网站进行了使用TPO及不使用TPO进行了测试,设置一系列的RTT时间:20ms、100ms、200ms,记录页面的加载时间,每个页面采集120个数据。
测试结果如图 7 所示,(PLT 为Page load time)
图 7 页面加载时间
如图 7所示,RTT时间越大,TFO的效果越明显。当RTT为200ms时,改善达到了11%-41%。
由于Server产生Cookie时需要加密,验证Cookie时需要解密,Google也测试了TFP开启时,Server的CPU使用率,如图 8所示
图 8 CPU使用率
如图8所示,当开启TFO时,CPU的使用率并不高,在某些区间甚至低于普通的TCP。
安全性
在TFO下,依然存在一些问题,如伪造TFO SYN攻击(通过DHCP及NAT、Moles获取有效的Cookies),这种场景下,Server资源会被攻击耗尽。
图 9显示了TFO的SYN-flood攻击和普通的TCP SYN-flood攻击对比情况
图 9 SYN-Flood攻击对比
结论
- TFO在TCP的第一次握手时就携带请求报文,对于35%的http请求,可节省一个RTT
- Cookie是加密的,一定程度上减少了攻击可能性
参考资料
- https://tools.ietf.org/html/rfc7413
- http://blog.sina.com.cn/s/blog_583f42f101011veh.html
- http://conferences.sigcomm.org/co-next/2011/papers/156947046pdf
- https://en.wikipedia.org/wiki/TCP_Fast_Open#cite_note-2
- https://www.ietf.org/proceedings/80/slides/tcpm-3.pdf
- https://datatracker.ietf.org/doc/rfc7413/?include_text=1
- https://tools.ietf.org/html/rfc7413
- https://lwn.net/Articles/508865/
来源:oschina
链接:https://my.oschina.net/u/4398177/blog/4841593