计算机网络知识点总结

概念引入

网络层相关

传输层相关

应用层相关

网络安全相关


简述OSI七层模型

OSI七层网络模型,自底向上描述(最好说明每个层干什么,举例网络协议,都在哪个层)

OSI七层模型、四层模型

  • 物理层: 建立、维护、断开物理连接
  • 数据链路层: 将二进制流 组合成 ; *帧编码*和误差纠正控制
  • 网络层: 提供主机间的逻辑通信;路由选择、路由及逻辑寻址;负责根据网络地址传送数据包;协议:IP, ARP, RARP, ICMP
  • 传输层: 提供应用进程间的逻辑通信。负责将数据*可靠地*传送到相应的*端口*。协议:TCP,UDP
  • 表示层:数据的表示、安全、压缩。
  • 会话层:建立、管理、中止会话。
  • 应用层: 为操作系统或网络应用程序提供访问网络服务的接口。协议:FTP,HTTP,DNS

物理层

建立、维护、断开物理连接

  • 物理接口信号线的规格;包括:形状和尺寸、引线数目和排列、固定和锁定装置等;
  • 传输二进制位流的标准;包括:传输二进制位流时线路上信号电压高低、阻抗匹配情况、传输速率和距离的限制等。

传输数据单位:比特流,二进制流 也就是所谓电流

数据链路层

将二进制流 组合成

数据链路层主要有两个功能 :*帧编码*和*误差纠正控制*。

数据链路层的主要协议有:

  • 帧中继(Frame Relay);
  • 点对点协议(Point-to-Point Protocol);
  • 以太网(Ethernet);
  • 高级数据链路协议(High-Level Data Link Protocol);
  • 异步传输模式(Asynchronous Transfer Mode);

网络层

网络层:实现端端节点到端节点间的通信

功能:路由选择、路由及逻辑寻址

网络层的目的是实现两个端系统之间的数据透明传送,具体功能包括寻址和路由选择、连接的建立、保持和终止等。

协议:

  • IP(IPV4 IPV6)通过IP地址进行路由选择
  • ARP“AddressResolutionProtocol”(地址解析协议)将IP地址转换为MAC地址
  • RARP 逆地址解析
  • ICMP 差错报告和查询

    由于IP协议的两个缺陷:没有差错控制和查询机制,因此产生了ICMP。ICMP主要是为了提高IP数据报成功交付的机会,在IP数据报传输的过程中进行差错报告和查询,比如目的主机或网络不可到达,报文被丢弃,路由阻塞,查询目的网络是否可以到达等等。

传输层

网络层负责根据网络地址传送数据包

传输层负责将数据可靠地传送到相应的端口

传输层的服务一般要经历传输连接建立阶段,数据传送阶段,传输连接释放阶段3个阶段才算完成一个完整的服务过程

在这一层,信息传送的协议数据单元称为*数据段*或*报文*。

传输层提供了主机应用程序进程之间的端到端的服务,基本功能如下:

  • 分割与重组数据 (网络层发送的数据包可能是黏在一起的)
  • 端口号寻址 (我要知道发送给主机的哪个端口)
  • 连接管理 (建立tcp或udp连接)
  • 差错控制和流量控制、纠错 (保证传输质量;拥塞控制)

传输层要向会话层提供通信服务的可靠性,避免报文的出错、丢失、延迟时间紊乱、重复、乱序等差错。

传输层既是OSI层模型中负责数据通信的最高层,并向高层用户屏蔽通信子网的细节。

协议:

  • 传输控制协议TCP(Transmission Control Protocol)
  • 用户数据报协议UDP(User Datagram Protocol)

TCP在不可靠的IP网络层上提供了一个可靠的传输层

会话层

建立、管理、终止会话。(在五层模型里面已经合并到了应用层)

对应主机进程,指本地主机与远程主机正在进行的会话

运输服务质量参数(QOS)等会话的属性在这一层设置(MQTT协议中 0:最多一次,1:最少1次,2:只一次)

表示层

数据的表示、安全、压缩。(在五层模型里面已经合并到了应用层)

格式有,JPEG、ASCll、DECOIC、加密格式等

应用层

网络服务与最终用户的一个接口。

应用层为操作系统或网络应用程序提供访问网络服务的接口。

应用层协议的代表包括:Telnet、FTP、HTTP、DNS(Domain Name System:域名系统)等。

简化后四层模型:物理层,网络层,传输层,应用层

