tfo以及quic的阅读笔记
Google研究发现TCP三次握手是页面延迟时间的重要组成部分,所以他们提出了TFO:在TCP握手期间交换数据,这样可以减少一次RTT。根据测试数据,TFO可以减少15%的HTTP传输延迟,全页面的下载时间平均节省10%,最高可达40%.论文见:google_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连接
建立了TFO连接而又没有完成TCP连接的请求在Server端被称为pending TFO connection,当pending的连接超过上限值,Server会关闭TFO,后续的请求会按正常的三次握手处理。
如果一个带有TFO的SYN请求如果在一段时间内没有收到回应,用户会重新发送一个标准的SYN请求,不带任何其他数据。
- Cookie
Cookie是用来验证Client的IP所有权的加密字符串。Server负责产生及验证Cookie。Client缓存Cookie以及在随后的连接初始化阶段将Cookie返回给Server。
Server通过加密Client的源IP产生16字节长度的Cookie(通过AES-128算法)。加密和解密Cookie很快,可以和正常的SYN及SYN-ACK包的处理时间差不多。
所以同样有个问题,是不是存在拿到cookie攻击的问题?? 所以Cookie值会隔一段时间变化一次;
但是伪造TFO SYN攻这种场景下,Server资源会被攻击耗尽。通过DHCP及NAT获取有效的Cookies
Conclusion
TCP Fast Open Data exchange in TCP handshake 1 RTT savings on 35% of HTTP requests
Cookie to mitigate security vulnerabilities
- TFO在TCP的第一次握手时就携带请求报文,对于35%的http请求,可节省一个RTT
- Cookie是加密的,一定程度上减少了攻击可能性
Implementation
Linux (private patch) and Chrome
Tested TFO on live Internet connections Worked on Comcast, ATT, etc.
web server application: only setsockopt(TFO)
原始文档:https://www.ietf.org/proceedings/80/slides/tcpm-3.pdf
rfc:https://tools.ietf.org/html/rfc7413
TCP_FASTOPEN 对应的内核代码:
static int do_tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, unsigned int optlen) { ----------------- case TCP_FASTOPEN: if (val >= 0 && ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) { tcp_fastopen_init_key_once(true); fastopen_queue_tune(sk, val); } else { err = -EINVAL; } break; --------------------------- } static inline void fastopen_queue_tune(struct sock *sk, int backlog) { struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue; int somaxconn = READ_ONCE(sock_net(sk)->core.sysctl_somaxconn); queue->fastopenq.max_qlen = min_t(unsigned int, backlog, somaxconn); }
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);
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);
PS:此时不要和syn cookie 搞混淆哦!!
SYN cookies 算法
TCP
连接建立时,双方的起始报文序号是可以任意的。SYN cookies
利用这一点,按照以下规则构造初始序列号:
- 设
t
为一个缓慢增长的时间戳(典型实现是每64s递增一次) - 设
m
为客户端发送的SYN
报文中的MSS
选项值 - 设
s
是连接的元组信息(源IP,目的IP,源端口,目的端口)和t
经过密码学运算后的Hash
值,即s = hash(sip,dip,sport,dport,t)
,s
的结果取低 24 位
则初始序列号n
为:
- 高 5 位为
t mod 32
- 接下来3位为
m
的编码值 - 低 24 位为
s
当客户端收到此SYN+ACK
报文后,根据TCP
标准,它会回复ACK
报文,且报文中ack = n + 1
,那么在服务器收到它时,将ack - 1
就可以拿回当初发送的SYN+ACK
报文中的序号了!服务器巧妙地通过这种方式间接保存了一部分SYN
报文的信息。
接下来,服务器需要对ack - 1
这个序号进行检查:
- 将高 5 位表示的
t
与当前之间比较,看其到达地时间是否能接受。 - 根据
t
和连接元组重新计算s
,看是否和低 24 一致,若不一致,说明这个报文是被伪造的。 - 解码序号中隐藏的
mss
信息
到此,连接就可以顺利建立了。
SYN Cookies 缺点
既然SYN Cookies
可以减小资源分配环节,那为什么没有被纳入TCP
标准呢?原因是SYN Cookies
也是有代价的:
MSS
的编码只有3位,因此最多只能使用 8 种MSS
值-
由于cookie的计算只涉及到包头部分信息,在建立连接的过程中不在服务器端保存任何信息,所以失去了协议的许多功能,比如超时重传、
Wscale
、SACK
- 增加了密码学运算;计算cookie有一定的运算量,增加了连接建立的延迟时间
TCP 首次建立连接的开销为 1-RTT,快速复用/打开连接的开销为 0-RTT,这与TLS 1.3 协议首次完整握手与快速恢复简短握手的开销一致。
所以再看看quic 这个东西: 是不是和TFO一样!!!!
quic三次握手见:quic握手
最后都变成了: 请求一个公钥,公钥加密,私钥解密的类型;类似于SSL/TLS啥的!!!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!