目录
OSI网络参考模型
是什么
数据流通过程
示意图
FTP
控制连接/数据连接
主动模式/被动模式
HTTP
定义
是什么
为什么说HTTP是无状态的
HTTP生命周期
客户端请求消息
服务器响应消息
HTTP和HTTPS端口号
HTTP1.1/HTTP2.0/HTTP3.0
HTTP1.1
HTTP2.0
HTTP3.0
HTTPS
原理
总结
SSL/TLS
是什么
SSL/TLS区别
总结
握手次数
HTTP/RPC
原理
区别
为什么有了HTTP还要有RPC
GET/POST
区别
POST方法会产生两个TCP数据包?
GET方法参数写法是固定的吗?
GET方法的长度限制是怎么回事?
POST方法比GET方法更安全?
SOAP/HTTP
QUIC
是什么
示意图
TCP
是什么
三次握手
四次挥手
为什么要有确认号和顺序号
为什么要建立三次握手
为什么要四次挥手
TCP就一定不丢包吗
TCP为什么面向字节流
TCP/IP协议簇
UDP
是什么
用UDP就一定快吗
UDP为什么面向数据报文
WebSocket/Socket
为什么有了HTTP还要有WebSocket
Socket
能干什么
是什么
单工/半双工/全双工
浏览器访问一个网站地址发生了什么
DDoS
是什么
如何防止
串口通信协议
存储单位转换
OSI网络参考模型
是什么
- OSI网络参考模型,它只是参考,在实际网络中并不使用。
- 只是在实际网络出现问题的时候,可以从一个宏观的整体去分析和解决问题。
- 而且搭建网络的时候也并不一定需要划分为7层。
- 但是当今互联网广泛使用的是TCP/IP网络模型,它原本只有四层,但是随着大家不断的实践后发现, 其实划分为5层会更加符合实际。
- OSI七层的名字不难记,但是这七层里面的知识非常复杂,每一层想深入学习一下其实都很难。
- OSI网络参考模型的目的其实很简单,就是为了解决主机之间的网络通讯。
- 比如联想的电脑要和戴尔的电脑互联一下,但是两台电脑是不同的公司,就跟你用普通话去和一个说 英语的外国人交流一样,没法沟通。
- 但是如果都统一用OSI网络模型来进行沟通,情况就不一样了。
- 假设现在联想的电脑用自己的应用软件搭建了一个网站,戴尔的电脑想要访问整个网站就需要用自己 的应用软件比如浏览器来访问网站。
- 现在两个应用软件需要如何进行交互就是应用层的事情。
- 应用层并不是说你需要使用什么样的应用程序,而是应用如何沟通。
- 最常见的应用层协议就是HTTP,比较常用的还有FTP。
- 开发者可以根据HTTP协议编写应用程序,让应用软件之间可以实现沟通。
- 应用层就是最接近用户的那一层,但是应用层只不过是逻辑上把两个应用连通。
- 实际物理上的连通是需要物理层的。
- 我们要发送出去的数据在计算机里面只不过是无数的0和1,0或者1就叫做比特。
- 物理层就要把这些比特用不同的媒介传输出去,可以用电,用光或者其它形式的电磁波来表示和传输 信号。
- 数据从网络接口出去以后,会经过不同的网络拓扑,并不是一条线走到底,因此就需要中继器和集线 器这样的设备。
- 但还是不够,信号要去哪台设备是需要定向的,因此需要高级一点的网络模型。
- 在数据链路层这里,比特会被封装成帧,帧是这一层表示数据的特殊名字而已。
- 在封装的时候会加上MAC地址,也就是物理地址。
- 网卡出厂的时候就有着全球唯一的MAC地址。
- 为了可以通过MAC地址对不同的设备进行数据的传输,就出现了交换机。
- 这里说的是二层交换机。
- 比如现在有一台交换机,连接多台主机,发送端发送数据的时候,交换机就 知道了发送端的MAC地 址。
- 如果此时交换机也知道了接收端的MAC地址,就可以把数据直接发送过去。
- 物理地址就是这样一跳一跳的进行传递。
- 另外物理层在传输0和1的时候,可能0会变成1,或者1变成0,会进行差错控制,以及一定的差错 修正。
- 另外设备之间的传输能力以及接收能力也是个问题。
- 很可能这边喷水式的传输,另一边夹缝式的接受,因此需要流控制来避免这种不对称性。
- 互联网是一张大网,如果用MAC物理地址来作为唯一的寻址方法是不科学的。
- 比如我和你现在买了同一个牌子的网卡,如果网卡的MAC地址差别就只有一个字母。
- 但是我在西安,你在北京,物理地址此时就很难做出快速定位。
- 相当于我知道你的名字,但是不知道你住在哪里,找不到你。
- 因此需要IP地址来进行寻址和路由的选择。
- IP这样的逻辑地址就是实现端到端的传输,而不是物理地址那样跳到跳的传输。
- 说到路由的选择,就是路由器,也是网络层的核心。
- 包就是网络层里面数据的名字,在封装为二层的帧之前就是包。
- 路由器根据包里面的IP地址进行路由的转发,地址管理和路由的选择就是这一层的核心。
- 虽然MAC地址和IP地址可以抵达对方的主机,但是对方的主机可能运行着无数个软件进程。
- 比如我现在用谷歌浏览器和火狐浏览器同时登录网站,如何让数据到指定的软件服务上,就需要用到 端口号作为地址来进行定位。
- 比如客户端这里生成了不同的端口号,即使同时访问服务端的HTTP端口号80也是没有问题的。
- 根据不同的源端口号来作出响应就可以了,所以传输层在网络层端到端的基础上,实现了服务进程到 服务进程的传输。
- 段就是传输层里面数据的名字,在封装为三层包之前就是段。
- 传输层管理两个节点之间数据的传输,负责可靠传输和不可靠传输,也就是TCP协议和UDP协议,另 外还有一个新的协议叫QUIC。
- TCP允许应用把字节流变成多份段,而不是把整个字节数据完整的发送出去,传输层还有流量控制来 确保传输速度,再加上错误控制来进行数据完整的接收
- 然后就到了会话层,比如你现在登陆了某个网站,网站服务可以保持你的登录状态,不用每次都输入 账号和密码,而且网站服务还会管理和控制登录的状态
- 另外会话层还负责同步服务,比如上次看某个电影断电了,下次在看的时候就可以自动同步到上次看 的时间段。
- 不同计算机内部各自的表达方式可能不太一样,表示层就来负责这样的转换,也就是编码和解码。
- 数据往往还需要进行加密,比如HTTPS就需要对数据进行加密和解密。
- 另外还有可能需要对文件进行瘦身,压缩也是这一层负责的。
- 应用层,表示层,会话层的数据一般统称为应用数据,或者叫应用负载,还可以叫上层数据,同时也 是教科书上面说的报文。
- 数据在各层的名字分别是报文,段,包,帧,比特。
- 就地址来说,有端口号,IP逻辑地址,MAC物理地址。
- 就传输功能来说,有服务进程到服务进程,端到端,跳到跳。
- 那现在就可以把这些东西关联起来,也就能理解数据流通的过程。
数据流通过程
- 客户端要发送数据,也就是报文。
- 报文来到了传输层,加上端口号,封装成段。
- 段来到了网络层,加上IP地址,封装成包。
- 这里的包是含有目标IP地址的包,但是因为目标的IP地址不是同一个网络下的,如果要发送到其它的 网络上面,就需要经过默认网关。
- 但是客户端主机刚开始并不知道默认网关的MAC地址,没有办法封装成帧。
- 这个时候就可以用ARP协议进行广播,找到网关IP对应的MAC地址,把包封装成帧。
- 源MAC地址填自己的,目标MAC地址填广播的地址。
- 假设当前网络有个二层交换机,这个交换机只需要记录不同的接口对应的MAC地址就可以了。
- 交换机收到广播后就会帮忙发送出去,人手一份。
- 所以默认网关收到消息后,就查看了帧,发现了发送端的MAC地址,再解封发现了包里面的IP地址, 就会把客户端的MAC地址和IP地址关联为一台主机。
- 同时默认网关也会把自己的IP地址放到包里面,再结合自己的MAC地址封装成帧,默认网关就这样 作出了响应,然后在原路返回,发送端就知道了默认网关的MAC地址,现在就可以封装成帧,并且发 送数据。
- 比特流到了默认网关的时候,解封为帧发现是发送给自己的,在解封为包查看到目标的IP地址是在另 一个网络中,就会进行路由转发,最终到达了目的网络。
- 如果目标的网关知道了目标的IP地址和MAC地址是哪台主机,封装成为帧就可以直接发送出去。
- 如果不知道还是用ARP协议进行广播。
- 目标主机收到了包,确认是自己的IP地址以后,解封查看段可以发现源和目标的端口号。
- 用目标的端口号找到指定的应用程序,应用程序处理完成之后,就可以按照源的信息作出响应。
示意图
FTP
控制连接/数据连接
- 控制连接的标准端口为21,用于发送FTP的命令信息。
- 数据连接的标准端口为20,用于上传和下载数据。
主动模式/被动模式
- 主动模式指的是服务器从20端口主动向客户端发起连接,因此主动模式需要服务器防火墙打开21和 20端口。
- 被动模式指的是服务器在指定范围内的某个端口被动的等待客户端发起连接。
HTTP
定义
- 超文本传输协议,在网络传输的时候,是一种规范。
- 无链接表示没有长时间的链接,没有连续的链接。
- 无状态表示两次请求没有关联,所以无法识别。
是什么
- HTTP协议是一个应用层的协议,它定义了通信报文的一些格式。
- 主要由请求报文和响应报文组成。
- 请求报文包括请求行,请求头,空行,请求体。
- 响应报文包括状态行,响应头,空行,响应体。
- 那么符合这样一个协议特征的通信协议,它就是HTTP协议。
为什么说HTTP是无状态的
因为HTTP发送完请求就立马断开了,所有说没有状态。
HTTP生命周期
- HTTP客户端与Web服务器的HTTP端口建立TCP的套接字连接。
- 通过TCP的套接字连接,客户端向Web服务器发送一个请求报文。
- 服务器解析请求报文并返回响应报文。
- 最后断开TCP的套接字连接。
客户端请求消息
请求报文包括请求行(request line),请求头(header),空行,请求体。
- 请求行就是定义了本次请求的请求方式,请求地址,HTTP协议版本。
- 请求头是由一系列的键值组成,允许客户端向服务器发送一些附加的信息或者客户端自身的信息。
- 请求体只有在发送POST请求时才会有,GET方法发送的是请求参数。
服务器响应消息
响应报文包括状态行,响应头,空行,响应体。
- 状态行包括HTTP协议的版本,状态码,以及对状态码的文本描述。
- 响应头由一系列的键值组成,用于描述服务器的基本信息。
- 响应体就是响应回来的内容。
HTTP和HTTPS端口号
HTTP的端口是80,HTTPS的端口是443。
HTTP1.1/HTTP2.0/HTTP3.0
HTTP1.1
- HTTP1.1是互联网第一个真正意义的HTTP标准版本。
- 发送一个HTTP请求的时候,是需要等收到HTTP响应,才可以再发送下一个HTTP请求。
- 但是我们浏览网页的时候只需要点击一次鼠标,明显就是一个请求。
- 其实一个网页一般都由多个文件组成,最基本的就是HTML,CSS,JS和图片文件。
- 对于一个HTTP协议来说,我们打开一个网页需要进行TCP三次握手,建立起TCP的连接,才能正式进 行请求。
- 服务器会先发送HTML文件给浏览器,但是其它文件不会发送给浏览器。
- 浏览器在收到HTML文件以后,根据HTML里面的内容,再向服务器依次请求CSS,JS等文件。
- 整个过程都是浏览器在帮我们完成的,所以用户的直接感受是只有一次请求。
- 如果在请求队伍里,有一个文件没有收到,后面的文件也没法接收了,这就会造成HTTP队头阻塞。
- 虽然对于HTTP1.1来说,默认是持久连接的,也就是保持这个TCP连接不需要对每个请求再来一轮TCP 握手,请求和响应都可以放在同一个连接里面,但是只有一个连接肯定太慢了,连接太多又怕会造成 DDos攻击,因此各个浏览器允许的持久连接数都不太相同,谷歌默认的是同时6个连接。
- 即使有多个连接仍然有问题,假设浏览器的其它连接的响应文件都收到了,就只有一个连接的文件还 没有收到,刚好是导致浏览器没法渲染的CSS文件,这也会造成HTTP队列阻塞。
- 为了解决这个问题,HTTP1.1里面有个叫管线化的技术,意思就是单个连接可以发送多个请求。
- 但是这里有个坑,虽然可以一次性发送多个,但是响应的时候必须按照发送的顺序接收,我先发了什 么,就得先收到什么,这就会造成很大的执行难度,网络情况很难预知,非常有可能第一个要收到的 响应丢包了,然后第二个响应变成了第一个要收到的,所以大部分浏览器实际上不会用到管线化这个 技术。
- 很多网站会把小图标单独做成一个图片,请求的时候只需要请求一个文件,而不是分开这么多请求。
- 然后再用JS或者CSS把小图标分布到网站的各个部分,这个叫做精灵图或者雪碧图。确实减少了请求 的次数,但是对于开发者来说就很麻烦。
- 除此之外,Data URLs是另一种代替的方案,可以用base64进行编码,然后就可以以字符的形式写进 HTML或者CSS里面,不需要单独一份图片文件,但是一般这个编码结果非常长,很不方便代码的维护 和管理。
- 前面说的浏览器会限制同一连接的请求数,其实就是限制每个域的连接数,因此有些网站就弄出多个 域,可以让浏览器同时下载这些资源。
- 举个极端的例子,比如说网站有5张图片,那么就可以设置5个图片的域名,这样浏览器就可以同时 进行下载,也就不用等前面的资源下载完成后再轮到下个资源,这种做法也叫做域名分片,但是这样 做就把开发的复杂度又给提高了。
- 为了减少请求还有很多方法,比如把JS和CSS合并,或者把CSS和JS都整合到HTML里面。
- 虽然大家都在想尽办法减少请求,但是后来越来越多的网站都需要”上锁”,也就是需要HTTPS。不然 像谷歌这样的浏览器就会给你的网站提示不安全。
- 对于HTTP1.1来说原本进行通信前就要进行TCP的三次握手,现在HTTPS里面的TLS1.2又要进行握手, 握手后才可以进行加密通信,虽然后来的TLS1.3减少了握手次数,但是对于HTTP1.1来说,这一来一 回的负担还是太重了,越多的来回就意味着越多的未知数,如果网络上有中间件炸了,容易造成丢包, 结果还是可能会阻塞网页的渲染。
- TCP除了三次握手的固定开销以外,还会有个慢启动,因为要进行拥塞控制,也就是说为了不造成网 络拥堵,而且也不知道网络的实际情况,一开始只会发送较小量的TCP数据段,到了后面再慢慢增加, 因此会导致新访问的网页刷新速度比较慢。
- 除了TCP的开销以外,还有HTTP本身就会产生固定开销,请求和响应都是有各种首部的,而且大部分 的首部都是重复的,发完一次,下一次还得发,尤其是cookie,每次都得发,字符还特别长。再加上 HTTP1.1本来就是明文的,首部又没有进行压缩,所以大部分首部又累赘又臃肿。
- 后来就有了HTTP2.0。
HTTP2.0
- HTTP2.0里面最大的一个特点就是多路复用,多路复用就是解决HTTP1.1队头阻塞的问题。
- 单个TCP连接就可以进行交错式的发送请求和响应,而且请求和响应之间互不影响。
- HTTP2.0并不是把单个文件就这样给直接响应过去,请求报文和响应报文都被划分为各个不同的帧,这 个帧可以分为首部帧和数据帧。其实就是把原本HTTP报文的首部和实体给拆分为两个部分,所以原本 的HTTP报文就不再是原来的报文,而是有点像数据链路层的帧。
- 这里面有个重要的流标识符。有了这个流标识符,可以让帧不用按照顺序抵达到对方那里。即使没有 按照顺序,最终这个流标识符还是可以按照顺序进行组合,而且帧类型里还可以设置优先级,来标注 流的权重。
- 其次HTTP2.0把首部压缩了,不过这次引入了叫HPACK的压缩算法,HPACK算法要求浏览器和服务器 都保存一张静态只读的表。
- 比方说经典的”HTTP1.1 200”起始行,在HTTP2.0里面就变成了”:status: 200”,因为是重复的首部,可以 实现在二次请求和响应里直接去掉。
- 另外像Cookie这样的首部,可以作为动态信息加入到动态表里面,这样节省下来的资源更是可观的。
- 再加上HTTP2.0的帧并不是ASCII编码的报文,而是被提前转化为二进制的帧,解析起来更有效率。
- HTTP2.0还有一个服务器推送,其实就是当浏览器进行请求的时候,服务器可以不像以往一样等浏览器 解析HTML时再一个一个响应,而是把浏览器后续可能需要的文件,一次性全部发送过去。
- 但是有个问题,客户端有可能点错了网页,但是就会多了很多缓存,而且服务器推送也可能造成DDos 攻击,所以HTTP2.0也会存在安全问题。
- 但实际上HTTP2.0比HTTP1.1要安全很多,首先是前面说到报文变为二进制的帧,对于人来说可读性 就差了很多。
- 其次虽然没有说HTTP2.0规定要用TLS加密,但是如果用了HTTP2.0还不用TLS加密就说不过去了。因 为到了HTTP2.0这个年代,还不用TLS加密,大牌浏览器都会提示不安全。
- 而且HTTP2.0的多路复用也已经减少了等待的时间,久而久之就变成了HTTP2.0必须用TLS。
HTTP3.0
- HTTP2.0只是解决了HTTP层面的队头阻塞,HTTP下面还有个传输层,而且HTTP是基于TCP的。
- HTTP2.0的帧发送下来以后要由TCP来处理,TCP不知道帧里面的内容哪个和哪个是一起的,TCP还是 按照自己的数据段来发送,如果有丢失的,还得重传。即使丢失的TCP数据段刚好是一行代码注释, 也没办法,也得重传,这就是TCP层面的队头阻塞。
- HTTP3.0就是把TCP和TLS的握手过程整合在了一起,直接减少了来回握手带来的开销,如果是重新恢 复的会话还可以不用再次握手。
- 但是TCP和TLS是两个协议,并不是说合并就能合并,为了能够让HTTP3.0进行部署,只能选择传输 层的UDP协议,并且在UDP协议上新增了一个协议,也就是QUIC。
- 这个QUIC整合了TCP和TLS,使得HTTP3.0默认就是要使用加密来进行传输的。
- 所以QUIC也可以不严谨的说成是TCP2.0。
- QUIC是因为要能够进行广泛部署才只能使用UDP,但是实际上的机制大部分还是采用TCP。
- QUIC主要解决了TCP层面的队头阻塞问题,从应用层那边传送过来的数据会被封装成QUIC帧,这个 QUIC帧和HTTP2.0的帧很像,也是加了流标识符。
- 但和HTTP2.0不同的是,HTTP3.0的应用层并没有所谓帧的概念,而是把数据帧转移到了QUIC里面, 相当于在传输层就有了数据帧,从源头解决了队头阻塞的问题,实现多路复用。
- 然后QUIC帧又再次被封装为QUIC数据包,QUIC数据包会加上一些信息,这里最重要的是加了 ConnectionID。
- 如果网络发生了全面的改变,比如说从WiFi突然转到了5G网络,虽然IP地址会发生改变,但是因为 客户端和服务端都协商好了连接ID,因此可以用连接ID来识别为同一个连接,避免再次握手。这也是 QUIC速度快的原因之一。
- 而且QUIC数据包会把里面的QUIC帧进行加密,也就是在TLS握手之后,QUIC帧里面的内容被加密了, 然后QUIC数据包会被UDP封装成数据段,这个时候UDP就会加上端口号。
- 所以当我们选择HTTP3.0进行通信的时候,QUIC就会像TCP那样开启连接,QUIC数据包就是在开启的 连接通道里进行发送和接收的。
HTTPS
原理
- HTTPS并不是一个单独的协议,它是在HTTP的基础上用TLS/SSL进行加密。
- SSL是TLS的前身,它们两个都是加密安全协议,现在绝大部分浏览器都不支持SSL,而是支持TLS。
- 所以在了解TLS对HTTPS的影响之前,就得先了解一下对称加密和非对称加密。
- 对称加密就是双方用同样的规则来为数据进行加密,也可以说是用同样的钥匙来解开密文,问题就是 如果有第三方知道加密的规则以后,就很容易被破解。
- 非对称加密会难理解一些,比如说张三和李四现在要进行通信,张三和李四的私钥都是唯一的,但是 彼此之间的公钥是相同的。
- 张三用自己的私钥和公钥进行混合生成新的密钥,发送给李四。
- 李四也用自己的私钥和公钥进行混合生成新的密钥,发送给张三。
- 张三再用自己的私钥和李四发送过来的混合密钥再混合一下得到了一个新的密钥。
- 李四也用自己的私钥和张三发送过来的混合密钥再混合一下得到了一个新的密钥。
- 最终张三和李四混合之后的密钥是一模一样的,这也就成了他们之间的通信密钥。
- 然后张三和李四就用最终混合出来的密钥给数据加密。
- 重点就是最终混合出来的密钥是用张三和李四各自的私钥给混合出来的。
- 这就是非对称加密的核心所在,用两个密钥来进行加密和解密,公开密钥是所有人都知道的密钥,私 有密钥仅仅是持有方才有的密钥。
- 一般来说私钥就放在服务器里面,数据经过公钥加密就只能被私钥解密,反过来数据经过私钥加密就 只能被公钥解密。
- 如果应用到客户端和服务器的话,就是服务器自己拥有成对的私钥和公钥,然后公布自己的公钥让客 户端知道。
- 客户端用公钥把自己的数据进行加密,加密后用公钥反而无法解密这段数据,一定要用服务器的私钥 才能解密,这样的非对称加密其实也叫公钥加密,因为不同于对称加密中只使用一把私钥进行加密。
- 其实在TLS中对称加密和非对称加密两种都得用上。
- 虽然现在可以对数据进行加密,但是还是不知道和我在沟通的是否是自己想要的对象。
- 比如有些域名很容易输入错误,这样就有可能会有不法分子伪装成这些域名来让你访问。
- HTTPS就解决了这个问题,因为服务器需要申请SSL证书,来证明这个域名是大家所熟知的域名。
- SSL证书其实就是保存在源服务器的数据文件,要让SSL证书生效就需要向CA机构申请,这样大家都 来信任这个机构颁发的证书。
- 这个证书除了表明域名是属于谁的,最重要的是这个证书里还包括了特定的 公钥和私钥。
- 简单来说服务器安装了SSL证书以后,用户就可以通过HTTPS来访问服务器了。
- 当然浏览器也会把HTTP默认端口80改为HTTPS的默认端口443。
- 现在浏览器通过HTTPS访问服务器正常的TCP三次握手是不变的。
- TCP三次握手以后,客户端发送了一个Client Hello给服务器。
- 客户端就会告诉服务器支持的TLS版本和支持的加密套件。
- 这里面有16个加密套件可以简单理解为不同的加密算法组合。
- 然后生成一个随机数发给服务器。
- 服务器接收到客户端的请求以后发送Server Hello给客户端,在响应报文里面会告诉客户端,服务器确 认支持的TLS版本以及选择的加密套件,并且服务器也会生成一个随机数发给客户端。
- 接下来服务器会再发出一个响应,来出示服务器自己的证书,这样浏览器就可以对照自己的证书信任 列表来确认这个服务器是否可信。
- 然后服务器再把公钥发送给了客户端。
- 最后服务器还要告诉客户端发送完了,于是就是Server Hello Done。
- 现在就轮到客户端来处理这些响应,首先客户端会生成第三个随机数,也叫预主密钥。这第三个随机 数会用刚刚收到的公钥进行加密,并且把这个加密后的随机数发送给服务器。
- 然后客户端再告诉服务器往后的数据就用商议好的算法和密钥来加密。
- 最后客户端再发一次请求,表示客户端这边TLS协商已经没有问题了。
- 同样的,服务器也给客户端发送一次请求表示服务器这边已经准备好了。
- 这里也表示着TLS的握手已经成功了。
总结
- 首先客户端和服务器打招呼,把自己的TLS版本,加密套件发送给服务器,同时还生成了一个随机数 给服务器,这里就称为第一个随机数。
- 接着服务器给客户端打招呼,服务器会告诉客户端当前服务器支持的TLS版本以及当前选择的加密套 件,并且服务器也会生成一个随机数发送给客户端,这里就称为第二个随机数。
- 接着服务器还会把证书和公钥发给客户端,都发送完毕后就告诉客户端。
- 然后客户端这边也会生成随机数,这里就称为第三个随机数,也叫做预主密钥。
- 这个预主密钥不会直接发送出去,而是用刚刚收到的公钥进行加密后再发送出去。
- 然后客户端这边的TLS协商已经没问题了,加密就开始了。
- 客户端把加密后的预主密钥发送给服务器,服务器会用自己的私钥进行解密,这样服务器就知道了预 主密钥。
- 最后客户端用预主密钥,第一个随机数和第二个随机数计算出会话密钥。
- 服务器也用预主密钥,第一个随机数和第二个随机数计算出会话密钥。
- 各自得到的会话密钥是相同的,得到会话密钥的步骤都是非对称加密的。
- 后面的会话都只使用这个会话密钥对数据进行加密,也就是后面使用的是对称加密,大家都使用同一 个私钥。
- 如果与其它服务器沟通就是建立新的会话,会话密钥也不相同,会话密钥只应用在当前会话,从而提 高了安全性。
SSL/TLS
是什么
- SSL/TLS是把HTTP下层的传输层协议由TCP/IP换成了SSL/TLS。
- 从而让HTTP运行在安全的SSL/TLS协议之上。
SSL/TLS区别
- TLS的产生是为了让SSL更安全,使协议更加精确和完善。
- TLS是在SSL3.0的基础之上进行了加强,最主要的差别是所支持的加密算法不同。
- TLS和SSL3.0不能互相操作,所以TLS相当于SSL3.1的版本。
- 也可以将TLS看作是SSL的升级版。
- SSL和TLS使用的报文鉴别码也是不同的。
- 还有就是TLS和SSL使用的算法也不相同。TLS使用RFC-2104定义的HMAC算法。SSL3.0也使用了类 似的算法,虽然和TLS的安全程度一样,但是具体的算法不一样,SSL3.0采用的算法在填充字节和秘 钥之间采用的是连接运算,而TLS的HMAC算法采用的是异或运算。
- 除此之外TLS还有更加严密的报警代码,比如解密失败,记录溢出,拒绝访问。
总结
- SSL/TLS对数据进行了加密传输,能够有效的防止数据被窃听。
- SSL/TLS的校验机制,能够有效的防止数据被篡改。
- CA机构颁发的SSL证书,能够有效的解决网站被冒充的风险。
握手次数
- TCP的握手次数是3次。
- 如果使用的是TLS1.2的版本那么握手次数是4次,所以HTTPS的握手次数一共是7次。
- 如果使用的是TLS1.3的版本那么握手次数是2次,所以HTTPS的握手次数一共是5次。
HTTP/RPC
原理
- HTTP协议是一个应用层的超文本传输协议,它是万维网数据传输通信的一个基础。
- 主要用于网页和服务器之间的一个数据传输。
- RPC是一个远程过程调用协议,它的定位是在不同的计算机应用之间实现数据的通信。
- 它只是通信协议的一个规范,并没有具体的实现,只有按照RPC的通信协议规范去实现的通信框架, 才是RPC协议真正具体的一个实现。
- RPC框架的底层都屏蔽了通信的复杂度,就像调用本地服务一样,去完成远程服务的一个调用。
- 因此这两个协议在定义层面是完全不同的。
区别
- HTTP是一个成熟的通信协议,RPC只是定义了服务之间数据通信的一个规范。
- HTTP协议和实现了RPC协议的框架,都能够去实现跨网络节点之间的一些服务通信。
- 它们底层都使用了TCP协议作为通信基础。
- RPC只是一种标准协议,符合RPC协议的这个框架都属于RPC框架。
- 所以RPC的网络通信协议层也可以使用HTTP协议来实现,比如gRPC。
为什么有了HTTP还要有RPC
- 都用HTTP就好了为什么还要用RPC呢?
- 首先是服务发现,要向某个服务器发起请求,首先要建立连接。
- 建立连接需要知道服务器的IP地址和端口号。
- 这个去找服务器IP地址和端口号的过程,就是服务发现。
- 在HTTP中,需要知道服务的域名,然后通过DNS服务器去解析,得到当前域名的IP地址和端口号。
- RPC就有些区别,一般会有专门的中间服务,去保存服务名和IP地址信息,比如consul。
- 如果想要访问某个服务,就去这些中间服务获取IP地址和端口号信息。
- 其实DNS服务器就是服务发现的一种体现。
- 所以也有基于DNS服务器去做服务发现的组件,比如CoreDNS。
- 所以在服务发现这一块儿,HTTP和RCP还是有区别的。
- 还有就是底层连接形式也是有区别的。
- 以HTTP1.1举个例子,它在建立底层TCP连接之后,会一直保持这个连接,之后的请求和响应都会复 用这条连接。
- RPC协议跟HTTP协议也类似,也是通过建立TCP的长连接进行数据交互。
- 但是不同的地方在于,RCP协议一般还会在建立个连接池。
- 在请求量大的时候,建立多条连接放在池内。
- 要发送数据的时候,就从池里面取出一条连接出来,用完放回去下次再复用。
- 由于连接池有利于提升网络请求的性能。
- 所以有不少编程语言的网络库里面,都会给HTTP加个连接池,比如谷歌的GO语言就是这么干的,最 后就成gRPC。
- 还有一点就是传输的内容,基于TCP传输的消息,无非就是消息头和消息体。
- 消息头标记一些特殊的信息,其中最重要的是消息体的长度。
- 消息体里面存放的是真正需要传输的内容,这些内容最终都是二进制0和1。
- 所以用TCP传输字符串和数字,问题都不大。
- 因为字符串可以转成编码再变成01串,数字本身也能直接转为二进制。
- 但是结构体也需要把它转成二进制01串这样的方案,现在也有很多现成的,比如JSON Protobuf。
- 这种可以将结构体转为二进制数组的过程就是序列化。
- 反过来,将二进制数组复原成结构体的过程就是反序列化。
- 对于HTTP1.1来说,虽然它叫超文本传输协议,支持音频和视频。
- 但是HTTP设计的本意,是用于做网页文本展示的,所以它传输的内容以字符串为主。
- 在消息体中,它使用JSON来序列化结构体的数据.
- 但是因为RPC定制化的程度更高,可以采用体积更小的protobuf去保存结构体的数据。
- 同时也不需要像HTTP那样考虑各种浏览器的行为,比如像302重定向啥的,因此性能也会更好一些。
- 这也是在公司内部微服务中抛弃HTTP选择RCP的主要原因。
- 但是HTTP2.0在HTTP1.1的基础上做了很多改进,所以性能可能比RCP协议还要好。
- 谷歌的gRPC底层就直接使用了HTTP2.0。
- 那为啥有了HTTP2.0还要有RPC协议?
- HTTP2.0这个协议是2013年的时候推出的。
- 在2013年以前,那个时候很多公司内部的RPC协议都已经跑了很多年了。
- 所以基于这些历史的原因,一般也没有必要去换。
GET/POST
区别
- GET在发送数据时,是向URL中添加数据的,URL的长度是受限制的,最大长度是2048个字符。
- POST在发送数据时,是向请求体中添加数据的,数据的长度是没有限制的。
- GET在后退或者刷新时是安全的,但是POST的数据可能会被重复提交。
- GET的数据可以被浏览器缓存,但是POST的数据不能被浏览器缓存。
- GET的参数可以保存在浏览器的历史中,但是POST的参数不会保存在浏览器的历史中。
- GET只允许ASCII编码的字符,但是POST没有限制,也允许二进制的数据。
- GET的编码类型是application/x-www-form-urlencoded。
- POST的编码类型可以是application/x-www-urlencoded也可以是multipart/form-data。
- GET的安全性较差,发送的数据是URL的一部分。POST比GET更安全,参数是不会保存在浏览器的历 史中。
- GET的数据在URL中是可见的,POST的数据在请求体中,数据不会显示在URL中。
- GET是安全并且幂等的请求,适合查询类接口的使用。POST是不安全并且不幂等的请求,适合提交类 接口使用。
POST方法会产生两个TCP数据包?
- 部分浏览器发送POST请求的时候,浏览器会先发送请求头,服务器响应100 continue,浏览器再发送 请求体,服务器响应200。
- 网络环境好的情况下,发送一次TCP数据包和发送两次TCP数据包的时间差别基本上可以无视。
- 但是在网络环境差的情况下,发送两次TCP数据包在验证数据包的完整性上面,有非常大的优势。
- 在HTTP协议中并没有明确说明POST会产生两个TCP数据包,比如谷歌浏览器就不会分开发送。
- 所以,请求头和请求体分开发送是部分浏览器或者某些框架的请求方法,不属于POST的必然行为。
GET方法参数写法是固定的吗?
- 在默认的约定中,GET的参数是写在?后面,用&分割。
- 也可以自己约定参数的写法,只要服务端能够解析出来就行。
GET方法的长度限制是怎么回事?
- HTTP协议中并没有请求体和URL的长度限制,对于URL的长度限制大多是浏览器和服务器的原因。
- 浏览器和服务器在处理比较长的URL时要消耗比较多的资源,所以为了性能和安全的考虑,就会给URL 的长度加限制。
- 主要还是为了防止客户端恶意构造较长的URL来攻击服务器。
POST方法比GET方法更安全?
- POST方法比GET方法更安全,仅限于数据在浏览器的地址栏上不可见。
- 从数据传输的角度来说,它们都是不安全的,因为HTTP在网络上是明文传输的,如果在网络节点上被 抓包,就能够获取完整的数据报文。
- 所以想要比较安全的数据传输,就只能加密,也就是使用HTTPS。
SOAP/HTTP
- HTTP协议不管当前这个数据是什么格式,它只管发送和响应。
- SOAP协议需要把数据对象转换成XML格式,然后通过HTTP协议来进行发送和响应。
- 这也就导致基于SOAP协议的产品,比如WebService慢慢的都没有公司在用了。
- 因为XML格式实在是太过于冗余和繁琐了,非常的笨重,可读性也比较差。
- 取而代之的是基于HTTP协议的WebAPI和gRPC,因为JSON格式非常的轻便和灵活,而且可读性也非 常高,解析规则也变得简单了。
- 但是JSON格式能支持的数据类型是非常少的,比如在JSON格式里面产品的价格到底是int,float还 是double根本就不知道。
- 所以在一些业务要求比较高的领域,就比如支付,还是用XML格式比较合适。
QUIC
是什么
- 要对QUIC有个整体的概念,就得了解HTTP2.0的基本通信模型。
- 靠近用户的应用层使用的是HTTP2.0的协议。
- 这个协议除了包含基本的HTTP语义,还有特有的多路复用以及流量的控制。
- 虽然HTTP2.0没有强制要求加密,但是基本都会实现加密。
- 所以就有了TLS这一层,这一层负责加密前的握手,以及身份认证,完整性和机密性,就是加密那些 玩意儿。
- 上层应用的数据下来以后就到了传输层,也就是使用TCP进行可靠控制。
- 因此TCP会负责通讯前的握手,负责拥塞控制和流量控制。
- 传输层下来就是网络层,也就是IP层。
- 但是对于QUIC的网络模型就不一样了。
- 首先QUIC会把HTTP2.0的多路复用和流量控制这些优点保留。
- 然后把TCP的拥塞控制和流量控制还有传输层的机制也保留。
- 最后再把TCP的三次握手和TLS的握手进行整合。
- 由于QUIC协议整合并且改良的东西太多了。
- 让QUIC协议直接在HTTP2.0下面共同工作,会产生很多问题。
- 所以就直接产生了新的HTTP协议,也就是HTTP3.0。
- HTTP3.0基本就是保留了HTTP的基本语义,把HTTP2.0的很多功能都交给了QUIC。
- 但是操作系统暂时并没有QUIC这个协议。
- 所以QUIC依旧必须依托在旧的传输层协议上。
- 如果选TCP肯定不行,因为QUIC本来就是要作为TCP2.0来代替旧的TCP,因此只能选择UDP,不然 无法完成应用进程到应用进程之间的传输。
- 如果把QUIC划分为应用层协议,按照定义来说不太准确,但是又有点道理,因为QUIC其实就是在应 用层实现的。
- 这也是为了让QUIC能够快速广泛的部署,而不用等到操作系统全面的升级。
- QUIC本身没有什么新东西,都是从别人那里拿了一点。
- 所以QUIC的数据包就是一个以太网帧把IP数据包封装在里面。
- IP数据包里面又封装了UDP段。
- UDP段里面又封装了1个或者多个QUIC包。
- QUIC包里面又封装了1个或者多个QUIC帧。
- QUIC帧里面又封装了应用层的数据。
- 简单来说就是把应用数据拆分为QUIC流,然后把QUIC流组合成QUIC帧,然后再把QUIC帧封装成 QUIC包。
- 每个QUIC包都有自己独立的编号,如果丢失了某个QUIC包,就能知道丢失的QUIC包里面的QUIC流。
- 其它的QUIC包不需要停着不动来等待重传,只需要重传必要的QUIC包,用来解决TCP的队头阻塞问 题。
- 这个机制看起来挺好,但是如果丢包的数据刚好是阻塞浏览器渲染页面的文件,比如就是某个CSS文 件的一部分。
- 页面还是无法渲染,看着解决了队头阻塞的问题,也只是从理论上解决了TCP队头阻塞的问题。
- 还有一个机制就是0-RTT。
- 对于HTTP2.0来说,在进行通信之前会产生TCP的三次握手,这里产生了1-RTT,也就是一次来回。
- 接着进行加密握手,如果使用的是TLS1.2,那么会造成2-RTT,也就是二次来回。
- 然后才进行正常的加密通信。
- 所以使用TLS1.2的HTTP2.0产生了3-RTT,也就是三次来回。
- 如果使用的是TLS1.3的HTTP2.0,那么加密握手会减少一轮,也就是总体变成了2-RTT。
- 对于使用QUIC的HTTP3.0来说,因为把TCP和TLS的握手整合在了一起,因此变成了1-RTT。
- 1-RTT以后就是加密通信了,因为通信双方所需要的各种参数都已经有了。
- 如果需要恢复通信,就可以直接使用加密参数进行通信。
- 这个时候整个通信连接变成了0-RTT。
- 所以可以理解为1-RTT是QUIC的首次通信,0-RTT是通信的恢复。
- QUIC的1-RTT握手的本质还是TCP和TLS。
- 最开始客户端会发送Client Hello进行打招呼。
- 接着服务端会响应Server Hello作为确认。
- 这两步的作用可以理解为加密的初始化,也就是InitalCRYPTO。
- 这两步完成以后下面的信息都是加密的信息。
- 在实际的抓包过程中,客户端会首先发送QUIC包,属于Inital初始化的握手信息。
- QUIC包里面封装的帧类型为CRYPTO,并且也会注明是TLS1.3发送Client Hello这一步。
- 然后服务端会响应Inital初始化的握手信息,包里面封装的帧类型也是CRYPTO,并且注明了是TLS1.3 的Server Hello。
- 接下来就是真正的握手,但是已经被加密了,而不是等到整个握手过程完成才进行加密。
- 实际上到了这一步可以说握手已经完成了一半,那客户端和服务端总得交换信息才能生成密钥。
- 所以说初始化握手并不是单纯的打个招呼那么简单。
- 在TLS1.3的Client Hello里面记录的信息,出现了随机数,加密套件,压缩方式,这些都是加密前需要 提供的信息。
- 相应的,服务端的Server Hello也提供了相应的参数内容。
- 正是因为在这两步双方都提供了各自需要的加密参数,生成了中间人的密钥。
- 那么对于中间人,可以在Handshake包里面,也就是第一个被加密的包里面可以看到IP地址和端口号, 还有一些其它的附加信息。
- 这些附加信息里面,最重要的是Connection ID。
- 另外一条重要的信息是包首部的Long Header。
- QUIC包里面有长首部和短首部。
- 长首部用于1-RTT的初次连接。
- 短首部可以用于1-RTT的密钥协商之后在使用。
- 在Handshake里面,还注明着encrypted Extensions和Certificate。
- 意思就是服务端在发送完Server Hello以后,还会把一些安全的扩展信息跟着一起发送出去,比如证书。
- 而且这些QUIC包一般会分成多个同时进行发送,在确认发送完毕以后客户端会响应Finished来表示握 手正式完成。
- 服务端也会响应HANDSHAKE_DONE来表示握手完成。
- 接下来就是正式的数据传输了,也就是包含了HTTP3.0的数据传输。
- HTTP3.0的流类型里面有一个加QPACK的东西。
- HTTP2.0使用的是HPACK的压缩格式,但是HAPCK是给TCP用的。
- 为了兼容QUIC就在HPACK的基础上发展出了QPACK这种压缩格式。
- 在整个流程里面,最重要的就是在前面的这个1-RTT里面,所有的信息都会被整合到这里面进行发送。
- 到了HANDSHAKE加密握手这一步就已经是加密的通信了。
- 这一点和其它协议的握手是有区别的。
- 如果是0-RTT,客户端发送Client Hello的时候就需要带上Token,并且把加密后的应用层数据也一起进 行发送,接着就可以直接进行响应了。
- 这里只不过是形式大大改变了,以前的HTTP数据被加密后再加上TLS和TCP的首部。
- 现在到QUIC这里就不一样了,除了HTTP的数据以外,还有很多首部信息也被加密了。
- 比如包的编号,ACK,帧。
- 对于用户来说数据变得更安全了,但是对于ISP来说要屏蔽某些流量就很难进行侦测了。
- 毕竟ISP能看到的QUIC包里面最重要的就是Connection ID。
- 在进行TCP可靠传输的时候,是需要根据4元组来建立一条逻辑连接的。
- 也就是源IP地址和目标的IP地址,以及源端口号和目标的端口号。
- 这样就可以准确定位到某台主机的某个服务进程里面。
- 但是如果4元组里面其中的一个元素改变了,就需要重新进行握手。
- 比如手机连接了家里的WiFi,出了家门以后,WiFi断了,手机一般会自动连到5G。
- 这个时候手机的源IP地址是会发生变化的,也就是需要重新进行TCP的握手连接。
- 为了避免这种断开又连接的重复情况,QUIC在包里面加上了连接ID。
- 客户端和服务端会协商好连接ID之后,就可以使用连接ID来识别某条逻辑上的链路。
- 但是即使有了连接ID,当在切换网络的那么一小段时间里,还是能够感觉到网络的延迟。
- 而且多了连接ID,相当于多了要存储的信息。
- 比如负载均衡除了需要基本的4元组以外,还得保存连接ID。
- 没办法改不了的东西,就得往上再加。
- 但是QUIC把HTTP2.0的很多优点都继承了下来。
- 比如流量限制,其实在一开始握手的时候就会告诉对方。
- 在Client Hello的扩展信息里面,有着quic_transport_parameters,这是QUIC的一些特殊参数,有一些 数据流的一些限制说明。
- 如果数据包需要重传,也是需要根据一定的信息来进行判定的。
- QUIC里面有一种重要的帧类型叫做ACK。
- 简单来说QUIC就是依靠这个ACK帧里面的内容,告诉了对方什么收到了,什么需要重传。
- QUIC确实从理论上解决了很多问题,特别是高延迟和容易丢包的网络环境下,QUIC会发挥它的作用。
- 但是在实际部署中肯定会存在着很多问题,每一个新技术,没有一定的资金和政策,要快速广泛的应 用还是会有很多的困难。
示意图
TCP
是什么
- TCP面向连接,面向字节流,有三次握手和四次挥手的存在,是一种可靠的通信协议,传输弱于UDP。
- TCP在传输过程中是一个源源不断的Byte流。在标准的TCP通信抽象上,操作的是Stream。
三次握手
- 第一次握手:客户端向服务器请求建立连接,把SYN设置为1,Ack设置为0,在选择一个顺序号x, 然后发送给服务器。
- 第二次握手:服务器收到了客户端的连接请求,此时服务器需要给客户端回复一个确认连接信息,把 SYN设置为1,Ack设置为1,确认号设置为x+1,同时也选择一个顺序号y,然后发送给客户端。
- 第三次握手:客户端收到了服务器的确认连接信息,也需要给服务器回复一个确认连接信息,把SYN 设置为0,Ack设置为1,确认号设置为y+1,顺序号设置为x+1,然后发送给服务器。
四次挥手
- 第一次挥手:客户端向服务器请求断开连接,把FIN设置为1,Ack设置为0,选择一个顺序号x,然 后发送给服务器。
- 第二次挥手:服务器收到了客户端的断开连接请求,此时服务器需要给客户端回复一个确认信息,把 FIN设置为0,Ack设置为1,确认号设置为x+1,同时也选择一个顺序号y,然后发送给客户端。
- 第三次挥手:服务器向客户端完成数据的传输以后,需要再向客户端发送一个断开连接的请求,把FIN 设置为1,Ack设置为1,确认号设置为x+1,同时也选择一个顺序号z,然后发送给客户端。
- 第四次挥手:客户端收到了服务器的断开连接请求,也需要给服务器回复一个确认信息,把FIN设置 为0,Ack设置为1,确认号设置为z+1,顺序号设置为x+1,然后发送给服务器。
- 谁都可以先发起断开连接的请求,谁先发起断开连接的请求谁就是客户端。
为什么要有确认号和顺序号
- TCP是可靠的通信协议,所以通信双方都必须要维护一个序列号,用来标记已经发送出去的数据包。
- 三次握手就是通信双方相互告知序列号的起始值,为了确保这个序列号被收到,所以双方都需要有一 个确认的操作。
为什么要建立三次握手
- TCP协议需要在一个不可靠的网络环境下实现可靠的数据传输,这就意味着通信双方必须要建立一个 可靠的数据传输通道,进行三次通信就是建立这样一个通道的最小值。
- 当然还可以四次,五次,只是没有必要浪费这个资源。
- 三次握手也可以防止重复的连接进行初始化,比如说在网络环境比较差的情况下,客户端连续多次发 送建立连接的请求,假设只有两次握手,那么服务器只能选择接受或者拒绝这个连接请求,但是服务 器不知道这次请求是不是之前因为网络堵塞而过期的请求,也就是说服务器不知道当前客户端的连接 是有效的还是无效的,所以才需要进行三次握手。
为什么要四次挥手
- TCP的通信过程是一个全双工的模式,也就是双方都可以同时向对方发送数据或者接受数据。
- 这也就意味着,双方都可以主动断开连接,当发送完断开连接的请求之后,都需要对方回复一个确认 信息,这样一来一回刚好就是四次挥手。
TCP就一定不丢包吗
- 比如现在我用微信给你发消息,假设这是两端之间的通信,并且为了保证消息的可靠性。
- 假设它们之间用的是TCP进行通信。
- 为了发送数据包,两端会先通过三次握手建立TCP连接。
- 一个数据包,从聊天框里发出消息,会从聊天软件所在的用户空间拷贝到内核空间的发送缓冲区,也 就是send buffer。
- 数据包进入到传输层,会被加上TCP报头,然后进入网络层会被加上IP报头。
- 接着进入到数据链路层,此时数据包加上MAC头,在这里数据包会先经过流控,也就是qdisc。
- 然后通过ringbuffer发到物理层网卡,数据就这样顺着网卡发送到了互联网上面。
- 然后数据就会经过N多个路由器和交换机之间的跳转,最后到达目标机器的网卡上面。
- 目标机器的网卡会通知DMA,将数据包的信息放到ringbuffer中,再触发一个硬中继给CPU。
- CPU触发软中继,让线程去ringbuffer中进行收包。
- 这样数据包就顺着物理层,数据链路层,网络层,传输层,最后从内核空间拷贝到用户空间的聊天软 件中。
- 抛开那些细节,这就是一个数据包从发送到接收的宏观过程。
- 在这个过程中,数据可能会出现丢包。
- 比如在建立连接时就会丢包,TCP会先通过三次握手建立连接。
- 在服务端第一次握手之后,会先建立半个连接,然后在进行第二次握手。
- 这个时候,需要暂存这些半连接,也就是半连接队列。
- 如果进行第三次握手,半连接就会升级为全连接,然后暂存到另外一个叫全连接队列的地方。
- 然后等待执行accept(饿克塞特)函数将全连接队列里面的信息取走。
- 如果全连接队列的长度满了,那新来的包就会被丢弃,
- 一旦发生全连接队列溢出,微信就会提示你”当前网络不可用,请检查你的网络设置”。
- 然后就是流量控制丢包,应用层能发送网络数据包的软件有那么多,如果所有的数据都不加以控制, 网卡肯定吃不消。
- 所以让数据按照规则排个队依次进行处理,也就是qdisc,流量控制机制。
- 排队得先有个队列,而队列有个长度,当流控队列长度不够大时,就会发生丢包。
- 当遇到这种情况时,可以尝试修改一下流控队列的长度。
- 还有接收缓冲区导致的丢包,当接收缓冲区满了,它的TCP接收窗口会变为0,就是零窗口。
- 并且会把数据包里面的win设置为0。
- 一般这种情况下,发送端就应该停止发送消息了,但是这个时候还有数据发送过来,就会发生丢包。
- 其它的丢包场景还有很多,比如网卡丢包,网络链路各个节点间的丢包,这些场景排查起来会涉及很 多命令,也比较复杂。
- 所以丢包是很常见的,几乎是不可避免的一件事情。
- 为了避免丢包,就要用TCP协议去做传输,毕竟它是个可靠的传输层协议。
- 建立了TCP连接的两端,发送端在发出数据之后,会等待接收端自动回复ACK包。
- ACK包的目的是为了告诉对方,自己确实收到了数据。
- 但是如果中间链路发生了丢包,发送端迟迟收不到确认ACK,于是就会进行重传。
- 来保证每个数据包都能确确实实的达到了接收端。
- 假如现在网断了,我还用微信给你发消息,微信还是会使用TCP不断的尝试重传数据。
- 如果重传期间网络恢复了,那数据就能正常发送过去。
- 如果多次重试直到超时还是失败,这个时候就是一个红色感叹号。
- 那微信用的就是TCP协议,丢包了还会重试,重试了还会出现红色感叹号。
- 那用TCP协议就一定不会丢包吗?
- TCP位于传输层,在它上面还有各种应用层协议,常见就是HTTP协议,RCP协议。
- TCP保证的可靠性是传输层的可靠性,TCP只保证数据从A机器的传输层可靠的发送到B机器的传输层。
- 至于数据到了接收端的传输层以后,能不能保证到应用层,TCP并不管。
- 假如我们现在输入一条消息,从聊天框发出去,如果走到了传输层的TCP发送缓冲区,不管中间有没 有丢包,最后通过重传,都能保证发送到了对方传输层的TCP接收缓冲区。
- 此时接收端回复一个ACK,发送端收到这个ACK以后,就会将自己发送缓冲区里面的消息给清空,到 这里TCP的任务就结束了。
- 但是微信的任务并没有结束,微信还要将数据从TCP的接收缓冲区里面读取出来。
- 如果在读取出来的这一刻,手机由于内存不足或者是其它原因,导致软件崩溃闪退了。
- 发送端将自己的消息已经发送给对方了,但接收端却并没有收到这条消息,于是消息就丢失了。
- 使用TCP协议却发生了丢包,虽然概率很小,但它就是发生了,合情合理。
- 如果登录到电脑版的微信之后,它能将最近的聊天记录,同步到电脑上面。
- 也就是说微信服务器可能记录了我们最近都发了哪些数据。
- 假设每条消息都有个ID,服务器和微信每次都能拿最新的消息ID进行对比。
- 就能够知道两端的消息是否一致,对于发送方只要定时跟服务端的内容对照一下。
- 就知道哪条消息没有发送成功,直接重新发送就好了。
- 如果接收方的聊天软件崩溃了,重启后跟服务器稍微通信一下,就知道少了哪条,把数据同步上来就 行了,所以不存在上面提到的丢包情况。
- 可以看出,TCP只是保证传输层的消息可靠性,并不能保证应用层的消息可靠性。
- 如果想要保证应用层的消息可靠性,需要应用层自己实现逻辑做保证。
TCP为什么面向字节流
- 应用层发送的数据报文,到了传输层以后,TCP会把数据报文当作字节流。
- TCP需要根据当前的网络环境来及时调整自己的发包数量,慢慢的发送数据,不断的加码,数据量越 发越多,直到出现丢包,这就是拥塞控制。
- 然后根据对方接收缓冲区的大小,决定现在应该发送多长的报文段,所以数据包报文在传输层被加上 了端口号,然后被封装成了段。
- 段来到了网络层,加上了IP地址,然后被封装成了包。
- 包来到了数据链路层,加上了MAC地址,然后被封装了帧。
- 帧最终到达物理层是比特,每个比特就是0和1。
- TCP需要保证的是每一个字节都能准确无误的传输给对方,所以说TCP是面向的字节流。
TCP/IP协议簇
UDP
是什么
- UDP面向无连接,面向数据报文,数据传输的时候没有确认机制,不需要反复握手建立连接,具体也 不知道接收方是否收到了数据,所以这是一种不可靠的通信协议。
- UDP在传输的过程中是数据报文。
用UDP就一定快吗
- 比如从A电脑的进程里面,发送一段数据到B电脑的进程里面。
- 可以使用TCP或者UDP协议进行通信。
- 对于TCP这样的可靠性协议,每次消息发送出去之后,都能明确知道对方有没有收到。
- 就像打电话一样,你问一句对方给你回一句,你就知道对方有没有在听。
- UDP就像是给邮政的信箱寄信一样,你寄出去的信,根本不知道对方有没有正常收到,丢了也是有可 能的。
- 可以使用Socket来选择使用TCP还是UDP。
- 如果使用字节流传输数据,那指的就是TCP协议。
- 如果使用数据报文传输数据,那指的就是UDP协议。
- 返回的FD是指Socket句柄,可以理解为Socket的身份证号码。
- 这个时候,根据协议的不同,还要执行一些操作。
- 如果一切都比较顺利的话,就开始传递消息。
- 但是如果不顺利,比如消息发到一半就丢包了,那TCP和UDP的处理方式就不一样了。
- UDP表示,没收到就没收,跟我没有关系。
- TCP的处理方式就截然相反了,没收到我绝对会给你补发。
- TCP为了保证数据的可靠性,首先就是重传机制。
- 它会给发出去的消息打上一个编号,也就是Sequence。
- 接收方收到后回复一个确认的ACK包。
- 发送方可以通过ACK的数值知道接收方收到了哪些Sequence的包。
- 如果长时间等不到对方的确认,TCP就会重新发送一次消息,这就是TCP的重传机制。
- 但是重传本身对性能的影响还是比较严重的,所以TCP就会尽量避免重传。
- 因为数据的发送方和接收方,处理数据的能力可能不一样,所以可以根据双方的能力,去调整发送的 数据量就好了,于是就有了发送窗口和接收窗口。
- TCP根据窗口的大小,去控制自己发送的数据量,来减少丢包的概率。
- 比如一开始窗口的大小为2,收到了一个数据包之后,窗口就变成了1,此时只能在收一个数据包。
- 当接收窗口变为0时,就会变为0窗口。
- 此时发送端停止发送数据,接收方接收到数据之后会不断的处理。
- 处理的能力也不是一成不变的,有时候处理的快就可以多收点数据,处理的慢了就希望对方能少发点 数据。
- 像这种根据自身的能力,不断调整窗口的机制,就是滑动窗口机制。
- 通过滑动窗口机制,TCP实现了流量的控制。
- 但是这还不够,有时候丢包,并不是因为发送方和接收方的处理能力导致的,而是跟网络环境有关。
- TCP需要根据网络环境来及时调整自己的发包数量,慢慢的发送数据,不断的加码,数据量越发越多, 直到出现丢包,这就是拥塞控制。
- 所以流量控制针对的是单个连接数据处理能力的控制,而拥塞控制针对的是整个网络环境数据处理能 力的控制。
- 流量控制和拥塞控制都是在降低重传的概率,但是重传这个事情就是无法避免的。
- 如果发送一个超大的数据包时,这个数据包丢了,那就得重传同样大的数据包。
- 但是如果把它分成一小段一小段,那就算真丢了,也只需要重传那一小段就可以了。
- 这就是TCP的分段机制,这个一小段的长度,在传输层叫MSS。
- 数据包长度大于MSS,就会分成N个小于等于MSS的包。
- 如果在网络层,数据包还大于MTU,那还会继续分包。
- 一般情况下,MSS等于MTU减去40个Byte。
- 所以TCP分段以后,到了IP层大概率就不会再继续分片了。
- 既然数据包会被分段,链路有这么复杂,还会丢包,所以数据包肯定就会发生乱序。
- 比如发了送数据包1号2号3号,结果3号数据包走了其它的网络路径,3号数据包先到,1号和2号 数据包后到,于是数据包就成了312。
- 这一点TCP也考虑到了,依靠数据包的Sequence,接收方就能知道数据包的先后顺序。
- 后发的数据包先到,就把它放到乱序队列里面。
- 等所有的数据包都到齐了,重新整理好数据包的顺序后再给到用户。
- 这也就是乱序重排机制。
- 但是网络环境链路是很复杂的,不管怎样都会出现丢包。
- 这个时候就有了UDP,因为没有TCP这些复杂的可靠性机制,所以它很快。
- 但是也有用了UDP却比TCP慢的情况。
- 现实中,也没有人直接拿UDP放到生产环境中去做项目。
- UDP的存在,本质就是内核提供的一个最小网络传输功能。
- 很多时候,虽然用了UDP,但是都怕它的丢包问题,所以都会在UDP的基础上做不同程度的应用层可 靠性保证。
- 比如QUIC协议,也就是HTTP3.0,都会在UDP的基础上做重传的逻辑,实现一套类似于TCP那样的可 靠性机制。
- 教科书上最爱说UDP适合用于音频视频传输,因为这些场景允许丢包。
- 但其实也不是什么包都能丢的,比如一些比较重要的关键帧,该重传还是得重传。
- 除此之外,还有一些乱序处理机制。
- 所以说虽然选择了使用UDP,但一般还是会在应用层上面,做一些重传机制的。
- 比如现在需要传一个特别大的数据包,在TCP里面,它的内部会根据MSS的大小分段。
- 这个时候进入到IP层后,每个包的大小都不会超过MTU,因此IP层一般不会再进行分片。
- 这个时候发生丢包了,只需要重传每个MSS分段就够了。
- 但是对于UDP,它本身并不会进行分段,如果数据过大,到了IP层就会进行分片。
- 此时发生丢包的话,再次重传就会重传整个数据包。
- 对于上面的情况,使用UDP就会比TCP慢。
- 比如早期基于UDP的NFS协议,就有这个问题。
- 当然解决起来也不复杂,这里的关键点在于是否实现了数据分段机制。
- 使用UDP的应用层如果也实现了分段机制的话,就不会出现上面的问题了。
UDP为什么面向数据报文
- 应用层发送的数据报文,到了传输层以后,UDP不会对数据报文进行分段。
- 所以不管应用层发送的数据包有多大,UDP都会一次发送一个数据报文。
- 数据报文来到了网络层,加上了IP地址,然后被封装成了包。
- 包来到了数据链路层,加上了MAC地址,然后被封装了帧。
- 帧最终到达物理层是比特,每个比特就是0和1。
- UDP需要保证的是每一个数据报文都能准确无误的传输给对方,所以说UDP是面向的数据报文。
- 不管是TCP还是UDP最终都是比特。
WebSocket/Socket
为什么有了HTTP还要有WebSocket
- 从HTTP协议的角度来看,就是点了一下网页上的某个按钮,前端发起一个HTTP的请求,网站返回一 次HTTP的响应。
- 这种由客户端主动请求,服务器响应的方式,满足了大部分网页的功能场景。
- 这种情况下,服务器不会主动向客户端发送一次消息。
- 然后在浏览网页的时候,突然弹出了一个小广告,点开这个小广告一看是某个传奇页游。
- 然后选了一个角色进入页面,全程没有一次动过鼠标,服务器自动将怪物的移动数据和攻击数据源源 不断的发给你。
- 像这种看起来服务器主动发送消息给客户端的场景,怎样才能在用户不做任何操作的情况下,网页能 收到消息并发生变更呢?
- 最常见的解决方案,就是在网页的前端代码里面,定时发送HTTP的请求到服务器,服务器收到后响应 消息。
- 这是一种伪服务器推送的形式,其实也不是服务器主动发送消息到客户端,而是客户端不断请求服务 器,只是用户无感知而已。
- 用这种方式的场景也有很多,最常见的就是扫码登录。
- 比如有些网站扫码登录,二维码出现之后,前端网页不知道用户扫没扫,于是不断的去向后端服务器 询问,看看有没有人扫过。而且是大概1到2秒的时间间隔,去不断的发出请求。
- 这样可以保证用户在扫完码之后,1到2秒就能得到反馈,不至于等的太久,这也就是HTTP定时轮询。
- 但是这样做有两个比较明显的问题。
- 第一个问题是不断的发送HTTP请求,虽然比较小,但是其实也消耗带宽,同时还会增加下游服务器的 负担。
- 第二个问题是在最快的情况下,用户在扫码之后需要等待1到2秒,才能触发下一次的HTTP请求,然 后在跳转页面,用户会感觉到明显的卡顿。
- 所以后来就有了长轮询。
- HTTP的请求发出后,会给服务器留一定的时间做响应,比如3秒,规定的时间内如果没有返回就超时。
- 如果HTTP请求将超时设置的很大,比如30秒,在这30秒内,只要服务器收到了扫码的请求,就立马 给客户端返回网页。如果超时了,那就立马发送下一次请求。这样就减少了HTTP请求的个数。
- 并且由于大部分情况下,用户都会在某个30秒的区间内,做扫码操作,所以响应也是及时的。
- 像这种发起一个HTTP请求,在较长时间内等待服务器响应的机制就是长轮询机制。
- 常用的消息队列RocketMQ,消费者获取数据时也用到了长轮询。
- 像这种在用户无感知的情况下,服务器将数据推送给浏览器的技术就是服务器推送技术。
- 轮询机制本质上还是客户端主动获取数据,对于扫码登录这样的简单场景还能用用。
- 但是如果是网页游戏呢?游戏一般会有大量的数据,从服务器主动推送到客户端,这就得用到 WebSocket。
- TCP连接的两端,同一时间内双方都可以主动向对方发送数据,这就是所谓的全双工。
- 而现在广泛使用的HTTP1.1也是基于TCP协议的,同一时间内客户端和服务器只能有一方发送数据, 这就是所谓的半双工。
- 全双工的TCP被HTTP用成了半双工,这是因为在HTTP协议被设计之初,考虑的是看看网页文本的场 景,能做到客户端发起请求,再由服务器响应就够了。
- 根本就没有考虑到网页游戏这种客户端和服务器之间,都需要互相主动发送大量数据的场景。
- 所以为了支持这样的场景,需要一个基于TCP的新协议,也就是新的应用层协议WebSocket。
- 网页上的图文用的就是HTTP协议,网页游戏用的就是WebSocket协议。
- 为了兼容HTTP协议和WebSocket协议,浏览器在建立连接之后,都使用HTTP先进行一次通信。
- 如果此时是普通的HTTP请求,那就继续用普通的HTTP协议进行交互。
- 如果想建立WebSocket连接,就会在HTTP请求里,带上一些特殊的请求头。
- 其中Connection:Upgrade表明浏览器想升级协议。
- 从Upgrade:WebSocket可以看出,客户端想升级成WebSocket协议。
- 同时会带上一段随机生成的BASE64码,也就是sec-websocket-key发给服务器。
- 如果服务器正好支持,并且升级成WebSocket协议,就会走WebSocket的握手流程。
- 同时用客户端生成的BASE64码用公开算法变成另一段字符串,放在HTTP响应里的sec-ws-accept里面, 同时带上101状态码返回给浏览器。
- 101状态码指的就是协议切换,然后浏览器也用同样的公开算法将BASE64码转成另一段字符串。
- 如果这段字符串跟服务器传回来的字符串一致,那验证就通过。
- WebSocket和HTTP都是基于TCP的协议,经历了TCP的三次握手之后,利用HTTP协议升级为WebSocket 协议。
- 所以WebSocket只有在建立连接时才会用到HTTP协议,升级完成之后,就跟HTTP协议没有任何关系。
- 后续双方就使用WebSocket的数据格式,进行通信。
- WebSocket的格式也是消息头加上消息体的格式。
Socket
能干什么
- 通过Socket,可以与某台机子建立连接,如果想要在两端之间传送一份数据,那么需要两端各自执行 Socket方法,得到FD句柄。
- 对于服务端需要依次执行bind,listen,accept方法。
- 然后坐等客户端的连接请求执行connect方法,向服务端发起建立连接的请求。
- 连接建立完成以后,客户端可以执行send方法发送消息,服务端可以执行recv方法接受消息。
- 反过来,服务端也可以执行send方法发送消息,客户端执行recv方法接收消息。
是什么
- 在操作系统内核空间里,实现网络传输功能的结构是sock,基于不同的协议和应用场景,会被泛化为 各种类型的sock,它们结合硬件,共同实现了网络传输功能。
- 为了将这部分功能,暴露给用户空间的应用程序使用,于是引入了Socket层,同时将sock嵌入到文件 系统的框架里,sock就变成了一个特殊的文件,用户就可以在用户空间使用文件句柄,也就是socket _fd 来操作内核sock的网络传输能力。
- socket_fd是个int类型的数字,可以把它理解为一套用于连接的数字。
- 以最常用的TCP协议举个列子,可以将它分为两个阶段,分别是建立连接和数据传输。
- 在客户端,代码执行socket提供的connect方法,传入sock_fd和IP端口时,内核会通过sock_fd句柄, 找到对应的文件,再根据文件里面的信息,找到内核的sock结构,通过这个sock结构主动发起三次握 手之后,连接就算准备好了,然后就可以开始传输数据了。
- 为了实现发送和接收数据的功能,sock结构体里面带了一个发送缓冲区和一个接收缓冲区,这里的缓 冲区就是一个链表,上面挂着一个个准备要发送或者接收的数据。
- 当应用执行send方法发送数据时,同样也会通过sock_fd句柄找到对应的文件,根据文件指向的sock 结构,找到这个sock结构里面带的发送缓冲区,将数据放到发送缓冲区,然后结束流程。
- 内核看心情来决定什么时候将这份数据发送出去,接收数据流程也类似,当数据送到Linux内核后,数 据不是立马给到应用程序的,而是先放在接收缓冲区中,等待应用程序候执行recv方法来获取数据。
- 服务端listen的时候,那么多数据包发到一个listen socket上面,服务端这个时候需要区分多个客户端。
- 客户端发来的数据包上面会有源IP地址和端口,以及目标IP地址和端口,这四个元素构成一个四元组, 可以用于唯一标记一个客户端。
- 服务端会创建一个新的内核sock,并用四元组生成一个hash key,将它放入到一个hash表中。
- 下次再有消息过来的时候,通过消息自带的四元组生成的hash key,再到这个hash表里面重新取出对 应的sock就可以了,那么服务端也就是通过四元组来区分多个客户端的。
单工/半双工/全双工
- 单工只支持数据在一个方向上进行传输。
- 半双工允许数据在两个方向上进行传输,但是某一时刻只允许数据在一个信道上进行单向传输。
- 全双工有两个信道,允许同时进行双向传输,要求双方都有独立的接收能力和发送能力。
浏览器访问一个网站地址发生了什么
- 在浏览器中输入一个网址。
- 需要DNS服务器解析域名,把URL地址解析为IP地址。
- 其实DNS就是一个数据库,这个数据库里面记录着很多的URL和对应的IP地址,这样就可以根据DNS 查找对应的IP地址。
- 有了IP地址就可以在互联网里找到指定的服务器。
- 但是在正式给服务器发送数据之前还是得建立TCP连接。
- 建立TCP连接就是要在发送数据之前建立通道。
- 客户端和服务器之间建立好通道就可以在这个通道里面发送数据。
- 大家都在这个通道里面发送数据,这样数据就不容易发生错乱,于是就有了建立通道前的三次握手。
- 客户端发送SYN数据包来表示请求连接。
- 服务器响应SYN和Ack数据包来表示同意建立连接。
- 客户端再发送Ack数据包来表示连接成功。
- 当和服务器建立连接以后,浏览器会发送HTTP请求报文给服务器。
- 报文的格式由请求行,请求头部,空行和请求数据组成。
- 请求行里面有请求的方法,请求的地址和HTTP协议的版本。
- 请求的头部就是一些关于浏览器的信息,由键/值对组成,一行一对。
- 直到遇到空行就表示下面没有请求的头部了。
- 最后就是请求的数据,毕竟浏览器需要什么样的数据,需要以什么样的形式获取数据都是需要告诉给 服务器的,只有这样服务器才知道浏览器想要获取什么样的信息。
- 当服务器收到HTTP的请求报文以后,服务器就会处理这些请求报文,并且做出响应。
- 响应报文和请求报文非常相似,报文的格式由状态行,响应头部,空行和响应数据组成。
- 状态行就是404,200,500那些三位数字。
- 响应头部由键/值对组成,一行一对。
- 直到遇到空行就表示下面没有响应的头部了。
- 最后就是响应的数据。
- 浏览器在接受到服务器的响应以后,页面就会开始进行渲染。
- 也就是开始解析接受到的HTML,CSS和JS等文件。
- 有了这些前端文件以后,用户就可以在前端看到页面的内容。
DDoS
是什么
- DoS攻击是占用网络服务的资源让服务器应接不暇,从而拒绝正常业务流量的一种网络攻击方式。
- DDoS攻击是DoS攻击的分布式版本,因为单台设备的攻击能力有限,治疗起来也比较容易,但是当成 千上万台设备组成一个网络同时对目标发起Dos攻击时,一般的服务器是扛不住的。
- 发起攻击的网络一般称为僵尸网络,每个僵尸可以是一台个人电脑也可以是一台服务器,甚至可以是 一部手机。
- 为了得到僵尸网络不法分子会利用木马,蠕虫,后门等恶意程序感染大量的设备,获得僵尸网络。
- 互联网中一次网络访问的过程简化来看就是客户端通过网络线路向远程服务器请求内容,服务器按照 客户端的需求进行查询或者计算出相应的数据,再通过网络线路返回给客户端。
- 现代互联网中的数据流转,依赖的是以TCP/IP协议为核心的通信系统。
- TCP/IP的参考模型是一个4层结构(应用层,传输层,互联网层,子网层)。
- 平时写信的时候大家一般都会遵从约定的格式,比如先写对方的称呼,加个冒号换行,再写正文,结 尾写上至此敬礼,最后写上署名和日期。这类似于四层结构中的应用层,规定了一些数据内容的协议 规则。
- 写完信以后做一个标记,比如沾上一根鸡毛或者盖上一个红戳。对方会根据这些标记决定如何回复, 要不要加急,要不要确认一下对方的身份。这类似于四层结构中的传输层规定了数据的传输方式。这 一层中的TCP协议为了保证通信的可靠性,需要先经历3次握手再发起数据的传输。
- 对于一次可靠的通信过程,事先的沟通是很有必要的。在正式写信说正事之前,需要先发送三封能确 定彼此的信建立一种可靠的连接。
- 第一次,在TCP协议的信件上有几个关键的字段,发起TCP连接时我方先把SYN设置为1,Ack设置 为0,在选择一个顺序号x,然后发送出去。
- 第二次,对方收到之后回复一封信,把SYN设置为1,Ack设置为1,确认号设置为x+1,同时也选择 一个顺序号y。
- 第三次,我方收到回信之后,把SYN设置为0,Ack设置为1,确认号设置为y+1,顺序号设置为x+1, 再次发送出去。
- 这样一个TCP的连接就建立起来了,接下来就可以发送用户的数据了,因为有3次握手的存在,通信 会更加的可靠。
- UDP协议就没有这么麻烦,不需要反复握手建立连接,直接把数据投递出去,也不管对方有没有收到, 所以这是一种不可靠的协议。
- 用来装信件(数据)的信封,类似于4层结构中的网络层,主要规定了通信双方的地址编码规则,这一层 采用的是IP协议,所以经常会听到所谓的“设备IP地址”。
- 而一封信的投递最终依靠的是邮局,邮局把信件打包装车后,根据收件地址把信件投递到目的地,这 一层对应着4层结构中的子网层,是信息传递的物理载体,比如以太网,卫星网。
- 这4层结构从应用层到子网层,数据按照不同的协议被不断的打包,到达目的地后刚好是相反的拆包 过程,最终被目标接收。
- 所以其中最为核心的是互联网层中的IP协议,只要是按照IP协议封装的数据都可以被发送,不论是以 太网,卫星网还是其它物理实现的子网。
- 只要按照信封上的格式写好收发地址,装入的信件就可以被投递到目的地,不论是走陆运,空运还是 海运,IP协议让不同的子网络被互连了起来。
- 所以从这个通信的过程中就能发现,从数据离开到最终到达这一路,几乎每个地方都有被DDoS攻击 的机会。
- 比如霸占服务器的网络带宽资源,只需要向一台服务器发送大量的IP协议数据包,就可以慢慢的消耗 掉对方的网络带宽。
- ping工具就可以发起一次攻击,ping产生的是ICMP协议包,ICMP是IP协议中用来进行差错控制的一 个补充,本质上还是一个IP包,这种攻击方式也被称为ICMP洪水。这种攻击手段类似于不断的给某 个人投递信件,写了什么不重要,重要的是让非常多的邮递员在对方家门口排起了长队,从而打断了 正常的信件收发。
- 当然也可以发送传输层的UDP协议包,发起一次UDP洪水攻击,这里会有一个问题,那就是会暴露攻 击设备的IP地址,而被对方禁封,所以攻击者一般都会通过伪造IP地址隐藏自己。
- 比如张三给李四写信,却把发件地址写成了王五,这样李四也就只能迁怒于王五,或者干脆写一个不 存在的地址,让李四无处泄愤。
- 出于隐藏自己的这个目的,后面又发明出了一种更有趣的攻击方式,叫反射攻击。既然可以伪造IP, 那么就不拘泥于伪造发件人的身份,同样也可以伪造收件人的身份,达到“借刀杀人”的效果。
- 所以可以把信封上的发件地址改为攻击目标的IP地址,然后把收件地址设置为互联网上大量的第三方 机器,从而把数据发送到这些第三方机器上面,这些机器在接收到数据之后,回复的数据就会涌入发 件地址指向的攻击目标,这些第三方机器也被称为”反射器”。这有点像把别人的电话号码挂在网站上, 然后机主被不明真相的推销员给呼死。
- 反射攻击很难追踪来源,但是在此基础之上又发明了一种把攻击流量放大以达到更强攻击效果的攻击 手段,叫做放大攻击。
- DNS服务器是一种用来把域名解析为IP地址的设备,同时DNS查询通常使用UDP这个不用验证来源 的传输协议,所以DNS服务器就是一个很好的放大器,一次DNS的查询请求返回的数据往往大于请求 的数据,这里有一个”带宽放大因子”BAF的概念,在DNS的查询中,一般60个字节的请求数据可以获 得3000个字节的返回数据,那么BAF=3000/60=50,从而产生50倍的放大效果。这样可以让攻击者不 断的去对DNS服务器发起查询请求,并把源地址伪造为攻击目标的IP地址,这样的反射攻击就会产生 50倍的流量放大效果。
- 除了对目标的带宽资源进行霸占以达到DDoS攻击效果以外,因为TCP协议中有连接的概念,所以还 可以攻击服务器的连接资源,服务器每次和客户端建立一个TCP连接时,需要经历三次握手,然后把 连接信息放入连接表中进行维护,而连接表的大小是有限的,所以可以让发起攻击的设备直接发起大 量的TCP连接,从而占满服务器的这个连接表,导致无法响应后续的TCP连接请求,从而达到DDoS 攻击的效果。这种攻击方式也称之为TCP洪水。
- 因为有三次握手的存在,所以TCP洪水无法通过伪造IP地址隐藏自己,在建立连接时,如果在第一次 握手中伪造了IP地址,那么服务器向客户端发送数据的第二次握手就无法到达。相当于你给别人写了 一封伪造发件地址的信,那么你是不可能收到回信的,因为连接无法建立。但是可以在建立连接的3 次握手本身上做文章,比如只发送SYN不进行后续的回答,进行”虚晃一枪”的SYN洪水,这样做的好 处是如果不回答攻击目标的SYN和Ack数据,那么考虑到可能是网络环境的问题,TCP协议中有重传 的机制,对方会多次尝试发送SYN和Ack直到超时,比如重试10次,那这就相当于每攻击目标一次, 对方就会回击10次。所以SYN洪水攻击一般都会伪造IP,要么是一个不存在的IP,或者是某个真实倒 霉蛋的IP。
- 在TCP协议中也可以通过反射发起攻击,向各个反射器发送SYN,并把发件地址伪造成攻击目标的IP, 这样大量的SYN和Ack数据,就会从各个反射器上涌入攻击目标,当然这种攻击方式无法在目标上建 立连接,所以还是在攻击网路带宽。
- 在TCP协议中,一般用4次挥手结束连接,但为了防止出现异常,一方可以发送一个RST数据强制切 断连接,这样可以让攻击设备不断的尝试伪造各种IP地址,并发送RST数据进行”盲打”,一旦IP和其 它某个正常用户的匹配上,就能切断正常用户和服务器之间的连接。这种攻击方式更针对用户,比如 在一场网络游戏对战中,在获悉对手的IP地址之后,就可以不断的切断对方的游戏设备和服务器的连 接,以干扰正常游戏。
- 不论是利用IP,UDP还是TCP协议攻击,针对的都是网络和连接资源,还有一种针对服务器内部资 源的攻击方式,消耗目标的IO。
- 一般的用户在网上冲浪的时候接触的都是应用层中像HTTP这样的协议,所以可以对一个站点发送HTTP 洪水攻击,比如利用站点的搜索功能不断的生成大量的关键词送入查询地址,因为HTTP请求作为用户 直接发起的涉及具体业务的请求,服务器在收到请求后需要进行像数据库查询这样的IO操作,所以这 样的攻击手法会对目标产生更大的消耗。当然HTTP洪水攻击有个问题,那就是不能伪造IP地址,因 为HTTP协议是基于TCP协议的,需要经历三次握手的过程。但是可以借助网络代理主机,得到不同的 真实IP发起攻击。
如何防止
- 可以通过CDN进行CDN稀释,把一些相对静态的资源作为缓存分发给各个CDN节点,用户在请求的 时候从最近的节点返回,从而在一定程度上能缓解DDoS攻击。
- 面对TCP协议的SYN洪水攻击,客户端发起的SYN先经过流量清洗设备,由清洗设备回复SYN和Ack, 如果对方应答了,那说明是正常的流量,清洗设备再把本次连接交给后方的服务器进行正常的通信, 如果对方不应答,清洗设备该重试就进行重试,超时后就断开连接。
- 可以进行分布式集群,如果某台服务器因为DDoS攻击挂了,还有其它的服务器暂时能用。
- 可以设置IP黑名单,但是不一定有效,因为大部分的IP都是虚拟的IP。
- 可以通过系统防火墙或者ESC安全组禁止非业务的端口。
- 可以更换源站的业务公网IP地址,但是不一定有效。
串口通信协议
- 常见的串口通信协议有RS232,RS485,RS422,这些串口通信协议只是定义了部分的物理层。
- 对于数据链路层基本上没有涉及,所以串口协议非常的灵活,也没有统一的标准,可以根据自己的需 求来定义。
- 串口通信常见的数据格式有起始位1bit,数据位7个bit,奇偶校验位1个bit,停止位1个bit。
- 还有一些比较常用的数据帧形式,比如帧起始,命令域,地址域,数据域,校验域,帧结束。
- 这些数据帧大部分都是用0x开头的十六进制表示的。
- 帧起始作为起始位。
- 命令域,地址域和数据域作为数据位。
- 校验域就是奇偶校验位。
- 帧结束就是停止位。
- 帧起始一般用两个向左的英文破折号表示。
- 命令域比较灵活,可以用0x10表示上行,0x20表示下行,0x30表示重传,0x40表示应答。
- 地址域可以用0x50表示基地址,每一个从节点的偏移地址作为上一个从节点的偏移地址在给它加上 0x50。
- 数据域也比较灵活,比如用1个bit表示硬件的版本号,1个bit表示软件的版本号,5个bit表示特定 的数据。
- 校验域一般用CRC进行校验。
- 帧结束一般用两个向右的英文破折号表示。
- 所以根据串口通信协议的这些特点和规则,就可以自己定义一个串口的通信协议。