描述从在浏览器地址栏输入URL到浏览器加载,中间发生了什么

  • 用户输入请求地址
  • 根据请求地址获取主机地址HOST, DNS解析返回IP地址
    • 浏览器缓存 -> host -> 路由缓存 -> 本地DNS -> 根域名、顶级、二级、三级…
    • 先查本地缓存,本地缓存没有,依次请求根域名、顶级、二级、三级…DNS服务器,直到找到IP地址
    • 本地域名服务器缓存DNS信息,留着下次用
  • 浏览器拿到IP后,就向服务器发送http连接请求,TCP三次握手
  • 防火墙将外网IP转换到内网IP,此步骤是通过NAT地址转换
  • 请求到达LVS服务
  • LVS反向代理到业务服务器,服务器返回数据,流量从防火墙出去
  • 浏览器接收到请求,进行处理,
    • 解析请求是2XX,正常显示;3XX,进行转发,4XX或5XX,显示错误
  • 断开连接, TCP四次挥手

IP分类

四个级别,分别为A类、B类、C类和D类。分类的依据是IP地址的前四位:

  • A类IP地址是第一位为“0”的地址。A类IP地址的前8位是网络标识,用十进制标识的话0.0.0.0-127.0.0.0是A类IP地址的理论范围。另外我们还可以得知,A类IP地址最多只有128个(实际上是126个,下文不赘述),每个网段内主机上限为2的24次方,也就是16,777,214个。

  • B类IP地址是前两位为“10“的地址。B类IP地址的前16位是网络标识,用十进制标识的话128.0.0.0-191.255.0.0是B类IP地址的范围。B类IP地址的主机标记长度为16位,因此一个网段内可容纳主机地址上限为65534个。

  • C类IP地址是前三位为“110”的地址。C类IP地址的前24位是网络标识,用十进制标识的话192.0.0.0-223.255.255.0是C类IP地址的范围。C类地址的后8位是主机标识,共容纳254个主机地址。

  • D类IP地址是前四位为“1110”的地址。D类IP地址的网络标识长32位,没有主机标识,因此常用于多播。

NAT网络地址转换

NAT英文全称是“Network Address Translation”,中文意思是“网络地址转换”

解决公网地址不足的问题

把内部私有网络地址(IP地址)翻译成合法网络IP地址的技术。

NAT名字很准确,网络地址转换,就是替换IP报文头部的地址信息

网络被分为私网和公网两个部分,NAT网关设置在私网到公网的路由出口位置,双向流量必须都要经过NAT网关

TCP和UDP的区别

| 协议|连接性|双工性|可靠性|有序性|有界性|拥塞控制|传输速度|量级|头部大小| |:–:|:–:|:–:|:–:|:–:|:–:|:–:|:–:|:–:|:–:|:–:| |TCP|面向连接(Connection oriented)|全双工(1:1)|可靠(重传机制)|有序(通过SYN排序)|无边界|有粘包情况|有拥塞控制|传输速度慢|量级低|头部20~60字节| |UDP|无连接(Connection less)|n:m|不可靠(丢包后数据丢失)|无序|有消息边界|无粘包|无拥塞控制|传输速度快|量级高| 头部8字节 |

TCP应用场景:将传输的文件分段传输时需要建立会话可靠传输流量控制;比如:下载一部电影

UDP应用场景:一个数据包就能完成数据通信不分段不建立会话不需要流量控制不可靠传输;比如:DNS域名解析,QQ聊天,讲课时屏幕广播(多播,广播)

TCP与UDP最大的不同是:传输数据的质量

TCP如何保证传输数据的质量?

答:序列号、检验和、ACK确认机制,流量控制,拥塞控制

UDP特点

  • 无连接的
  • 尽最大努力交付,不可靠,不进行拥塞控制
  • 面向报文的,没有拥塞控制,适合多媒体通信的要求
  • 支持一对一,一对多,多对一,多对多通信
  • 首部开销小,只有8个字节

TCP特点

传输控制协议

  • 面向连接的传输层协议
  • 只能是点对点的
  • 提供可靠交付;拥塞控制
  • 提供全双工通信
  • 面向字节流

TCP有哪些手段保证可靠交付

TCP通过拆包、序列号、检验和、确认机制、重发控制、连接管理、流量控制、拥塞控制实现可靠性。

  1. 拆包;应用数据被分割成 TCP 认为最适合发送的数据块。
  2. 序列号;TCP 给发送的每一个包进行编号,接收方对数据包进行排序,把有序数据传送给应用层。
  3. 校验和;TCP 将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP 将丢弃这个报文段和不确认收到此报文段。
  4. 去重:TCP 的接收端会丢弃重复的数据。
  5. 流量控制:TCP 利用可变大小的滑动窗口协议实现流量控制
  6. 拥塞控制:当网络拥塞时,减少数据的发送。
  7. 超时重发机制:当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。

TCP流量控制

TCP 利用可变大小的滑动窗口协议实现流量控制

  • TCP 连接的发送方接收方都有固定大小的缓冲空间
  • TCP的接收端只允许发送端发送接收端缓冲区能接纳的数据
  • 当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失
  • TCP 使用的流量控制协议是可变大小的滑动窗口协议

具体解释滑动窗口协议

