TCP 粘包/拆包 问题
问题定义:
TCP 是一个面向字节流的协议,并不理解上层发来的完整的数据包(注意,不是数据报,数据报一般特指无连接服务的信息载体),而是会根据 TCP 缓冲区的实际情况进行包的划分,所以体现出来的业务影响就是,一个完整的数据包可能被划分为多个 TCP Segment,而多个完整的数据包也可能会被合并为一个大的 TCP Segment,这就是 TCP 拆包/粘包问题
问题影响:
这个问题对于发送端没有影响,主要是接收端:接收端从 TCP 中一次读取的字节数是不确定的,所以如果客户端连续发送了两个数据包:D1,D2,接收端至少可能存在 3 种情况:
- 两次读取分别读到 D1 和 D2,理想情况
- 一次读取,读到了 D1 和 D2,发生了粘包
- 两次读取,第一次读取到了 D1-part1,第二次读取到了 D1-part2 和 D2,发生了拆包和粘包
如果流控严格,滑动窗口很小,那么收发次数会更多,粘包/拆包的情况会更多。
问题原因
拆包产生的原因发生在三个层面:
- 待发送的数据大于 Socket 缓冲区的大小
进程缓冲区的数据会进行切分,部分进入内核 Socket 缓冲区,导致数据包被拆分 - 待发送的数据大于 MSS (Maxium Segement Size,最大报文段大小)
TCP 发送的数据包会按 MSS 进行拆分,避免 IP 分片 - 链路层的帧大小大于 MTU,在 IP 层做了 IP 分片,导致数据包被拆分
一般来说,MSS = MTU + TCP header + IP header,但是因为物理传输线路的复杂性,各部分的 MTU 并不一样,而 MSS 是唯一的,所以并不一定能保证不分片。
粘包可能发生在发送端,也可能发生在接收端:
- 待发送的数据包太小,TCP 或 IP 层进行了缓冲整合再发送: Nagle 算法
- 处理端读缓冲不及时,导致数据包粘包
解决思路
大方向上,底层协议是不可能也不应该理解上层业务的,所以无法保证不做拆分和重组,解决只能放在上层做,也就是应用层。一些常用的手段包括:
- 消息定长。对于不够长度的,需对齐。
- 在包尾增加定界符进行分割,比如回车,FTP 协议是这样做的。
- 设计应用层协议,比如 HTTP,引入 header 和 payload。
HTTPS
为什么要用 HTTPS
HTTPS 主要是为了解决中间人攻击的问题:客户端的 HTTP 被劫持,数据并不是直接在客户端和服务端之间传输,而是经过了中间人进行转发。
防止中间人攻击的办法,最直观的是加密,如果密钥只有客户端和服务端拥有,则中间人无法监听、伪造。但在互联网上分发和保存密钥本身就是不安全的。
HTTPS 是怎么做的
HTTPS 的本质仍是加密,但是解决了密钥分发的问题。简单来说:基于 CA 证书机制的非对称加密,完成对称加密的密钥的协商,从而实现密钥的动态生成,无需静态存储在客户端与服务端。
- 什么是非对称加密,对称加密
加密的依据是一个数学上很难的问题,比如 NP 问题,要求没有多项式时间复杂度的算法,从而不能破解(概率上)。对称加密很好理解,用一个密钥,然后对数据进行加密,然后用同样的密钥进行解密,比如 AES。非对称加密需要两个密钥,一个公钥,一个私钥,用公钥加密,私钥解密,如 RSA。
非对称加密算法复杂,安全性高,但是加解密效率没有对称加密高。 - 什么叫 CA 证书
证书也就是数字证书,是 public key certificate (公钥验证体系) 的一环,主要是表明一个公钥是合法的。证书内容一般包括公钥,证书拥有者信息,证书签发机构信息等。CA 是 Certificate Authority 的缩写,是数字证书的第三方签发机构,它需要对其签发的数字证书和持有者进行背书。CA 证书就是 CA 签发的数字证书,不同意普通证书,普通证书谁都可以制作。 - 为什么 HTTPS 需要 CA 证书
假设证书不是由 CA 颁发,那么一个带恶意的中间人攻击流程,如下图所示:
中间人攻击
客户端并不知道自己已经被劫持,他使用的是中间人的证书进行非对称加密;而中间人对于服务端来说,完全就是一个普普通通的客户端,用的是服务端的证书,服务端也不知道自己已经被劫持。
需要理解的是,非对称加密并不能防止中间人攻击,阿克琉斯之踵在于公钥的可伪造性上。所以为了防止中间人攻击,必须通过 CA 证书来保证非对称加密这个环节是不可伪造的。
但是一般,比如 Chrome 在验证到证书不合法,可能是过期了的时候,只是告警,但是并不阻拦用户继续访问。 - CA 证书为什么是可信的
这一点由 CA 机构保证,是 Trust Base 的一部分,可以理解为 CA 证书出了问题导致的事故 CA 机构要赔钱。CA 签发的证书,都可以通过验证链查找到对应的根证书,根证书保存在操作系统里,是具有权威性的,利用本地根证书可以验证 CA 签发证书是否是伪造的。
当一个根证书被安装的时候,比如 WireShark 抓包,会提示你是否信任,你信任了就是你的事了,所以不要乱安装证书。 - HTTPS 一定安全吗
不一定,HTTPS 只解决了中间人攻击的问题,对于非中间人攻击,比如安装了非权威的根证书,然后中间人通过这个根证书签发了一个证书,这也是抓包软件抓取 HTTPS 的原理,还是会被劫持。另外,非对称加密的私钥存储,对称加密的密钥的存储,都可能导致问题,但这不属于 HTTPS 考虑的传输安全范畴。
HTTPS 的工作流程
详细流程需要看协议,比如交换加密算法发生在哪里,等等。推荐阅读 https://www.cnblogs.com/makelu/p/11140824.html
https://segmentfault.com/a/1190000018992153
https://www.jianshu.com/p/6c46ef63c407
更详细一点的图
网友评论