OSI模型
- 物理层:
解决两个硬件之间怎么通信的问题,常见的物理媒介有光纤、电缆、中继器等。它主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。
它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后在转化为1、0,也就是我们常说的数模转换与模数转换)。这一层的数据叫做比特。
- 数据链路层:
在计算机网络中由于各种干扰的存在,物理链路是不可靠的。该层的主要功能就是:通过各种控制协议,将有差错的物理信道变为无差错的、能可靠传输数据帧的数据链路。
它的具体工作是接收来自物理层的位流形式的数据,并封装成帧,传送到上一层;同样,也将来自上层的数据帧,拆装为位流形式的数据转发到物理层。这一层的数据叫做帧。
- 网络层:
计算机网络中如果有多台计算机,怎么找到要发的那台?如果中间有多个节点,怎么选择路径?这就是路由要做的事。
该层的主要任务就是:通过路由选择算法,为报文(该层的数据单位,由上一层数据打包而来)通过通信子网选择最适当的路径。这一层定义的是IP地址,通过IP地址寻址,所以产生了IP协议。
- 传输层:
当发送大量数据时,很可能会出现丢包的情况,另一台电脑要告诉是否完整接收到全部的包。如果缺了,就告诉丢了哪些包,然后再发一次,直至全部接收为止。
简单来说,传输层的主要功能就是:监控数据传输服务的质量,保证报文的正确传输。
- 会话层:
虽然已经可以实现给正确的计算机,发送正确的封装过后的信息了。但我们总不可能每次都要调用传输层协议去打包,然后再调用IP协议去找路由,所以我们要建立一个自动收发包,自动寻址的功能。于是会话层出现了:它的作用就是建立和管理应用程序之间的通信。
- 表示层:
表示层负责数据格式的转换,将应用处理的信息转换为适合网络传输的格式,或者将来自下一层的数据转换为上层能处理的格式。
- 应用层:
应用层是计算机用户,以及各种应用程序和网络之间的接口,其功能是直接向用户提供服务,完成用户希望在网络上完成的各种工作。前端同学对应用层肯定是最熟悉的。
TLS和SSL的区别
最新版本的TLS(Transport Layer Security,传输层安全协议)是IETF(Internet Engineering Task Force,Internet工程任务组)制定的一种新的协议,它建立在SSL 3.0协议规范之上,是SSL 3.0的后续版本。在TLS与SSL3.0之间存在着显著的差别,主要是它们所支持的加密算法不同,所以TLS与SSL3.0不能互操作。
TLS/SSL 的功能实现主要依赖于三类基本算法:
- 非对称加密: 利用非对称加密实现身份认证和密钥协商
- 对称加密: 对称加密算法采用协商的密钥对数据加密
- 散列函数 Hash(常见的有 MD5、SHA1、SHA256): 基于散列函数验证信息的完整性。
防止中间人攻击,所以使用证书颁发机构颁发的证书进行通讯
TLS/SSL 握手过程
1. client_hello
客户端发起请求,以明文传输请求信息,包含版本信息,加密套件候选列表,压缩算法候选列表,随机数,扩展字段等信息,相关信息如下:
(1) 支持的最高TSL协议版本version,从低到高依次 SSLv2,SSLv3,TLSv1,TLSv1.1,TLSv1.2,TLSv1.3。
(2) 客户端支持的加密套件 cipher suites 列表, 每个加密套件对应前面 TLS 原理中的四个功能的组合:认证算法 Au (身份验证)、密钥交换算法 Key Exchange(密钥协商)、对称加密算法 Enc (信息加密)和信息摘要 Mac(完整性校验)。
(3) 支持的压缩算法 compression methods 列表,用于后续的信息压缩传输。
(4) 随机数 random_C,用于后续的密钥的生成。
(5) 扩展字段 extensions,支持协议与算法的相关参数以及其它辅助信息等,常见的 SNI 就属于扩展字段,后续单独讨论该字段作用。
2. server_hello + server_certificate + sever_hello_done
(1) server_hello, 服务端返回协商的信息结果,包括选择使用的协议版本 version,选择的加密套件 cipher suite,选择的压缩算法 compression method、随机数 random_S 等,其中随机数用于后续的密钥协商。
(2) server_certificates,服务器端配置对应的证书链,用于身份验证与密钥交换。
(3) server_hello_done,通知客户端 server_hello 信息发送结束。
3. 证书校验
客户端验证证书的合法性,如果验证通过才会进行后续通信,否则根据错误情况不同做出提示和操作,合法性验证包括如下:
(1) 证书链的可信性 trusted certificate path。
(2) 证书是否吊销 revocation,有两类方式离线 CRL 与在线 OCSP,不同的客户端行为会不同。
(3) 有效期 expiry date,证书是否在有效时间范围。
(4) 域名 domain,核查证书域名是否与当前的访问域名匹配,匹配规则后续分析。
4. client_key_exchange + change_cipher_spec + encrypted_handshake_message
(1) client_key_exchange,合法性验证通过之后,客户端计算产生随机数字 Pre-master,并用证书公钥加密,发送给服务器。
(2) 此时客户端已经获取全部的计算协商密钥需要的信息:两个明文随机数 random_C 和 random_S 与自己计算产生的 Pre-master,计算得到协商密钥: enc_key = Function(random_C, random_S, Pre-Master); 。
(3) change_cipher_spec,客户端通知服务器后续的通信都采用协商的通信密钥和加密算法进行加密通信。
(4) encrypted_handshake_message,结合之前所有通信参数的 hash 值与其它相关信息生成一段数据,采用协商密钥 session secret 与算法进行加密,然后发送给服务器用于数据与握手验证。
5. change_cipher_spec + encrypted_handshake_message
(1) 服务器用私钥解密加密的 Pre-master 数据,基于之前交换的两个明文随机数 random_C 和 random_S,计算得到协商密钥:enc_key = Function(random_C, random_S, Pre-Master); 。
(2) 计算之前所有接收信息的 hash 值,然后解密客户端发送的 encrypted_handshake_message,验证数据和密钥正确性。
(3) change_cipher_spec, 验证通过之后,服务器同样发送 change_cipher_spec 以告知客户端后续的通信都采用协商的密钥与算法进行加密通信。
(4) encrypted_handshake_message, 服务器也结合所有当前的通信参数信息生成一段数据并采用协商密钥 session secret 与算法加密并发送到客户端。(将随机密码加密的数据响应给客户端)
6. 握手结束
客户端计算所有接收信息的 hash 值,并采用协商密钥解密 encrypted_handshake_message,验证服务器发送的数据和密钥,验证通过则握手完成。
7. 加密通信
开始使用协商密钥与算法进行加密通信。注意:
(1) 服务器也可以要求验证客户端,即双向认证,可以在过程 2 要发送 client_certificate_request 信息,客户端在过程 4 中先发送 client_certificate 与 certificate_verify_message 信息,证书的验证方式基本相同,certificate_verify_message 是采用 client 的私钥加密的一段基于已经协商的通信信息得到数据,服务器可以采用对应的公钥解密并验证。
(2) 根据使用的密钥交换算法的不同,如 ECC 等,协商细节略有不同,总体相似。
(3) sever key exchange 的作用是 server certificate 没有携带足够的信息时,发送给客户端以计算 pre-master,如基于 DH 的证书,公钥不被证书中包含,需要单独发送。
(4) change cipher spec 实际可用于通知对端改版当前使用的加密通信方式,当前没有深入解析。
(5) alter message 用于指明在握手或通信过程中的状态改变或错误信息,一般告警信息触发条件是连接关闭,收到不合法的信息,信息解密失败,用户取消操作等,收到告警信息之后,通信会被断开或者由接收方决定是否断开连接。
签名过程
发送报文时,发送方用一个哈希函数从报文文本中生成报文摘要,然后用发送方的私钥对这个摘要进行加密,这个加密后的摘要将作为报文的数字签名和报文一起发送给接收方。接收方首先用与发送方一样的哈希函数从接收到的原始报文中计算出报文摘要,接着再用公钥来对报文附加的数字签名进行解密,如果这两个摘要相同、那么接收方就能确认该报文是发送方的。
数字签名有两种功效:一是能确定消息确实是由发送方签名并发出来的,因为别人假冒不了发送方的签名。二是数字签名能确定消息的完整性。因为数字签名的特点是它代表了文件的特征,文件如果发生改变,数字摘要的值也将发生变化。不同的文件将得到不同的数字摘要。 一次数字签名涉及到一个哈希函数、接收者的公钥、发送方的私钥。
DES是一种将64bit明文加密成64bit密文的对称密码算法,密钥长度是56bit
AES的密钥长度有128、192、256bit三种
单向散列函数的应用(消息摘要) –
防止数据被篡改
确认消息的完整性
CA的公钥会内置到操作系统或浏览器中
使用系统的验证方式对信任对象进行验证,会根据Trust Object的验证策略,一级一级往上,验证证书链上每一级数字签名的有效性,从而评估证书的有效性
使用内置在项目中的CA证书验证服务器证书是否有问题
TCP
TCP的序号和确认号
32位序号 seq:Sequence number 缩写seq ,TCP通信过程中某一个传输方向上的字节流的每个字节的序号,通过这个来确认发送的数据有序,比如现在序列号为1000,发送了1000,下一个序列号就是2000。 32位确认号 ack:Acknowledge number 缩写ack,TCP对上一次seq序号做出的确认号,用来响应TCP报文段,给收到的TCP报文段的序号seq加1
TCP的标志位 每个TCP段都有一个目的,这是借助于TCP标志位选项来确定的,允许发送方或接收方指定哪些标志应该被使用,以便段被另一端正确处理。 用的最广泛的标志是 SYN,ACK 和 FIN,用于建立连接,确认成功的段传输,最后终止连接。
SYN:简写为
S
,同步标志位,用于建立会话连接,同步序列号;ACK: 简写为
.
,确认标志位,对已接收的数据包进行确认;FIN: 简写为
F
,完成标志位,表示我已经没有数据要发送了,即将关闭连接;PSH:简写为
P
,推送标志位,表示该数据包被对方接收后应立即交给上层应用,而不在缓冲区排队;RST:简写为
R
,重置标志位,用于连接复位、拒绝错误和非法的数据包;URG:简写为
U
,紧急标志位,表示数据包的紧急指针域有效,用来保证连接不被阻断,并督促中间设备尽快处理;
三次握手
三次握手(Three-way Handshake),是指建立一个 TCP 连接时,需要客户端和服务器总共发送3个报文。
三次握手的目的是连接服务器指定端口,建立 TCP 连接,并同步连接双方的序列号和确认号,交换 TCP 窗口大小信息。在 socket 编程中,客户端执行 connect() 时。将触发三次握手。
第一次握手: 客户端将TCP报文标志位SYN置为1,随机产生一个序号值seq=J,保存在TCP首部的序列号(Sequence Number)字段里,指明客户端打算连接的服务器的端口,并将该数据包发送给服务器端,发送完毕后,客户端进入
SYN_SENT
状态,等待服务器端确认。第二次握手: 服务器端收到数据包后由标志位SYN=1知道客户端请求建立连接,服务器端将TCP报文标志位SYN和ACK都置为1,ack=J+1,随机产生一个序号值seq=K,并将该数据包发送给客户端以确认连接请求,服务器端进入
SYN_RCVD
状态。第三次握手: 客户端收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给服务器端,服务器端检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,客户端和服务器端进入
ESTABLISHED
状态,完成三次握手,随后客户端与服务器端之间可以开始传输数据了。
注意
小写的ack代表的是头部的确认号Acknowledge number, 缩写ack,是对上一个包的序号进行确认的号,ack=seq+1。
大写的ACK,则是我们上面说的TCP首部的标志位,用于标志的TCP包是否对上一个包进行了确认操作,如果确认了,则把ACK标志位设置成1。
四次挥手关闭连接
四次挥手即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发。 由于TCP连接是全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭
第一次挥手: Client端发起挥手请求,向Server端发送标志位是FIN报文段,设置序列号seq,此时,Client端进入
FIN_WAIT_1
状态,这表示Client端没有数据要发送给Server端了。第二次分手:Server端收到了Client端发送的FIN报文段,向Client端返回一个标志位是ACK的报文段,ack设为seq加1,Client端进入
FIN_WAIT_2
状态,Server端告诉Client端,我确认并同意你的关闭请求。第三次分手: Server端向Client端发送标志位是FIN的报文段,请求关闭连接,同时Client端进入
LAST_ACK
状态。第四次分手 : Client端收到Server端发送的FIN报文段,向Server端发送标志位是ACK的报文段,然后Client端进入
TIME_WAIT
状态。Server端收到Client端的ACK报文段以后,就关闭连接。此时,Client端等待2MSL的时间后依然没有收到回复,则证明Server端已正常关闭,那好,Client端也可以关闭连接了。