发送窗口中有四个概念:

  • 已发送并收到确认的数据(不在发送窗口和发送缓冲区之内)
  • 已发送但未收到确认的数据(位于发送窗口之内)
  • 允许发送但尚未发送的数据(位于发送窗口之内)
  • 发送窗口之外的缓冲区内暂时不允许发送的数据

接收窗口中也有四个概念:

  • 已发送确认并交付主机的数据(不在接收窗口和接收缓冲区之内)
  • 未按序收到的数据(位于接收窗口之内)
  • 允许接收的数据(位于接收窗口之内)
  • 不允许接收的数据(位于发送窗口之内)

滑动窗口协议

接收方通过报文告知发送方还可以发送多少数据,从而保证接收方能够来得及接收数据,防止出现接收方带宽已满,但是发送方还一直发送数据的情况。

TCP拥塞控制

一个门限:慢启动门限 ssthresh

三个窗口:

  • 接收窗口 rwnd (receive window)
  • 发送窗口 swnd(send window)
  • 拥塞窗口 cwnd(congestion window)

出现拥塞时,网络吞吐量会随输入负荷的增大而下降,因此要进行拥塞控制。

TCP拥塞控制算法(TCP congestion control algorithm),主要包括4个步骤:

  1. 慢启动;指数增长
  2. 拥塞避免;线性增长
  3. 拥塞发生;拥塞发生时
  4. 快重传和快恢复;拥塞发生后的恢复过程
    1. 快重传:TCP认为这种情况太糟糕,ssthresh = cwnd /2;cwnd = 1,重新进入慢启动
    2. 快恢复:拥塞没那么糟糕;ssthresh = cwnd /2;cwnd = cwnd / 2,重新进入拥塞避免

TCP拥塞控制算法

慢启动(slow-start)算法原理

开始发送一个报文段,收到确认后拥塞窗口翻倍。然后传输2个报文段,收到2个确认后增加拥塞窗口变成了4个MSS。 这样没经过一个RTT,发送速率就会翻番。于是,TCP发送的起始速率慢,但是在慢启动阶段会以指数增长。

拥塞避免

进入拥塞状态后,TCP的cwnd增加速率就比较缓慢,一个RTT将cwnd的值增加一个MSS,线性增长。

快速恢复

在快速恢复中,对于引起TCP进入快速恢复状态的缺失报文段,对收到的每个冗余的ACK,cwnd的值都增加一个MSS。 最终,当对丢失报文段的一个ACK到达时,TCP在降低cwnd后进入拥塞避免状态。

当TCP通信开始后, 网络吞吐量会逐渐上升; 随着网络发生拥堵, 吞吐量会立刻下降;

拥塞控制, 归根结底是TCP协议想尽可能快的把数据传输给对方, 但是又要避免给网络造成太大压力的折中方案.

三次握手和四次挥手

三次握手

三次握手

  1. 第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入SYN_SENT状态,等待服务器确认
  2. 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECEIVED状态;
  3. 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),客户端进入ESTABLISHED(TCP连接成功)状态,服务端收到客户端发来的ACK后,进入ESTABLISHED状态,完成三次握手。

为什么要三次握手

为了确保双发收发都是正常的

简述tcp连接时的握手过程,不要第三次握手行不行?为什么不能用两次握手进行连接?

  1. 原因1:没有第三次握手,服务端不知道客户端是否成功拿到了自己发送的SYN,即不能确定客户端能收到服务端发送的消息
  2. 原因2:如果使用两次握手,服务端接收客户端SYN后,进入ESTABLISHED状态;假设存在场景,客户端发起第一次连接超时,然后客户端发起第二次连接正常并传送数据断开,此时第一次连接到达服务端,这时服务端以为客户端又要建立第二次连接,进入ESTABLISHED状态,造成资源浪费;

四次挥手

四次挥手

  1. 第一次挥手: 客户端数据发送完成,向服务端发送释放连接的请求。客户端进入FIN_WAIT_1状态。
  2. 第二次挥手:服务端接收到客户端的连接释放请求,会告诉应用层要释放TCP连接。然后发送ACK到客户端,然后进入CLOSE_WAIT状态。此时表明客户端到服务端的连接已经释放,不会接受来自客户端的数据了,但是由于TCP是全双工。所以此时服务端还可以向客户端发送数据。
  3. 第三次挥手:服务端如果在此时数据还没有发送完成,会继续发送,在数据发送完毕之后。服务端会向客户端发送连接释放的请求。然后服务端进入LAST_ACK状态。
  4. 第四次挥手:客户端在接受到服务端的释放请求。会向服务端在发送一个确认请求。此时客户端进入TIME_WAIT状态 该状态会持续 2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃) 时间,若该时间段内没有 服务端的重发请求的话,就进入 CLOSED 状态。当 客户端收到确认应答后,也便进入 CLOSED 状态。

为什么要四次挥手

