SSL/TSL
在双方通信之前,需要商量一个用于对称加密的密钥。我们知道网络通信的信道是不安全的,传输报文对任何人是可见的,密钥的交换肯定不能直接在网络信道中传输。因此,使用非对称加密,对对称加密的密钥进行加密,保护该密钥不在网络信道中被窃听。
⭐这样,通信双方只需要一次非对称加密,交换对称加密的密钥,在之后的信息通信中,使用绝对安全的密钥,对信息进行对称加密,即可保证传输消息的保密性
非对称加密
公钥只能加密,不能解密,私钥解密
甲对乙说,我这里有A型号锁,对应钥匙A,我给你一大箱子A锁(公钥),但是钥匙A(私钥)不给你,以后你给我发消息就用A锁锁在盒子里给我,然后我自己用钥匙A就能打开看。
- 公钥加密,私钥解密。这个目的是为了保证内容传输的安全,因为被公钥加密的内容,其他人是无法解密的,只有持有私钥的人,才能解密出实际的内容;
- 私钥加密,公钥解密。这个目的是为了保证消息不会被冒充,因为私钥是不可泄露的,如果公钥能正常解密出私钥加密的内容,就能证明这个消息是来源于持有私钥身份的人发送的。
对称加密
共享唯一密钥,可以加密也可以解密
甲对乙说,我这有一把锁,以后我们互相传消息,就把消息放盒子里,然后用这个锁锁上再传,这个锁有两把一模一样的钥匙,咱俩一人一把,说完甲把钥匙递给了乙。
证书颁发机构CA(身份验证)
客户端 C 和服务器 S 想要使用 SSL/TLS 通信,由上述 SSL/TLS 通信原理,在进行非对称加密之前,C 需要先知道 S 的公钥,而 S 公钥的唯一获取途径,就是把 S 公钥在网络信道中传输。要注意网络信道通信中有几个前提:
- 任何人都可以捕获通信包
- 通信包的保密性由发送者设计
- 保密算法设计方案默认为公开,而(解密)密钥默认是安全的
因此,假设 S 公钥不做加密,在信道中传输,那么很有可能存在一个攻击者 A,发送给 C 一个诈包(AS的公钥),假装是 S 公钥,其实是诱饵服务器 AS 的公钥。当 C 收获了 AS 的公钥(却以为是 S 的公钥),C 就会使用 AS 公钥对数据进行加密,并在公开信道传输,那么 A 将捕获这些加密包,用 AS 的私钥解密,就截获了 C 本要给 S 发送的内容,而 C 和 S 二人全然不知。
同样的,S 公钥即使做加密,也难以避免这种信任性问题,C 被 AS 拐跑了!
解决:
为了公钥传输的信赖性问题,第三方机构应运而生——证书颁发机构。CA 默认是受信任的第三方。CA 会给各个服务器颁发证书,证书存储在服务器上,并附有 CA 的电子签名。
当客户端(浏览器)向服务器发送 HTTPS 请求时,一定要先获取目标服务器的证书,并根据证书上的信息,检验证书的合法性。一旦客户端检测到证书非法,就会发生错误。
数字签名(防止篡改)
数字签名,是 CA 在给服务器颁发证书时,使用散列+加密的组合技术,在证书上盖个章,以此来提供验伪的功能,防止证书被伪造
文件 -散列-> 摘要 -加密-> 签名
⭐
三个重要信息:文件、公钥、签名
发送者通过 散列+私钥加密 对文件进行签名,再将文件、公钥、签名发送给客户端
防止文件被篡改?
将签名解密,原文哈希,然后对比两者
防止签名被篡改?
公钥私钥
防止收到攻击者的信息(文件、公钥和签名都是攻击者的)/ 防止公钥被篡改?
只需要证明公钥生成者的身份。CA给签名者生成了一个证书(包含其身份信息和公钥),签名者把该证书发送给客户端验证,客户端就可以通过证书知道公钥的拥有者了
防止证书被篡改?
CA使用自己的私钥对证书进行了签名,放到证书中,每个人的电脑里都安装了根证书(包含了CA及其公钥),这样公钥就保证了签名的安全性,进而保证了证书的安全性!!
- 混合加密的方式实现信息的机密性,解决了窃听的风险。
- 摘要算法的方式来实现完整性,它能够为数据生成独一无二的「指纹」,指纹用于校验数据的完整性,解决了篡改的风险。
- 将服务器公钥放入到数字证书中,解决了冒充的风险。
TCP
三次握手
A:喂,听得到我吗?
B:我听得到你,你听得到我吗?
A:我也听得到你
为什么要三次握手?
- 三次握手才可以 阻止重复历史连接的初始化(主要原因)
客户端发送的旧 SYN
报文在网络中阻塞了,并且客户端宕机,重新发送新的SYN报文(序列号不同):
在两次握手的情况下,服务端在收到客户端的旧SYN报文之后就进入ESTABLISHD状态,没有中间状态给客户端来阻止历史连接,导致服务端可能建立一个历史连接,造成资源浪费。
而三次握手的情况下,服务端在收到客户端的旧SYN报文之后进入SYN_RECV状态,并返回ACK报文,客户端发现跟自己的期望确认号不同,就会返回RST报文给服务端来终止本次连接,从而阻止了历史连接的初始化。
- 三次握手才可以 同步双方的初始序列号
初始序列号的作用:按序接收、防止重复接收
四次握手其实也能够可靠的同步双方的初始化序号,但由于 第二步和第三步可以优化成一步,所以就成了「三次握手」。
两次握手只保证了 一方的初始序列号能被对方成功接收,没办法保证双方的初始序列号都能被确认接收。
- 三次握手才可以 避免资源浪费
如果客户端发送的 SYN
报文在网络中阻塞了,重复发多次 SYN
报文(序列号相同),那么服务端在收到请求后就会建立多个冗余的无效链接,造成不必要的资源浪费
第一二三次握手丢失会发生什么
四次挥手
A:我说完了,你说完就挂电话吧!
B:好嘞…
B:……
B:我也说完了,可以挂电话了
A:好嘞,拜拜
为什么要四次挥手?
第一二三四次挥手丢失会发生什么?
为什么最后要等待2MSL才进入CLOSE状态?/ 需要 TIME-WAIT 状态?
- 防止历史连接中的数据,被后面新建立的相同四元组的连接错误的接收;
2MSL
时长,足以让两个方向上的数据包都被丢弃,使得原来连接的数据包在网络中都自然消失,再出现的数据包一定都是新建立连接所产生的。比如如果被动关闭方没有收到断开连接的最后的 ACK 报文,就会触发超时重发 Fin报文,另一方接收到 FIN 后,会重发 ACK 给被动关闭方, 一来一去正好 2 个MSL。
- 保证「被动关闭连接」的一方,能被正确的关闭;
第四次挥手时,客户端发送给服务器的 ACK 有可能丢失,如果服务端因为某些原因而没有收到 ACK 的话,服务端就会重发 FIN,如果客户端没有等待而是直接释放,那么就永远接收不到FIN,服务端也永远接收不到ACK,就无法释放
为什么三次握手不用?
三次握手超时重传syn,不会断开连接
Socket连接
socket()
函数,创建Socket
bind()
函数,给 Socket 绑定一个 IP 地址和端口
listen()
函数,进行监听,可以通过netstat
命令查看对应的端口号是否有被监听
accept()
函数,来从内核获取客户端的连接,如果没有客户端连接,则会阻塞等待客户端连接的到来
connect()
函数,发起连接
TCP 是如何保证可靠性的
连接管理,序列号/确认应答,重传,流量控制,拥塞控制
重传
超时重传、快速重传、SACK重传
滑动窗口
允许发送方连续发送多个数据段而不需要等待确认
流量控制
发送窗口:不可发送 | 可发送 已发送未确认 | 已发送已确认
接收窗口:不可接收 | 可接收 | 已接收
发送窗口会根据接收窗口动态调整,接收窗口会根据接收能力动态调整
拥塞控制
四个算法:
慢启动:TCP连接刚建立时,发送端会以指数增长的速度增加拥塞窗口,避免一开始就发送过多数据导致网络拥塞。
拥塞避免:一旦拥塞窗口达到一定阈值(慢启动阈值),TCP会进入拥塞避免阶段。在拥塞避免阶段,拥塞窗口以线性增长的方式增加
拥塞发生:超时重传 ssthresh->cwnd/2,cwnd->1
快速重传 ssthresh=cwnd/2,cwnd=cwnd/2,进入快恢复算法
快速恢复:快速重传和快速恢复算法一般同时使用,cwnd = ssthresh + 3
① 如果再收到重复的 ACK: cwnd 增加 1;
② 如果收到新数据的 ACK: cwnd = ssthresh,原因是该 ACK 确认了新的数据,说明从 duplicated ACK 时的数据都已收到,该恢复过程已经结束,可以回到恢复之前的状态了,也即再次进入拥塞避免状态;
NAT
如果一个组织内部新建了局域网,此IP地址只能用于局域网内的通信,不能直接连到互联网上,此类IP就是私有IP。
不同局域网内的私有IP地址可以重复
NAT 可以把 私有IP地址(局域网LAN)转换成公有IP地址,这样,在广域网WAN中,就只需要一个统一的 IP 地址来标识该 LAN 在整个 Internet 上的位置,而连接到该LAN的主机使用私有IP地址而不需要公共IP地址
NAT 不光可以缓解 IPv4 地址资源短缺的问题,还可以隐藏内部网络的实际拓扑结构,使得外部网络无法直接访问内部网络中的设备,从而提高了内部网络的安全性。
ARP
解决了在局域网中将IP地址映射到MAC地址的问题
IP地址是逻辑地址,用于网络层,MAC地址是物理地址,用于数据链路层
HTTP
1.1
简单、灵活、广泛、长连接、管道传输
无状态、明文传输、头部无压缩、头部冗长、队头阻塞、请求应答
2.0
头部压缩(消除重复头)、二进制数据、并发传输(解决了应用层的队头阻塞,没有解决tcp层的)、服务器推送
基于Stream发送的,消息分割成一个或多个帧在流里面传输,每个stream都有一个ID标识,接收端会根据ID将接收到的帧有序重组成消息,因此不同的请求响应消息就可以在不同的stream中并发传输,并且多个流共用一条TCP连接
- 流(Stream): 已经建立TCP连接上的双向字节流,可以承载一个或多个消息
- 消息(Message): 一个完整的HTTP请求或响应,由一个或多个帧组成。特定消息的帧在同一个流上发送,这意味着一个HTTP请求或响应只能在一个流上发送
- 每一个帧可看做是一个学生,流可以认为是组(流标识符为帧的属性值),一个班级(一个连接)内学生被分为若干个小组,每一个小组分配不同的具体任务(请求/响应消息)。
- HTTP/1.* 一次请求-响应,建立一个连接,用完关闭;每一个小组任务都需要建立一个班级,多个小组任务多个班级,1:1比例 ⚪ 一 o ⚪ 一 o ⚪一 o
- HTTP/1.1 Pipeling解决方式为,若干个小组任务排队串行化单线程处理,后面小组任务等待前面小组任务完成才能获得执行机会,一旦有任务处理超时等,后续任务只能被阻塞,毫无办法,也就是人们常说的线头阻塞 ⚪一 o o o
- HTTP/2 多个小组任务可同时并行(严格意义上是并发)在班级内执行。一旦某个小组任务耗时严重,但不会影响到其它小组任务正常执行 ⚪三 o o o
3.0
QUIC、无队头阻塞(当某个流发生丢包时,只会阻塞这个流,其他流不会受到影响)、1/0 RTT连接建立时间(QUIC 内部包含了 TLS)、连接迁移(使用连接ID标记连接的两端,IP地址改变,可以很快复用连接)
IPv4和ipv6区别
1. ipv4协议的地址长度为32位(4字节),ipv6协议有128位(16字节),可以提供更多的地址
ipv4以二进制数表示,ipv6以十六进制表示
ipv4以8位为一组,用.隔开,ipv6以16位为一组,用:隔开
2. ipv6首部为固定长度40字节,去掉了校验和,更加简化,提高传输效率
3. ipv6自动配置地址,ipv4手动或DHCP配置