目前造车热的车联网,区块链,物联网,其实他们所追求的核心都是想达到万物互联.但是每个测重点可能不太一样.车联网以车切入万物互联.区块链可能更多的关注溯源可信,真正让万物互联的可能就是各个账本.物联网更不用说了,智能家居典型代表.其实他们最最核心的东西就是我们今天要讲的网络.万物互联靠什么互联,最基本的设施就是网络.
什么是网络呢,有人能解释下吗
网络是由若干节点和连接这些节点的链路构成,表示诸多对象及其相互联系。(百度的)
网络有四要素
1、通信线路和通信设备;
2、有独立功能的计算机;
3、网络软件支持;
4、实现数据通信与资源共享。
结合目前我们的职业和后期可能面临研究的方向,着重讲下第四条,实现数据通信与网络资源共享
至于其他的交给运营商,运维等等他们去忙吧
设备之间通信其实就和人一样,我找你沟通凡尔赛,肯定得先找到你本人,然后用都能听的懂的语言来聊.古时候对牛弹琴就是一个很失败的通信方案.
找你本人,其实就是目前计算机网络里的MAC地址和IP地址,ip好理解,mac地址其实可以理解为接入以太网网卡地址,以太网要求接入必须要有网卡接口,从一个网卡发送另外一个网卡的数据包接收和发送地址.计算机与网络设备要相互通信,双方就必须基于相同的方法。比如,如何探测到通信目标、由哪一边先发起通信、使用哪种语言进行通信、怎样结束通信等规则都需要事先确定。不同的硬件、操作系统之间的通信,所有的这一切都需要一种规则。而我们就把这种规则称为协议(protocol).常见的TCP、UDP.当然还有其他协议,甚至你可以自定义协议.比如我看到网上有移动端做APM可以分性能监控和数据上报2个模块,其中上报组件为了方便可扩展,并具有动态下发上报策略,同时还要高效就使用了自定义报文协议.
TCP、UDP 协议呢,也能讲很久,时间有限,这里我们着重讲和我们相关的TCP协议
TCP/IP 是协议簇,比如:TCP、UDP、IP、FTP、HTTP、ICMP、SMTP 等都属于 TCP/IP 簇内的协议。TCP/IP协议可以划分为四层
链路层:负责封装和解封装 IP 报文,发送和接受 ARP/RARP 报文等。
网络层:负责路由以及把分组报文发送给目标网络或主机。
传输层:负责对报文进行分组和重组,并以 TCP 或 UDP 协议格式封装报文。
应用层:负责向用户提供应用程序,比如HTTP、FTP、Telnet、DNS、SMTP等。
正常一条网络请求需要经过的流程是:
1.DNS 解析。请求 DNS 服务器,获取域名对应的 IP 地址
2.与服务器建立连接。包括 TCP 三次握手,安全协议同步流程
3.连接建立完成,发送、接收数据,解码数据
先说说DNS解析,为啥要DNS解析,因为设备太多,ip太难记,发明了DNS,DNS是一个和ip相互映射的分布式数据库.
以浏览器举例,一般会浏览器本身找DNS,没有操作系统找DNS,没有会找本地DNS服务器,一般在城市某个地方,如果还没有就是13台根DNS服务器找.根DNS服务器会返回所查询域的主域名服务器的地址(.net),本地DNS服务器使用该IP信息联系负责.net域的这台服务器。这台负责.net域的服务器收到请求后,会返回.net域的下一级DNS服务器地址(blog.csdn.net)给本地DNS服务器。以此类推,直至找到.每一层都有缓存,但为了域名解析的实时性。每一层缓存都设有过期时间.
那么问题来了这么复杂的流程,加上缓存,就会带来一些问题.比如:
缓存时间设置过长,域名更新不及时。设置时间短,大量 DNS 解析请求影响请求毒素
域名劫持。容易被中间人攻击,或者运营商劫持。把域名解析道第三方 IP 地址,据统计劫持率高达 7%
DNS 解析过程不受控制,无法保证最快的解析速度
一次请求只可以借此一个域名
那么我们的研究任务来了
如何防DNS劫持或者加快速度
为了解决上述问题,就有了 HTTPDNS。原理就是代替系统的 DNS 解析工作,解决上述问题。
域名解析与请求分离,所有请求都直接使用 IP 地址,无需 DNS 解析,App 定时请求 HTTPDNS 服务器更新 IP 地址即可
通过签名等方式,保证 HTTPDNS 请求的安全,避免被劫持
DNS 解析由自己控制。可以保证根据用户所在地返回就近的 IP 地址。或根据客户端测速结果使用最快的 IP
一次请求可以解析多个域名
对于 DNS 解析的情况,业界主流做法就是 HTTPDNS 或者内置 Server IP 列表。客户端直接访问 HTTPDNS 接口,获取业务在域名配置系统上配置的访问延迟最优的 IP,获取到 IP 后就直接往此 IP 发送业务协议请求,不再需要本地 DNS 服务器进行解析,从根本上解决了劫持问题。同时可以降低网络延迟,提高连接的成功率。
建立的 Server IP 列表,是在本地缓存一个 IP 映射表,可以在 App 启动时请求接口下发更新。访问其他的服务的时候根据映射拿到 IP 再发出请求。
绝大多数的 App 的第一步都是 DNS 解析,解析请求回根据当时的网络情况不同而不同,各平台的 DNS 缓存策略存在差异,因此对于移动 App 网络性能会产生影响。App 网络情况跟很多因素都相关。但是 DNS 是第一步也是最重要的一环。
1.降低 DNS 请求带来的延迟 客户端 App 请求第一步是 DNS 解析。但是由于 Cache 的存在,使得大部分的解析请求都不会产生任何延迟。各平台都有自己的 Cache 过期策略。像 iOS 系统一般都是 24h 后过期。还有就是从飞行模式切换回来、开关机、重置网络设置等都会导致 DNS Cache 的清除。所以一般情况用户在第二天打开你的 App 都会经历一次完整的 DNS 解析请求。网络情况差的时候会明显的请求总耗时增加。如果可以直接跳过 DNS 解析这一步,就可以提高网络性能了。
2.预防 NDS 劫持 DNS 劫持指的是改变 DNS请求返回的结果,将目的域名对应的 IP 指向另一个地址。一般有两种方式,一种是通过病毒的方式改变本机配置的 DNS 服务器地址,二是通过攻击正常的 DNS 服务器而改变其行为。不管何种方式都会影响 App 的业务请求,如果遇到恶意的攻击还会衍生出各种安全问题。客户端自己做 DNS 到 IP 地址的映射就绕过了向 DNS 服务器请求而可能被遭到攻击的可能,让劫持者无从下手
3.服务器动态部署 DNS 映射实际上是模拟了 DNS 请求的解析行为。如果客户端将自己的位置信息(例如ip地址、国家码等)上传给服务器,服务器就可以根据位置信息就近推荐合适的 Server IP 地址。从而减小了整体网络请求延迟、实现了动态部署
如何设计自己的 DNS 映射机制?这个可以研究,时间有限先不讲了.
三次握手问题,同样带来请求时间加长
不要每次请求都重新建立连接,复用连接或一直使用同一条连接(长连接)
对于我们来说主要研究的应该是复用连接,长链接一般除了客服什么都暂时用不到
HTTP 协议里有个 keep-alive,HTTP1.1 默认开启,一定程度上缓解了每次请求都需要进行 TCP 三次握手建立连接的耗时。原理是请求完成后不立即释放连接,而是放入连接池中。若此时有另一个请求要发出,如果请求的端口和域名在复用池里面有一致的,那么就直接拿出连接池中的连接进行发送和接收数据,少了建立连接的耗时。
实际上,现在无论是客户端还是浏览器都默认开启了 keep-alive,对同个域名不会再有每发一个请求就进行一次建连的情况,纯短连接已经不存在了。但是有问题,就是这个 keep-alive 的短连接一次只能发送接收一个请求,在上一个请求处理完成之前。无法接受新的请求。若同时发起多个请求,就有两种情况:
若串行发送请求,可以一直复用一个连接,但速度很慢,每个请求都需要等待上个请求完成再进行发送
若并行发送请求,那么首次每个请求都要进行 TCP 三次握手建立新的连接,虽然第二次可以复用连接池里面的这堆连接,但若连接池里面保留的过多,对服务端资源产生交大浪费,若限制了保持的连接数,并行请求超出的连接仍每次需要建立连接。对于这个问题新一代的 HTTP2.0 提出了多路复用解决方案。
HTTP2 的多路复用机制一样是复用连接。但它复用的这条连接支持同时处理多条请求,所有请求都可以在这条连接上进行,也就是解决了上面说的并发请求需要建立多条连接带来的问题。
HTTP2 这里的多路复用协议解决了这些问题,它把在连接里传输的数据都封装成一个个 stream,每个 stream 都有标识,stream 的发送和接收可以是乱序的,不依赖顺序,也就不会有阻塞的问题,接收端可以根据 stream 的标识去区分属于哪个请求,再进行数据拼接,得到最终数据。
解释下多路复用这个词,多路可以认为是多个连接,多个操作,复用就是 复用一条连接或一个线程。HTTP2 这里是连接的多路复用,网络相关的还有一个 I/O 的多路复用(select/epoll),指通过事件驱动的方式让多个网络请求返回的数据在同一条线程里完成读写。
客户端来说,iOS9 以上 NSURLSession 原生支持 HTTP2,只要服务端也支持就可以直接使用,Android 的 okhttp3 以上也支持了 HTTP2,国内一些大型 APP 会自建网络层,支持 HTTP2 的多路复用,避免系统的限制以及根据自身业务需要增加一些特性,例如微信的开源网络库 mars,做到一条长连接处理微信上的大部分请求,多路复用的特性上基本跟 HTTP2 一致。
HTTP2 的多路复用看起来是完美的解决方案,但还有个问题,就是队头阻塞,这是受限于 TCP 协议,TCP 协议为了保证数据的可靠性,若传输过程中一个 TCP 包丢失,会等待这个包重传后,才会处理后续的包。HTTP2的多路复用让所有请求都在同一条连接进行,中间有一个包丢失,就会阻塞等待重传,所有请求也就被阻塞了。
对于这个问题不改变 TCP 协议就无法优化,但 TCP 协议依赖操作系统实现以及部分硬件的定制,改进缓慢,于是 GOOGLE 提出 QUIC 协议,相当于在 UDP 协议之上再定义一套可靠传输协议,解决 TCP 的一些缺陷,包括队头阻塞。具体解决原理网上资料较多,可以看看。
QUIC 处于起步阶段,少有客户端接入,QUIC 协议相对于 HTTP2 最大的优势是对TCP队头阻塞的解决,其他的像安全握手 0RTT / 证书压缩等优化 TLS1.3 已跟进,可以用于 HTTP2,并不是独有特性。TCP 队头阻塞在 HTTP2 上对性能的影响有多大,在速度上 QUIC 能带来多大提升待研究。
第三步连接完成数据传输过程
这个过程要讲内容就比较多了.先讲讲最主要的点,网络速度.
为了提升用户体验,我们最好可以压缩数据,减小传输数据的大小
传输数据大小问题。数据对请求速度的影响分两方面,一是压缩率,二是解压序列化反序列化的速度。目前最流行的两种数据格式是 json 和 protobuf(Google 提供)。json 是字符串,protobuf 是二进制。即使采用各种压缩算法压缩后,protobuf 仍会比 json 小。protobuf 在数据量和序列化速度上均占优势。IOS里的KVStorage,集成微信的MMKV采用的就是这种存储方式.大家可以底下研究下.
除了传输数据的 body 大小,每个 HTTP 协议头的数据也不可忽视,HTTP2 里对 HTTP 协议头也进行了压缩,HTTP 头大多是重复数据,固定的字段如 method 可以用静态字典,不固定但多个请求重复的字段例如 cookie 用动态字典,可以打到非常高的压缩率.
说到速度就要说到一个安全了.因为为了安全可能会牺牲一部分速度了.
标准安全协议 TLS 保证了网络传输的安全,前身是 SSL,不断在演进。我们日常使用的 HTTPS 就是 HTTP 协议加上 TLS 安全协议。大家底下可以了解下TLS 安全协议的设计理念.
这里我们主要讲讲在这个之外的我们约定的前后端数据加解密的.
以前我们用的基本都是RSA的前后端加密,国外设计的,然后有些漏洞我们也不一定知道,所以国内推出了国密SM2,SM3,SM4,SM9,ZUC.具体算法原理就不多讲了,这个要讲很久.
我就讲讲我们项目为什么用了SM2WithSM3签名这种数据传输模式.
其实提升网络传输速度,我们其实还需要研究一个东西,那就是保证安全的情况下,降低加密成本,因为加密本身就对前后端都有一定的时间损耗.那么我们为啥还要用SM2WithSM3加签验签这种复杂的方式呢.
我先讲讲他为啥复杂了,首先我们都知道加解密对吧,但是这个SM2WithSM3,是先对摘要信封进行SM2加密信封,然后用信封对明文SM4加密.将版本号时间戳随机数sm4加密后的密文再进行SM2签名,其中sm2签名涉及到sm3杂凑算法值.具体不多讲因为支付好像他们分享过.
为啥不直接sm4加密下,对称加密不安全,为啥不sm2加密下,要这么多.首先我们要明白一个东西.加解密和签名的分别作用是什么.
加解密是数据的安全性,签名是防篡改。
如果不在意数据丢失泄漏但是防篡改可以用签名验证。
如果在意数据安全,也防篡改,就两者都用。
不知道大家还注意里面一个东西没.你既然都加密了,签名了,为啥里面还搞时间戳,随机数啥的干嘛.我们都知道数据安全了,并且防篡改了.理论上确实没问题.但是漏了一种问题,防重放攻击,别人不篡改,不获取数据,就用重放攻击你.
时间戳是一种防重放攻击,但是也有漏洞比如业界一直认定的60秒,合法,60秒内就会钻漏洞,所以有了随机数加持.
讲完这个,还想给大家讲讲抓包
截获真实客户端的HTTPS请求,伪装客户端向真实服务端发送HTTPS请求
接受真实服务器响应,用Charles自己的证书伪装服务端向真实客户端发送数据内容
客户端收到服务器回应以后,首先验证服务器返回的证书。如果证书不是可信机构颁发,或者证书中的域名与实际域名不一致,或者证书已经过期,以浏览器为例客户端会向网页访问者显示一个警告,由其选择是否还要继续通信。 如果证书没有问题,客户端就会从证书中取出服务器的公钥。然后生成密码、公钥加密。 生成密码的过程会先产生一个随机数Pre-master key,该随机数是整个握手阶段出现的第三个随机数,稍后会经过公钥加密发送到服务端,有了它以后,客户端和服务器就同时有了三个随机数——RandomC,RandomS,Pre-master key,接着双方就用事先商定的加密方法,各自生成本次会话所用的同一把“协商密钥”。