双方数据发送完毕,都认为可以断开

  • 当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,”你发的FIN报文我收到了”。
  • 只有等到Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

客户端断连怎么处理

如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

传输层和应用层之间的关系

传输层的协议TCP或UDP加上端口就可以标识一个应用层协议

应用层 = 传输层 + 端口

常见应用层协议

  • http = tcp + 80
  • https = tcp + 443
  • RDP = tcp + 3389 # 远程桌面
  • ftp = tcp + 21
  • 共享文件夹 = tcp+445
  • SMTP = tcp + 25 # 发邮件
  • pop3 = tcp + 110 # 收邮件
  • telnet = tcp + 23
  • dns = tcp + 53

简述DNS

DNS(Domain Name System): 域名系统

是*域名解析服务器*组成的服务系统

DNS解析的详细过程

  • 客户机提出域名解析请求,并将该请求发送给本地的域名服务器。
  • 当本地的域名服务器收到请求后,就先查询本地的缓存,如果有该纪录项,则本地的域名服务器就直接把查询的结果返回。
  • 若没有查到,则将请求发给根域 DNS 服务器,并依序从根域查找顶级域,由顶级查找二级域,二级域查找三级,直至找到要解析的地址或名字,即向客户机所在网络的DNS服务器发出应答信息,DNS 服务器收到应答后先在缓存中存储,然后,将解析结果发给客户机。若没有找到,则返回错误信息。
  • 本地域名服务器把返回的结果保存到缓存,以备下一次使用,同时还将结果返回给客户机。

DNS优化原理

  • DNS缓存
  • DNS负载均衡
    • 在DNS服务器中为同一个主机名配置多个IP地址,在应答DNS查询时,DNS服务器对每个查询将以DNS文件中主机记录的IP地址按顺序返回不同的解析结果,将客户端的访问引导到不同的机器上去,使得不同的客户端访问不同的服务器,从而达到负载均衡的目的。例如可以根据每台机器的负载量,该机器离用户地理位置的距离等等。

DNS缓存

我们有时会遇到一种情况:ip可以访问,域名地址访问失败,这是怎么回事呢?

原因:域名解析失败,往往是因为DNS缓存的问题。

DNS存在着多级缓存,从离浏览器的距离排序的话,有以下几种:

浏览器缓存,系统缓存,路由器缓存,ISP(电信运营商)缓存,根域名服务器缓存,顶级域名服务器缓存,主域名服务器缓存。

多级DNS服务器,每一级DNS服务器如何去缓存,缓存刷新时长?

浏览器缓存

chrome://net-internals/#dns 这里可以看各域名的DNS 缓存时间。Chrome对每个域名会默认缓存60s。

ISP(电信运营商)缓存

有些不靠谱,有些缓存服务器(不多)会忽略网站DNS提供的TTL,自己设置一个较长的TTL, 导致顶级DNS更新时不能及时拿到新的IP地址

缓存是双刃剑,提高了获取DNS的速度,也会影响DNS在IP变更时不能及时更新到最新。

简述http协议

http协议是在tcp/ip协议之上的应用层规范

http请求分为4部分:状态行,请求头,空行,消息体

<method> <request-URL> <version>
<headers>

<entity-body>

常用的四种方法:GET,POST,PUT,DELETE用来 查,增,改,删四种操作

常见请求头字段

  • Accept : 规定可接受的 response 的 Media type(s) 类型。 Accept: text/html
  • Authorization : HTTP认证的凭据(最基本的格式:该凭据是用户名+密码)。是最简单的资源访问限制的实现方法。 ;Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
  • Cache-Control :Cache-Control是no-cache,是浏览器通知服务器:本地没有缓存数据; Cache-Control:max-age=259200 是通知浏览器:259200 秒之内别来烦我,自己从缓冲区中刷新
  • Content-Type :请求体的类型 ;Content-Type: application/x-www-form-urlencoded
  • Cookie :该字段的值会同时被存储到浏览器端;Cookie: $Version=1; Skin=new;
  • Etag:特定版本资源的标识符,通常是消息摘要。ETag: “737060cd8c284d8af7ad3082f209582d”

GET和POST的区别

使用上

GET 是安全的和幂等的

GET /books/?sex=man&name=Professional HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Connection: Keep-Alive

POST 用于改变服务器上的资源

POST / HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Content-Type: application/x-www-form-urlencoded
Content-Length: 40
Connection: Keep-Alive

sex=man&name=Professional  

原理上

  • GET和POST是HTTP定义的两种不同方法,本质上都是TCP链接,并无差别
  • 有一个重大差别是,GET产生一个TCP数据包;POST产生两个TCP数据包

    • 对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
    • 而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
  • 但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。

    • GET用来获取资源,POST用来上传资源
    • GET参数通过URL传递,POST放在URL和body中
    • GET只能有ASCII码的编码方式提交请求,POST的数据编码格式没有规定
    • GET可提交的数据量受URL长度限制(浏览器规定url长度<2k,服务器一般只处理64k以下的数据),POST一般不受限制
    • GET请求会被浏览器主动cache,而POST不会,除非手动设置。
    • GET在浏览器回退时是无害的,而POST会再次提交请求。

HTTP状态码

状态码系列:

  • 1XX:通知
  • 2XX: 成功
  • 3XX 重定向
  • 4XX:客户端错误
  • 5XX 服务端错误

基本响应代码:

  • 200(“OK”)
    • 一切正常。实体主体中的文档(若存在的话)是某资源的表示
  • 400(“Bad Request”)
    • 客户端方面的问题。实体主题中的文档(若存在的话)是一个错误消息。希望客户端能够理解此错误消息,并改正问题。
  • 500(“Internal Server Error”)
    • 服务期方面的问题。实体主体中的文档(如果存在的话)是一个错误消息。该错误消息通常无济于事,因为客户端无法修复服务器方面的问题。
  • 301(“Moved Permanently”)
    • 当客户端触发的动作引起了资源URI的变化时发送此响应代码。另外,当客户端向一个资源的旧URI发送请求时,也发送此响应代码。
  • 404(“Not Found”) 和410(“Gone”)
    • 当客户端所请求的URI不对应于任何资源时,发送此响应代码。404用于服务器端不知道客户端要请求哪个资源的情况;410用于服务器端知道客户端所请求的资源曾经存在,但现在已经不存在了的情况。
  • 409(“Conflict”)
    • 当客户端试图执行一个”会导致一个或多个资源处于不一致状态“的操作时,发送此响应代码。

SOAP Web服务只使用响应代码200(“OK”)和500(“Internal Server Error”)。无论是你发给SOAP服务器的数据有问题,还是服务器在处理数据的过程中出现问题,或者SOAP服务器出现内部问题,SOAP服务器均发送500(“Internal Server Error”)。

HTTP各个版本之间的区别

http0.9

最初的http版本,仅支持get方法,只能传输纯文本内容

请求结束服务后会给客户端返回一个HTML格式的字符串,然后由浏览器自己渲染。

http0.9是典型的无状态连接

http1.0

  • 本质上支持长连接,但是默认还是短连接,增加了keep-alive关键字来由短链接变成长连接。
  • HTTP的请求和回应格式也发生了变化,除了要传输的数据之外,每次通信都包含头信息,用来描述一些信息。
  • 还增加了状态码(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)等

http1.1

  • HTTP1.1最大的变化就是引入了长链接,也就是TCP链接默认是不关闭的可以被多个请求复用
  • 客户端或者服务器如果长时间发现对方没有活动就会关闭链接,但是规范的做法是客户端在最后一个请求的时候要求服务器关闭链接。
  • 节约带宽,HTTP1.1支持只发送header头信息不带任何body信息,如果服务器认为客户端有权限请求指定数据那就返回100,没有就返回401,当客户端收到100的时候可以才把要请求的信息发给服务器
  • 并且1.1还支持了请求部分内容,如果当前客户端已经有一部分资源了,只需要向服务器请求另外的部分资源即可,这也是支持文件断点续传的基础。

http2.0

  • 多路复用:在一个连接里面并发处理请求,不像http1.1在一个tcp连接中各个请求是串行的。花销很大
  • 在1.0版本后增加了header头信息,2.0版本通过算法把header进行了压缩这样数据体积就更小,在网络上传输就更快。
  • 服务端有了推送功能,将客户端感兴趣的东西推给客户端,当客户端请求这些时,直接去缓存中取就行。

WebSocket协议

底层原理

  • 基于TCP传输协议,并复用HTTP的握手通道

有哪些优点

对比参照物是HTTP协议,概括地说就是:支持双向通信,更灵活,更高效,可扩展性更好。

  • 支持双向通信,实时性更强。
  • 更好的二进制支持。
  • 较少的控制开销。连接创建后,ws客户端、服务端进行数据交换时,协议控制的数据包头部较小。在不包含头部的情况下,服务端到客户端的包头只有2~10字节(取决于数据包长度),客户端到服务端的的话,需要加上额外的4字节的掩码。而HTTP协议每次通信都需要携带完整的头部。
  • 支持扩展。ws协议定义了扩展,用户可以扩展协议,或者实现自定义的子协议。(比如支持自定义压缩算法等)

连接建立过程

  1. 首先,WebSocket复用了HTTP的握手通道
  2. 具体是指:客户端通过HTTP请求与WebSocket服务端协商升级协议。协议升级完成后,后续的数据交换则遵照WebSocket的协议。

客户端:申请协议升级

GET / HTTP/1.1
Host: localhost:8080
Origin: http://127.0.0.1:3000
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: w4v7O6xFTi36lq3RNcgctw==
  • Connection: Upgrade:表示要升级协议
  • Upgrade: websocket:表示要升级到websocket协议。
  • Sec-WebSocket-Version: 13:表示websocket的版本。如果服务端不支持该版本,需要返回一个Sec-WebSocket-Versionheader,里面包含服务端支持的版本号。
  • Sec-WebSocket-Key:与后面服务端响应首部的Sec-WebSocket-Accept是配套的,提供基本的防护,比如恶意的连接,或者无意的连接

服务端:响应协议升级

HTTP/1.1 101 Switching Protocols
Connection:Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: Oy4NRAQ13jhfONC7bP8dTKb4PTU=

状态代码101表示协议切换,后续的数据交互都按照新的协议来。

具体步骤

服务器端:

  1. 创建socket,绑定端口
  2. 开始监听(listen)
  3. 等待并接受客户端连接请求,返回新的socket(accept)
  4. 由新socket与客户端进行io交互。
  5. 关闭连接(可能主动,也可能被动)

客户端:

  1. 创建socket;先三次握手,然后发起申请协议升级请求
  2. 连接服务器(connect) 与服务器进行io交互
  3. 关闭连接(可能主动,也可能被动) 以上是基于tcp协议的过程,udp更简单。

数据帧格式

  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-------+-+-------------+-------------------------------+
 |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
 |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
 |N|V|V|V|       |S|             |   (if payload len==126/127)   |
 | |1|2|3|       |K|             |                               |
 +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
 |     Extended payload length continued, if payload len == 127  |
 + - - - - - - - - - - - - - - - +-------------------------------+
 |                               |Masking-key, if MASK set to 1  |
 +-------------------------------+-------------------------------+
 | Masking-key (continued)       |          Payload Data         |
 +-------------------------------- - - - - - - - - - - - - - - - +
 :                     Payload Data continued ...                :
 + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
 |                     Payload Data continued ...                |
 +---------------------------------------------------------------+
  • FIN:1个比特。1,表示这是消息(message)的最后一个分片(fragment),0,表示不是是消息(message)的最后一个分片(fragment)。
  • Opcode: 4个比特。操作代码
    • %x0:表示一个延续帧。当Opcode为0时,表示本次数据传输采用了数据分片,当前收到的数据帧为其中一个数据分片。
    • %x1:表示这是一个文本帧(frame)
    • %x2:表示这是一个二进制帧(frame)
    • %x8:表示连接断开。
    • %x9:表示这是一个ping操作。
    • %xA:表示这是一个pong操作。

连接保持和心跳

  • 发送方->接收方:ping
  • 接收方->发送方:pong

ping、pong的操作,对应的是WebSocket的两个控制帧,opcode分别是0x9、0xA。

安全

Sec-WebSocket-Key/Sec-WebSocket-Accept

Sec-WebSocket-Accept根据客户端请求首部的Sec-WebSocket-Key计算出来。 计算公式为:

  1. 将Sec-WebSocket-Key跟258EAFA5-E914-47DA-95CA-C5AB0DC85B11拼接。
  2. 通过SHA1计算出摘要,并转成base64字符串。

Sec-WebSocket-Key/Sec-WebSocket-Accept主要作用在于提供基础的防护,减少恶意连接、意外连接

数据掩码

增强协议的安全性, 但并不是为了防止数据泄密,而是为了防止早期版本的协议中存在的代理缓存污染攻击(proxy cache poisoning attacks)等问题。

代理缓存污染攻击(TODO)

鉴权授权

在 HTTP 切换到 Socket 之前,没有什么好的机会进行鉴权,因为在这个时间节点,报文(或者说请求的Headers)必须遵守协议规范。但这不妨碍我们在协议切换完成后,进行鉴权授权:

鉴权

  • 在连接建立时,检查连接的HTTP请求头信息(比如cookies中关于用户的身份信息)
  • 在每次接收到消息时,检查连接是否已授权过,及授权是否过期
  • 以上两点,只要答案为否,则服务端主动关闭socket连接

授权

服务端在连接建立时,颁发一个ticket给peer端,这个ticket可以包含但不限于:

  • peer端的uniqueId(可以是ip,userid,deviceid…任一种具备唯一性的键)
  • 过期时间的timestamp
  • token:由以上信息生成的哈希值,最好能加盐

CDN的作用和原理

CDN(Content Delivery Network):内容分发网络

CDN是利用DNS的重定向技术,DNS服务器会返回一个跟用户最接近的点的IP地址给用户,CDN节点的服务器负责响应用户的请求,提供所需的内容。

三种web存储:localStorage、sessionStorage、cookie

cookie定义:http是无状态协议,cookie就产生了,来标识会话,维护状态

cookie就是一种浏览器管理状态的一个文件,其实就是一个小数据库的表结构,包括:name、value、Domain、path、expires, size 等等属性

cookie不可跨域

不可跨域性,就是不能在不同的域名下用,每个cookie都会绑定单一的域名

cookie的属性

  • name
  • value: 必须被URL编码
  • domain
    • cookie绑定的域名,如果没有设置,就会自动绑定到执行语句的当前域
    • 统一个域名下的二级域名也是不可以交换使用cookie的,比如,你设置www.baidu.com和image.baidu.com,依旧是不能公用的
  • path: 默认是’/‘,这个值匹配的是web的路由;当你路径设置成/blog的时候,其实它会给/blog、/blogabc等等的绑定cookie
  • Expires/max-age
    • Max-Age,是以秒为单位的,Max-Age为正数时,cookie会在Max-Age秒之后,被删除
    • 当Max-Age为负数时,表示的是临时储存,不会生出cookie文件,只会存在浏览器内存中,且只会在打开的浏览器窗口或者子窗口有效,一旦浏览器关闭,cookie就会消失
    • 当Max-Age为0时,又会发生什么呢,删除cookie,因为cookie机制本身没有设置删除cookie,失效的cookie会被浏览器自动从内存中删除,所以,它实现的就是让cookie失效。
  • secure: 当这个属性设置为true时,此cookie只会在https和ssl等安全协议下传输
  • HttpOnly(重要): 如果这个属性设置为true,就不能通过js脚本来获取cookie的值,能有效的防止xss攻击,

服务端设置

通过Set-Cookie用键值对形式设置请求头

OAuth2.0

OAuth授权所需信息:

  1. 应用名称
  2. 应用网站
  3. 重定向URI或回调URL(redirect_uri)
  4. 客户端标识 client_id
  5. 客户端密钥 client_secret

授权成功后,服务器 回调请求redirect_uri,客户端通过下发的code和自己的secret请求服务器得到access_token

B站课程

跨域

跨域是针对浏览器来说的,浏览器的同源策略 (地址里面的协议、域名和端口号均相同)

浏览器的同源策略: 一个请求在浏览器端发送出去后,是会收到返回值响应的,只不过浏览器在解析这个请求的响应之后,发现不属于浏览器的同源策略(地址里面的协议、域名和端口号均相同),会进行拦截。如果是在curl里面发送一个请求,都是没有跨域这样一个概念的

基于http协议层面的几种解决办法

  • 设置Access-Control-Allow-Origin
  • jsonp
  • CORS预请求

设置Access-Control-Allow-Origin\Headers\Methods请求头

res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Headers", "*");
res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, OPTIONS");
  • 设置为*表示,可以接收任意域名的访问;
  • 也可以设置为特定域名访问
  • 如果有多个域名访问可以在服务端动态设置

jsonp

浏览器是允许像link、img、script标签在路径上加载一些内容进行请求,是允许跨域的, 那么jsonp的实现原理就是在script标签里面加载了一个链接,去访问服务器的某个请求,返回内容。

<script src="http://127.0.0.1:3011/xxx"></script>

CORS预请求

“需预检的请求”要求必须首先使用OPTIONS方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。”预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。

ssl加密的过程

https是http + ssl或tls

HTTPS的加密解密方式是非对称加密与对称加密的结合

SSL全名为Secure Sockets Layer; TLS(Transport Layer Security); 传输层安全协议。

两种加密方式:

  • 对称加密(共享密钥加密): 加密和解密同用一个密钥。加密时就必须将密钥传送给对方。
  • 非对称密钥加密: 使用一对非对称的密钥。一把叫做私有密钥,一把叫做公开密钥。私有密钥不能让其他任何人知道,而公开密钥则可以随意发布,任何人都可以获得。

非对称加密过程:

  • A:B,你好,我想向你发一段消息,请你把你的公钥给我
  • B:好的,我的公钥是:xxxxxxx。
  • A:好的,我收到了你的公钥,我给你发送的消息经过你的公钥加密后是:yyyyyyy。
  • B:收到,我现在用我的密钥来解密看看。

由于非对称加密算法复杂度和计算量大,对称加密效率高,SSL就将这两种加密算法混合着用,这样安全和效率就都能保证了。其中具体的过程如下:

SSL加密过程(非对称加密算法 + 对称加密):

  1. 客户端A给出 支持的SSL版本+一个随机数+自己支持的加密方式
  2. 服务端B接收到这些信息后确认加密方式+自己的安全证书+一个随机数发给A
  3. 客户端A确认数字证书(验证服务端身份,防止中间人攻击)有效性,然后生成一个随机数,并将这个随机数用B的数字证书公钥加密后发送给B。
  4. 服务端B使用自己的私钥解密这个随机数
  5. A和B通过第二步确定的加密方法将前三个随机数生成一个对话密钥(对称加密),用来接下来的通信

如何开启HTTPS

申请一张SSL证书,然后将SSL证书部署到服务器端,开启443端口,就可以实现HTTPS访问了

如何验证数字证书的有效性

数字证书有效期验证

证书的使用时间要在起始时间和结束时间之内

根证书验证

普通的证书一般包括三部分:用户信息,用户公钥,以及CA签名

要验证这张证书就需要验证CA签名的真伪。那么就需要CA公钥。而CA公钥存在于另外一张证书(称这张证书是对普通证书签名的证书)中。因此我们又需要验证这另外一张证书的真伪。因此又需要验证另另外证书(称这张证书是对另外一张证书签名的证书)的真伪。依次往下回溯,就得到一条证书链。那么这张证书链从哪里结束呢?就是在根证书结束(即验证到根证书结束)。根证书是个很特别的证书,它是CA中心自己给自己签名的证书(即这张证书是用CA公钥对这张证书进行签名)。信任这张证书,就代表信任这张证书下的证书链。

所有用户在使用自己的证书之前必须先下载根证书。

所谓根证书验证就是:用根证书公钥来验证该证书的颁发者签名。所以首先必须要有根证书,并且根证书必须在受信任的证书列表(即信任域)。

数字证书的信任是基于对CA根证书的信任的

CRL验证

CRL是经过CA签名的证书作废列表,用于证书冻结和撤销。一般来说证书中有CRL地址,供HTTP或者LDAP方式访问,通过解析可得到CRL地址,然后下载CRL进行验证。

中间人攻击

定义:中间人攻击是指攻击者与通讯的两端分别创建独立的联系,并交换其所收到的数据,使通讯的两端认为他们正在通过一个私密的连接与对方直接对话,但事实上整个会话都被攻击者完全控制。

代理人攻击,在客户端和服务端之间做一层代理,获取两边信任,进行攻击

防范手段:https + 可信任数字证书

XSS攻击

跨站脚本攻击: 就是攻击者想尽一切办法将可以执行的代码注入到网页中。

XSS 的全称是 Cross Site Scripting 也就是跨站脚本,当目标网站目标用户浏览器渲染HTML文档的过程中,出现了不被预期的脚本指令并执行时,XSS就发生了

对于 XSS 攻击来说,通常有两种方式可以用来防御:

  1. 转义字符
  2. CSP(Content-Security-Policy)建立白名单

转义字符

用户的输入应该是永远不信任的。最普遍的做法就是转义输入输出的内容,对于引号、尖括号、斜杠进行转义

escape('<script>alert(1)</script>') => &lt;script&gt;alert(1)&lt;&#x2F;script&gt;

对于显示富文本来说,显然不能通过上面的办法来转义所有字符,因为这样会把需要的格式也过滤掉。对于这种情况,通常采用白名单过滤的办法,当然也可以通过黑名单过滤,但是考虑到需要过滤的标签和标签属性实在太多,更加推荐使用白名单的方式。

const xss = require('xss')
let html = xss('<h1 id="title">XSS Demo</h1><script>alert("xss");</script>')
// -> <h1>XSS Demo</h1>&lt;script&gt;alert("xss");&lt;/script&gt;
console.log(html)

CSP

CSP 本质上就是建立白名单,开发者明确告诉浏览器哪些外部资源可以加载和执行。我们只需要配置规则,如何拦截是由浏览器自己实现的。我们可以通过这种方式来尽量减少 XSS 攻击。

两种方式来开启 CSP:

  1. 设置 HTTP Header 中的 ==Content-Security-Policy==
  2. 设置 ==meta== 标签的方式 ====

以设置 HTTP Header 来举例

  1. 只允许加载本站资源 Content-Security-Policy: default-src ‘self’
  2. 只允许加载 HTTPS 协议图片 Content-Security-Policy: img-src https://*
  3. 允许加载任何来源框架 Content-Security-Policy: child-src 'none'

CSRF攻击

CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。

本质:攻击者盗用了你的身份,以你的名义发送恶意请求

手段:攻击者构造出一个后端请求地址,诱导用户点击或者通过某些途径自动发起请求。如果用户是在登录状态下的话,后端就以为是用户在操作,从而进行相应的逻辑

CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账……造成的问题包括:个人隐私泄露以及财产安全。

防御手段

  • 验证Referer;(服务端做Referer检查,阻止第三方网站请求接口;也不是万无一失的,发请求时我们可以篡改Referer的值)
  • 修改数据的敏感的操作应该使用POST;(攻击者也可以构造form提交,仅仅使用POST远远不够)
  • 请求时附带验证信息,比如验证码和token(csrftoken验证)
  • csrftoken验证
    • 在 HTTP 请求中以參数的形式添加一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,假设请求中没有token 或者 token 内容不对,则觉得可能是 CSRF 攻击而拒绝该请求。
    • csrftoken产生的机制:客户端与服务端 指定token产生规则,客户端发送请求时带上自己生成的token;隐患:客户端被破解(反编译等)无法防范;

Node.js增加csrftoken