你管这玩意叫网络?网络图解
一、OSI七层网络参考模型
数据流通过程图解
客户端要发送数据(报文)给服务器,报文来到传输层,加上端口号封装成段;段来到网络层,加上IP地址封装成包;
出现问题:源IP与目标IP不在同一个网络下,要将包发送到其他网络就需要经过默认网关,但是现在客户端现在并不知道默认网关的MAC地址,无法将包进一步封装成帧。
解决办法:此时需要用到ARP协议进行广播,才能找到网关IP对应的MAC地址,将包封装成帧,源MAC地址填客户端自己的,目标MAC地址填广播地址。假如当前网络有个2层交换机,交换机收到广播后,就会广播到所有的接口。当默认网关收到后,会将帧解封成包,同时会将客户端MAC地址和IP地址关联为一台主机;另外它还会把自己的IP地址放入包里面,再结合自己的MAC地址将包封装成帧,原路返回给客户端,这样客户端就知道默认网关的MAC地址了。
让我们恢复数据传输流程,目前客户端发送的数据(报文)已经成功封装成了帧,并发送到默认网关了。比特流到了默认网关时,解封为帧后发现是发送给自己的,再解封为包后看到目标IP是在另一个网络中,就会将数据包进行路由转发,最终到达目的网络。
如果目标的网关知道目标IP地址和MAC地址是哪台主机的话,就会将数据包封装成帧直接发送到目标主机,如果不知道目标IP地址和MAC地址是哪台主机的话,还是用ARP广播喊一下街就可以了。
目标主机收到包确认是自己的IP地址后,解封查看段可以发现源(IP、端口号)和目标端口号,用目标端口号给到指定的应用程序,应用程序处理好后,就可以按照源的信息做出响应。
回去的原理也是一样的,等客户端拿到服务器端的响应后,这就是一次请求响应的数据流通过程了。
二、从集线器到交换机
在你们公司里有几台电脑,你们没有WiFi,但是你们还想传输数据,此时你们可以通过一根网线将所有电脑都串联起来,这样这几台电脑之间就可以相互传输数据了。
但是随着你们公司规模不断扩大,电脑越来越多,网线越来越长,整个网络搞的很混乱,通过网线相互连接会这种方式行不通了。此时就需要用到集线器了。
每台网络设备都有全球唯一的MAC地址,如果要实现两台电脑的通信,就需要知道对方的MAC地址。
此时你的通信数据会被封装成数据帧,数据帧中填入源MAC地址+目标MAC地址,通过网线发送出去。
经过集线器时,集线器会把你的数据帧广播发送到你们公司的所有电脑,所有电脑收到数据帧后会检查目标MAC地址是否为自己的MAC地址,不是给自己的就丢弃;是自己的就接收处理。
出现问题:大家都被迫接收你发送的数据帧,增加了自己设备的工作量;更大的问题是集线器不能同时发送和接收数据,一次只能允许一台设备发送数据,如果两台设备同时通过集线器发送数据,就会发生冲突碰撞,数据帧会被丢弃。此时就需要用到交换机了。
解决方法:在OSI模型中,交换机之所以比集线器多一层是因为交换机会做笔记。
交换机有一张MAC地址表,记录了设备的MAC地址和端口号,我们把电脑的网线分别插入交换机的端口上, 两台设备第一次进行通信时,交换机会通过ARP广播给所有设备,找到目标MAC地址后,交换机会将这次通信的两台设备的MAC地址记录进MAC地址表中,以后再通信时交换机会先查看MAC地址表,如果有目标MAC信息就会直接发送给对应设备;如果MAC地址表没有目标设备的信息才进行广播寻址。
上面提到的这种交换机只认识MAC地址,而MAC地址又属于2层数据链路层的东西,所以这种交换机被称为2层交换机。
2层交换机的局限:当多台设备发送的数据帧都是广播地址(FF:FF:FF:FF:FF:FF)时,交换机将不得不都进入泛洪模式(广播发送),此时就是“大洪水”了。不仅会影响网络,浪费设备算力,还降低了安全性。
解决方法:我们可以通过VLAN的方式对不同的设备进行划分,将设备划分成不同的虚拟局域网,每个VLAN都是一个独立的区域。即使不同设备之间使用同一个交换机,但是区域内发送的数据,其他VLAN区域看不到,这样就达到了缩小广播范围的效果。这种方式能大大提升安全性和改善网络能力。
出现问题:2层交换机只能处理MAC地址,处理不了IP地址。不同LALAN区域都有属于自己的网络,如果要从一个网络到另一个网络就要涉及3层路由了,不同网络的之间通信,需要通过路由器来实现。
但是在一个非常复杂的网络里,比如一个大公司,往往需要多台路由器来解决VLAN之间的通信问题,但是路由器一般不会设置太多端口,而且由于路由器的功能比较多,它的处理速度相对交换机要慢,路由器价格也比交换机要贵,此时就需要介于2层交换机和路由器之间的3层交换机了。
3层交换机就是拥有处理3层网络能力(同路由器一样可以处理IP地址),也任然具备2层交换机处理能力(同交换机一样可以处理MAC地址)。
既能处理MAC地址也能处理IP地址;既能进行MAC地址转发也能进行IP地址路由;
一方面能创建更多的广播域了,另一方面每个广播域区间也相应缩小了,很好的解决了不同VLAN之间路由通信的问题。
3层交换机的局限:
虽然3层交换机实现了一些路由器的功能,比如:NAT和QoS等等。
但是3层交换机是没有WAN口的,因为WAN口是用来接入互联网的,我们通常使用路由器的WAN口来连接互联网服务提供商的。
另外功能多就会导致3层交换机比2层交换机的处理速度满。
三、CDN内容分发网络
出现问题:客户端访问服务器距离太远,意味着数据传输过程经过的节点太多,而节点与节点之间会发生阻塞或丢包等状况,将会导致客户端的请求到不了服务器端。为了解决这个问题CDN技术出现了。
解决方法: CND内容分发网络就是帮助服务器近距离给用户分发网页内容的,网页内容包括静态内容和动态内容。
对于静态内容:
1.源服务器会将静态内容提前备份给CND,这一步叫Push。此时当用户访问源服务器时,就近的CDN会将静态内容提供给用户。
2.如果源服务器没有将静态内容提前备份给CDN,当客户端请求访问服务器时,CDN就会向服务器主动拉取静态内容,这一步叫Pull。
对于动态内容:
动态内容通过CDN获取的话就比较难了,动态内容是根据每个用户的交互产生的,无法提前给到CDN。
但是CDN也是能提供一些动态服务的,比如:时间服务。有些CDN会提供可以运行在CDN上的接口,让源服务器使用CDN上的接口,而不是源服务器自己的代码,这样用户就可以直接从CDN上获取时间,而不是从源服务器上获取了。
不管是静态内容还是动态内容的获取,CDN的布局相当于给源服务器增加了一道墙,用户不用直接访问源服务器了,而是必须通过CDN进行沟通,这样就避免了恶意的DDos攻击。
虽然用户无法攻击源服务器了,但是任然可以攻击CDN网络节点,如果一台CDN节点挂了怎么办?
有些互联网大厂会在世界各地部署许多CDN服务器节点,同时实时监控着这些CDN服务器的负载情况,如果某台CDN服务器超载了,就会把当前用户的请求转移到没有超载的CDN服务器上,实现网络流量的平均分配,也叫做负载均衡。
如何让CDN节点实现负载均衡呢?
这里采用的方法与DNS域名解析里根服务器的做法相似,采用的就是任播的通信方式,使用了任播的通信方式后,CDN服务器对外都拥有同一个IP地址,这个IP地址收到用户请求之后就会采用就近原则,请求由距离用户最近的CDN服务器来响应。不管黑客用户的攻击来的多猛烈,利用任播的技术把流量转移到另外没有超载的服务器就可以缓解了。
综上所述,总结一下CDN的几个作用:
-
1、加速,加快用户到服务器之间的请求响应速度。
-
2、负载均衡,帮助网站实现流量的平均分配。
-
3、更安全,有效避免了用户的DDos攻击。
-
4、省钱,为网站节省了一大笔的带宽流量费用。
四、DNS域名解析
就像互联网中的每一台主机都由ip地址标识位置一样,ip地址可以是纯数字或数字加字母,记忆起来很痛苦。于是,ip地址可以与域名关联,我们只需记住域名即可。
在浏览器中,我们输入域名来获取相应网页内容,而非ip地址。但计算机只能识别ip地址进行定位,因此我们需要进行域名到ip地址的转换,这个过程就是我们今天要讲的dns域名解析过程。
图书馆是按层级划分的,域名也是如此。以B站为例,从左到右解读域名,首先看到熟悉的三w,三w其实是主机名。以B站为例,还有mail、member和space等主机名,这些主机名方便记忆。
比如:三w用于访问主站,mail用于访问邮箱,member与会员页面有关。它们后面都跟着.bilibili,即隶属于哔哩哔哩域名统一管理。
这样我们就能想起qq也是类似情况。三w访问主站,mail访问qq邮箱,很多网页都采用这样的形式。
我们看到哔哩哔哩后面跟着点com,很多网页都是跟着点com,因为它们隶属于com域名进行管理。当然,常见的还有点cn和点net等。那么,是谁管理点com、点cn、点net这些域名的呢?
域名由点划分,因此域名的最后也需要有一个点来分割。但由于最终都由根来统一管理,因此没必要在全部域名的最后写点root,所以直接把根用点表示,而一般我们会忽略这个点。现在域名结构树已形成,最顶部由一个点表示,再次证明世上先有蛋后有鸡。
但目前有个问题,底下众多域名最终汇聚到一个根管理,能行吗?
实际上根由一群服务器组成,这群服务器仅用13个不同域名,从a到m开头,这13个根域名服务器由12个独立机构运营,注意是13个域名,不是13台机器。绝大多数同学会在此处出错。
肯定有同学好奇,目前有多少台机器负责根域名服务器的工作?
截至目前,有12个独立机构运营的根服务器,已有1467个节点。本打算展示我国节点,但可能涉及敏感问题,所以只显示美国节点。不过现在又有问题,只有13个根域名。
而有1467个节点,即绝大部分节点IP地址相同,比如这两个f根域名IP地址相同。那我们如何与最近节点取得联系?通过哪种技术实现?答案是采用任播技术。
当我们与根域名服务器联系时,就能找到离我们最近的根域名服务器。
根域名服务器管理com、cn和net等域名服务器,这些域名服务器称为顶级域名服务器,即top level domain,简称TLD。这个简写大家记住,等会还会用到。
顶级域名服务器分别管理各自域名服务器,比如哔哩哔哩和qq,这些服务器叫权限域名服务器或权威域名服务器。英语是authoritative。权威域名服务器管理各自主机。
当然,实际网络管理层次更复杂,但万变不离其宗。知道前面这些知识,我们就能讲解域名解析过程。
假设现在需要用浏览器访问B站,在地址栏输入网址后,浏览器需要做什么?
我们稍微回忆一下前面的图书馆例子,浏览器首先查看自身缓存有无对应IP记录,同时查询主机本地文件有无对应记录。如有记录,就没必要进行后面步骤。当然,这里我们假设没有缓存。
但有个细节,浏览器为进行域名解析,需调用解析器。用C语言表示的话,就是通过域名获取IP地址的代码。解析器可帮助浏览器调用系统网络功能,解析器就是一段程序,无需过于复杂,相当于DNS客户端。
DNS客户端需向DNS服务器查询IP地址,解析器会向DNS服务器发送请求。但如何与DNS服务器联系呢?我们有其地址吗?
网络设置里可查询到DNS服务器地址。也就是说,电脑里有该地址,可直接联系。若无该地址或DNS服务器地址设置错误,但又能上网,会出现能上QQ却不能浏览网页的情况,因为QQ直接使用IP地址访问服务器。
DNS服务器通常是最接近我们的本地DNS服务器,由ISP负责管理,如中国电信和中国网通等。
本地DNS服务器在收到请求后,会查看自身缓存,如有则直接返回IP地址,并标注非权威。毕竟本地DNS服务器并不控制域名,只是帮忙走流程。
当然,有些本地DNS服务器可能还会记录解析的域名。接下来的步骤由本地DNS服务器独立完成,解析器只需等待即可。
在这里,我们用命令行模仿本地DNS服务器后的解析过程,使用命令nslookup。假设本地DNS服务器里没有任何根域名服务器的域名和地址,我们需先设置查询类型为ns,即名称服务器。我们要查询根服务器的域名,所以输入一个点表示根。在迅雷不及掩耳之间得到一大串回复,首先是我们使用的DNS服务器8.8.8.8,另外用的是53端口,这是典型的DNS端口。
提醒一下,虽然这里没有显示,但DNS一般使用UDP进行传输。看看下面分别有非权威和权威的结果,但只有非权威的结果,非权威结果通常是缓存结果,而非空管相应服务器返回的结果。我们可以看到这些就是根服务器的域名,一共有13个域名。
现在我们知道域名需要得到对应IP地址才能进行访问,因此设置type为a,即设置为IPv4类型。选择一个根服务器,由于要找B站的地址,选择b根服务器。输入b.root-servers.net回车,得到其对应的IP地址。
此次为非权威答复,因为根服务器知道com域名服务器的地址,于是我们直接与该com域名服务器对话,输入server 199.14.201,即刚刚b根服务器的地址,设置type等于ns,输入com.,即向域名服务器咨询com域名服务器的地址,很快得到了结果。
这里有一堆域名服务器,但此次为权威响应,因为由根服务器直接负责com域名。回答部分,顶部是服务器的域名,底部是域名对应的IPv4和IPv6地址。特别要注意的是,这里的gtld表示generic top level domain,即通用顶级域名,属于顶级域名TLD中最常见的一种。既然知道这么多com域名服务器的地址,可以选择一个,仍选b,记录下IPv4地址192.33.14.30。
于是直接与该B通用顶级域名服务器通话,输入server 192.33.14.30,即刚刚的顶级域名地址,设置type等于ns,输入bilibili.com,即向顶级域名服务器咨询bilibili.com域名服务器的地址。点击回车后,代码迅速呈现,可以看到bilibili.com的域名服务器有两个,一个是ns3,另一个是ns4,这两个域名服务器由DNS平台提供服务,各自对应多个IP地址。此次无其他选择,随便选一个,记录下IP地址129.211.176.212。
于是直接与该权威域名服务器对话,输入server 129.211.176.212,即刚刚记录的地址,设置type等于a,输入www.bilibili.com,即向权威域名服务器咨询www.bilibili.com域名服务器的IPv4地址。回车后,看到一条结果,其中的canonical name常用于域名跳转。这意味着www.bilibili.com会跳转到a.w.bdcdne.com,这个a开头的域名地址是一个CDN,即内容分发网络。因此,必须得到其IP地址,直接输入该CDN的地址。
白驹过隙之间,我们得到了结果,CDN域名返回了几个IP地址,这就是我们需要的东西。本地DNS服务器得到这个地址后,会返回给解析器。当然,一般还会把地址缓存起来。解析器接着把地址给浏览器,浏览器就可以通过这个IP地址去进行网页的连接了,这就是整个解析过程。要注意的是,解析器与本地DNS服务器之间用的是递归方式,即发送数据后最终返回结果。
而本地DNS服务器和三层服务器之间用的是迭代方式,即第一步得到什么,第二步接着进行第三步步。大家要注意两者的区别。
五、在浏览器输入URL回车之后的过程
上网的第一步是输入网址,将已知的网址输入到浏览器的搜索栏。
我们在浏览器输入的url实际上并不能直接找到服务器的地址,这些由字母组成的url只是方便记忆。实际上,每个网址都有相应的ip地址,ip地址由数字组成,不方便记忆。
因此,我们需要进行dns解析,将url地址解析为ip地址,这一过程称为dns解析。
dns是一个数据库,记录了许多url和对应的ip地址,这样大家就可以根据dns查找到对应的ip地址。有了ip地址,我们就可以在互联网上找到指定的服务器
虽然我们知道具体的ip地址,但在正式发送数据之前,还是得建立tcp连接。
可能有人疑惑,为什么需要建立tcp连接?建立tcp连接就是在发送数据之前建立客户端和服务端之间的通道。建立通道后,就可以在这个通道里发送数据了。
大家都在这个通道里发送数据,这样数据就不容易发生错乱。于是就有了建立通道前的三次握手:客户端发送数据包来表示请求连接,服务器响应数据包来表示同意建立链接,客户端再发送数据包来表示成功连接。
当我们和服务器建立连接后,浏览器会发送HTTP请求报文给服务器。报文格式由请求行、请求头部空行和请求数据组成。
请求行包含请求方法、请求地址和HTTP协议版本。
请求头部包含关于浏览器的信息,由键值对组成,一行一对,直到遇到空行表示请求头部结束。
最后为请求数据,具体说明我们需要什么数据以及以何种形式获取数据。
如果用表格形式来看,当服务器收到HTTP请求报文后,会处理请求报文并做出响应。响应报文与请求报文相似,格式由状态行、响应头部空行和响应数据组成。
状态行最重要的是那三位数字,如常见的404 Not Found表示资源未找到的错误,另外最常见的是200表示请求成功。
响应头部由键值对组成,一行一对,直到遇到空行表示响应头部结束。
最后是响应数据。
浏览器接收服务器的响应后,页面开始渲染,即解析接收到的HTML、CSS和JavaScript等文件。
有了这些前端文件,用户就可以在前端看到页面内容,即在浏览器中看到内容。这就是浏览器输入URL并回车后发生的事情。
六、TCP详解、HTTP&HTTPS见其他文档
七、HTTP状态码
接下来开始学习,状态码有几百个,但常用的码只有十几个。
首先,要知道状态码的分类,如1xx、2xx、3xx、4xx、5xx,状态码很有规律,通常是三个数字加一段字。
1表示信息性,表示接收的请求还在处理中。以1开头的状态码虽然很少用在请求中,但依旧挺好。
2开头的状态码表示成功。
请求方法有很多种(Get/Put/Post/Head/Trace),不管使用哪一种,只要请求没问题,200状态码就直接甩给你。
听说要创建用户,服务器该怎么表示呢?201我们走起来,Post and Put我欢迎你来。
没有内容返回给客户端,204状态码表示无内容。
资源现在不在了,已被移去其他地方,服务器说不用担心,数字3让你很安心。
旧的地址也不好使了,给你一个新地址,301让你重定向,这是资源的新方向。
如果今天资源在这里,明天又转移了,就给出临时地址302。
看到有条件请求,检查缓存时间轴,304不用再下载,服务器资源没修改。
4开头表示客户端出错。
请求语法错误,返回400状态码。
数据库查无此人,返回401状态码。
虽然知道你是谁,但没权限,我管理谁,返回403状态码。
地址是不是写错了,或者资源已经不在了,反正我就是没找到,返回404状态码。
409冲突问题,新老版本记得对齐。
5开头是服务器报错。
可能是代码出错了,可能是数据库出错了,未知错误,先返回500状态码随便应付。
代理网关夹心饼,响应还得往上领,502状态码不是什么胶水,而是我上游正在水。
服务器还没准备好,负荷超载运行不了,503我宕机了,反正你是访问不了。
八、DHCP原理与握手过程
若访问网络,最基础的条件是拥有一个IP地址。但究竟是谁给我们分配IP地址的呢?
有人可能会认为这是废话,运营商会分配IP地址。
但若用WiFi连接网络,为何只需输入WiFi密码即可上网?其实起作用的是DHCP。
试想,若完全手动配置上网信息,需自行填写IP地址、子网掩码、网关地址和DNS服务地址。若家里来了客人,让客人手动配置这些以联网,简直是一场灾难。
网络管理员还需确保一个IP地址仅供一台设备使用,否则会发生冲突。这种配置IP地址的方式是静态的,适合长期使用。一般来说,固定设备如打印机、服务器等需要这样的静态IP地址,但这种分配方式不太适合大部分家庭和公共场所。
因此,DHCP这种分配IP地址的方式变得尤为重要。无论是有线还是无线连接网络,只要确保使用自动获取IP地址的方式,DHCP服务器通常会分配IP地址、子网掩码、网关地址和DNS。设备获取这些配置信息后,会自动配置,然后可以上网。这种动态方式对应着DHCP里的“D”,即Dynamic。
当然,DHCP也可以分配静态地址。我们等会再说。
获取的信息不仅限于IP地址,还可以有其他上网配置信息,这对应着DHCP里的“C”,即Configuration。
说到这里,大家可能有个疑惑:DHCP服务器应该长成什么样?为何我家没有这样的东西?
实际上,DHCP服务器不一定要是长得黑黑长长的东西。大部分人能见到的DHCP服务器,正是路由器或光猫。换句话说,若知道路由器的管理密码,也可以进行一些额外配置。若突然需要增加很多上网设备,可以在路由器的DHCP设置里增大地址池的范围,这样设备在获取IP时,DHCP服务器就可以提供更多的IP地址。
不过,大家可能又有疑问了:在DHCP里真的可以这样设置吗?运营商不就给了我很多IP地址吗?
想得美。一般来说,在路由器里获取的IP地址都是私有地址,私有地址有固定范围,但已经足够多来分配使用。这些私有地址仅在局域网内使用,最终在因特网内传输需转成公有地址。
地址池范围可以增大,也可以缩小,但操作要谨慎,因为DHCP分配出去的IP地址有租期。
若给一台设备分配了一个租期为七天的IP地址,这台设备即使只使用IP地址一天,在没有额外操作的前提下,其他设备在到期前都不能用这个IP地址。
若要实现静态地址分配,可以把租期设置为infinite,就相当于没有期限了。不过要谨慎进行这样的设置。
另外,如果网络中有一些地址专门用于服务器或其他用途,不希望这些地址被动态分配,那么在配置DHCP地址池时,可以排除这些地址,或将特定的IP地址保留给对应的MAC地址的设备使用。
接下来,我们来看看DHCP具体是如何工作的。
假设网络中有两台设备和一台路由器,从网络结构来看,它们都处于同一个局域网中。
现在,一台新设备想要上网,当设备插入网线并设置自动获取IP地址时,这台设备实际上没有任何信息。
虽然从网线来看,我们知道路由器是DHCP服务器,但新设备并不知道哪个是DHCP服务器,因此新设备需要进行DHCP discover,即发现DHCP服务器的存在。
DHCP discover这一步,必须要发送数据出去。那么,具体发送什么类型的数据呢?
从网络模型来看,DHCP处于应用层,也就是说,DHCP discover实际上是应用层报文。既然基于最上层,那么网络模型下层的信息是一定要有的,毕竟不存在没有底层基础的空中楼阁。
DHCP在传输层使用的是UDP协议,传输层的一个重要信息是端口,其中客户端使用68端口,服务端使用67端口。
在网络层,数据包最基本的要有源IP地址和目的IP地址,但这里就遇到了问题。因为新设备本来就是要索取IP地址,根本就没有自己的IP地址,而且新设备本来就是要寻找DHCP服务器地址,目的IP地址更不知道怎么填。
还好,IP地址里有两个特殊的地址,以IPv4为例,如果不知道自己的IP地址,可以填写0.0.0.0;如果不知道目标IP地址,可以填写255.255.255.255。填写这些地址就会进行广播,当然,广播不会在整个互联网里传播,只会在本地进行传播。
但这里看着不像在广播,假设此时在路由器前加了一台二层交换机,交换机在收到广播的数据包以后,会转发给其他设备。
当然,大部分家庭都不会加一台交换机。而且,路由器在收到广播的数据包以后,默认不进行转发,只有路由器独享了,不会打扰别的设备。
接下来,数据链路层最重要的是MAC物理地址,也需要源和目标MAC地址。新设备有自己的源MAC地址,但目标的MAC地址是不知道的,因此这里和IP地址是同样的道理,填写MAC广播地址。
DHCP discover这一步的设计很简单,一开始也没有考虑安全问题。如果有不法分子一直进行discover,是有可能把地址池给占用完,导致正常用户无法上网。
DHCP discover步骤完成后,若网络中有DHCP服务器存在,则会进行处理,即进行DHCP offer步骤。DHCP会提供上网所需的配置信息,包括IP地址、子网掩码、网关地址和DNS地址。
通常,家庭中的网关DHCP和DNS地址由路由器承担。此外,此步骤还有两个重要信息:IP地址租期到期之前需续租,且会提供续租时间。
传输层仍使用UDP协议,但源和目标端口号颠倒,因为此次是服务端发送给客户端。
网络层中,原IP地址易于理解,因为路由器有其IP地址,且在此步骤中路由器会初次提供IP地址。因此,源和目标IP地址均可填写在数据包上。
数据链路层中,原MAC地址为路由器的,目标MAC地址即新设备提供的。
那么到此DHCP工作已完成了吗?
但此处可能出现多种情况,例如,若局域网中有两台DHCP服务器,它们同时提供offer,新设备只能选择一个,否则不合理。
因此,进入下一步DHCP request,即选择并正式进行请求。
由于上一步DHCP服务器已提供IP地址,若确定使用该IP地址,则需在报文中说明这个IP地址。
由于新设备尚未完全允许使用此IP地址,因此在网络层中仍使用0.0.0.0作为原IP地址,目标IP地址仍为广播地址。
这也是许多同学的疑惑:新设备已收到DHCP服务器提供的配置信息,单播发送给DHCP服务器就好了,为何仍使用广播地址?
实际上,网络中可能存在其他DHCP服务器,因此使用广播可以告知所有设备已选择哪个服务器。
同理,数据链路层的MAC地址与discover阶段相同。若DHCP服务器收到新设备发来的dhcp request,则会发送dhcp ack确认新设备可以使用IP地址。此步骤的所有数据信息基本与dhcp offer相同。
现在,新设备可以开始上网。为验证大家是否真正理解DHCP的原理,下面展示实际的抓包信息。
首先,映入眼帘的是DHCP握手的四个步骤:discover、offer、request和ack。
我们先来看第一步,discover。
新设备想要租用IP地址,但不知道谁是DHCP服务器,因此从0.0.0.0发送,并用255.255.255.255进行广播,MAC地址为新设备的地址作为原地址,并使用MAC的广播地址作为目标地址。传输层使用UDP从68端口发送到67端口。信息较多的是应用层,此处出现一个特殊的ID值——transaction id。这个ID值由客户端提供,是一个随机数。若有其他设备也在进行DHCP交互,transaction id有助于更好地判断请求属于哪个设备。
另外,因为DHCP是基于Bootstrap Protocol发展出来的,因此在报文里会看到bootp或者boot这样的字样。这里bootp flags设置为Unicast的意思是服务器可以单播发送给新设备,即不用广播进行发送。因此,在DHCP offers这一步就能看到没有使用广播地址,下面多处填写0.0.0.0,道理很简单,因为新设备没有MAC地址。这里重点是option选项里面,我们看请求IP地址。这里虽然写的是0.0.0.0,但实际中很可能写的是旧的IP地址,因为设备之前用过的IP地址,还想继续使用。因此,可能会显示旧的IP地址。选项里重要的还有参数请求列表,客户端想要什么信息可以一次性在这里说明,但是DHCP服务器并不一定会全部提供。
接下来我们看DHCP offer,因为DHCP服务器已经指定了一个IP地址给新设备,而且上一步已经说了可以使用单播,因此IP地址这里就单对单进行发送。但是注意了,实际上服务器是有能力用广播的形式发送DHCP offer的。我们回到报文里,这一次your client ip address就填写好了,也就是服务器给客户的IP地址。next server ip address这里会让很多人糊涂,因为客户端并不是只能找一个DHCP服务器,还可以找第二个服务器。但是一般家庭都只有一个路由器,因此这里也不会有其他地址了,会填写当前路由器的地址。另外,也不是每个网络都有中继代理,除非DHCP服务器和客户端不在同一个网段,此时就需要配置DHCP中继了。但一般家庭都是一个路由器管理多台设备,因此这里写0.0.0.0。接下来的还是一样,要看option选项,这些是服务器提供的信息。子网掩码、IP地址、租期和续租时间等等。客户端向服务器请求这些信息,但服务器并没有全部提供,这是很多同学忽略的细节。
接下来就是DHCP request这一步的报文信息,和DHCP discover非常相似,基本上就是复制粘贴。但是在option选项这里有一个重点,客户端会说明自己选择好的DHCP服务器。一般来说会选择第一个收到其报文的DHCP服务器。而且大家可以看到这一步用了广播地址,如果其他DHCP服务器收到后也知道客户端选择的是不是自己。参数请求列表这里一般还是会把之前的请求信息复制过来。DHCP服务器上一步如果没有提供客户端想要的信息,客户端依旧想要得到这些信息,因此还是可以写上继续请求的。
最后一步是DHCP ack,更简单了,意思就是确认IP地址,允许给客户使用了。这个报文和DHCP offer一样,可以单播或者广播。现在你就知道DHCP的基本原理了。
九、VPN技术原理
办公离不开手机和电脑,国内大多数公司使用微信和QQ办公,国外很多公司则选择VPN。说到VPN,大家会想到科学上网,其实VPN是用来远程办公的。
据了解,最早的VPN出现在1996年,当时互联网不如现在发达。HTTPS在2000年才编入RFC,96年时很多人上网使用HTTP协议。HTTP协议的主要缺点是明文传输,未对数据进行加密。
这对大公司来说是个问题,例如公司业务部在东边,仓库在西边,客户在东边下单购买商品,需将购物信息发送到西边的仓库。若通过互联网发送,数据经过谁的手都不知道。且数据未加密,更易被中间人获取客户购买信息。
大公司可能考虑架设专线解决此问题,但架设跨越东西方的专线成本高昂且费力,因此大部分公司无法采用此方法。为降低成本,只能利用现有公用网络体系。
于是,VPN较好地解决了此问题。核心原理很简单,公司在两头配置VPN集线器,也有其他形式如VPN服务器、VPN网关。公司内部所有要发送的数据都需经过VPN集线器加密后才能从公司发出,数据经过ISP进入互联网。ISP即互联网服务提供商(电信/联通)。数据抵达另一头的VPN集线器后会解密,再分配到指定主机。流程反过来也一样,核心就是:数据在公用网络中保持加密状态。
这是VPN的一种类型。即站点对站点VPN,这种VPN应用于同一公司内部不同地点的内部网络,也可应用于不同公司的外部网络。
站点对站点意味着两端或多端地点相对固定,链接不间断。一个数据包发送到VPN集线器时,数据包上的源地址会被更改为当前VPN集线器的地址,目的地址则被改为目的VPN集线器的地址。数据包会被加密,中间人看来只是两个集线器之间的通信,且数据已加密,从而隐藏了实际源地址和目标地址。
不过,真的就能完美隐藏IP地址吗?等会解释这个问题。
回到VPN类型,另一种类型是客户端对站点VPN或远程登录VPN。这种类型很适合聚焦办公情景,因为站点对站点地址相对固定,但每个员工的家庭地址不同。若员工在咖啡厅或酒店办公,IP地址会变化,更不用说用手机办公了。因此,这种类型相对灵活,适合不需要长时间连接的方式。一般来说,这种VPN可用浏览器直接通信,也可另外安装客户端软件进行VPN通信。此外,这种VPN还有全隧道和半隧道模式。
若想把所有网络数据都走公司网,就选全隧道。但在家办公难免摸鱼,所以很多人选择半隧道。
加密只是VPN的一个职责,即保密,让数据不易被人识破。加密需使用算法,常用的有AES、3DES,这两个算法名中的都有一个E,E表示加密。单纯加密不能完美传输数据,因为黑客即使看不懂数据,也可能乱改数据,自己得不到,也不让别人得到。还好,VPN的另一个职责是保护数据完整性,这就需要用到Hash。
HASH使用算法根据字符串生成唯一的HASH值。可以看到,一段字符串对应一个HASH值,增加一个字符,HASH值就会完全不同。这样,接收方可根据HASH值判断数据是否被篡改。常用的HASH算法有MD5和SHA系列。
现在问题又来了,数据确实安全了,但最重要的是要知道和自己沟通的是否是认识的人。比如,有人黑员工的电脑使用VPN登录公司内部网怎么办?这就需要VPN的第三个职责——认证。常见使用的算法有PSK和ISA。如果大家对具体某个算法有兴趣,不要忘了把算法名字打到公屏上。
其实,要让VPN具有刚刚说的三个职责,需要结合很多协议来实现。
网络通信本来就是一堆协议组合而成的,一堆协议又可以组成一个框架。VPN主要用到了两大框架:IPsec和SSL/TLS。这两大框架的名字都有着“S”,这个“S”不是超人“S”,而是“Security”的缩写,即安全。虽然这两大框架内容复杂,但总体知道核心是安全即可。那为什么会需要用到这两大框架呢?
很多人可能知道,SSL/TLS代表HTTPS里的S,即浏览网页时用的是SSL/TLS。所以,客户端对站点这种类型的VPN一般使用SSL/TLS,有能进行VPN功能的浏览器即可,非常方便。关于SSL/TLS的详细,大家可以看看我期HTTPS的视频。
IPsec就不一样了,既可以用在客户端对站点VPN,也可以用在站点对站点VPN。不过多数是用在站点对站点VPN上的。IPSEC即IP Security的意思,而IP协议在网络层,所以IPSEC在网络层。
我们来简单回顾一下OSI模型数据流程,从应用层往下流,到了目标那端就从物理层往上流。这里有个细节,应用层往下流时,会经过网络层使用IPsec,对网络层上面的数据全部加密后再发送出去。而SSL/TLS在第六层表示层会加密应用层数据再往下发送,底下的层不能使用SSL和TLS加密。
大部分人对VPN有误解,比如觉得VPN可以完美隐藏自己要访问的网站。其实,目标地址被修改后的数据经过ISP的网络发送到VPN服务器,VPN服务器再把数据解密发送到真实服务器,你和VPN服务器之间就建立了一个无形的通道。只有你们双方知道这个通道,所以VPN的V代表Virtual虚拟的意思,P表示Private私人隐私的意思。
但把你想要访问的网站告诉给VPN真的好吗?你能保证VPN不会出卖你吗?如果你的VPN真的不会出卖你。那也有可能在DNS域名解析的时候,你就已经先问ISP某个网站的IP地址了,因为有可能你设置的DNS服务器还是ISP提供的,这样ISP还是会知道你想访问什么网站。
上网是一件很复杂的事情,千万不要认为有什么完美的事情。还有人觉得VPN可以完美隐藏自己的IP地址,但别人要知道自己的IP地址有很多方式。不过我听过一个很笨的案例,有个人用账号密码登录某个网站后,然后忘记自己已经登录了,再把VPN打开来,以为服务器不知道自己的真实IP。其实你第一次登录的时候,服务器就已经知道了你的真实IP。
有些人使用VPN是想通过某个国家的IP访问特定资源,VPN确实可以做到定位到某个国家的IP地址,但问题是很多网站服务器也是会知道你在使用VPN的,从而制造一些问题让你回答。
还有人是为了在公用WIFI的前提下保护自己的数据,害怕会遭到ARP攻击,实际上如果你访问的是HTTPS的网页,就不用担心这个问题了。黑客虽然知道你在访问什么网站,但是却不知道你实际发送和获取的内容。
说了这么多,相信大家对VPN就有了一个更正确的了解,而不是把VPN用在一些违法的用途上。
十、SSH协议握手过程
使用ssh远程登录服务器时,ssh是一种加密通信方式,大家通常会直接输入ssh命令。但在输入密码并点击回车之前,需确认密码不会被监听泄露。那么,ssh如何为我们保驾护航呢?在正式了解之前,我们先快速复习几个概念。
若你刚租了房子,房东会给你一把钥匙,自己再留一把。若世界上只有这两把钥匙,便形成了对称加密,即只有你和房东可以开门或关门。对于数据信息中的对称加密,双方用同一把密钥进行加密和解密。
若我有一对密钥,分别是公钥和私钥,公钥可给你,私钥绝不能给任何人。你可以用公钥加密信息后发送给我,只有与公钥成对的私钥才能解密信息,这就是非对称加密。
但对称加密和非对称加密都面临同样的问题:如何安全地将密钥发送给对方,同时防止被中间人知晓?这就需要用到DH密钥交换(Diffie Hellman)。
简单来说,就像我把秘密藏在一个箱子里,并用只有我能开的锁锁起来发送给对方。对方收到后用对方的锁再锁起来发送给我,我收到后用自己的锁打开,再发送给对方。因为没有其他人有对方的锁,所以没人能打开。对方收到后用自己的锁打开并取出秘密。整个过程没有外人能打开箱子。
但DH密钥交换有个问题:中间人虽然打不开箱子,但可以换一个箱子并换上自己的锁,从而更改里面的内容。因此,为了证明信息没有被篡改,我们需要对信息进行哈希运算,得出同种算法的唯一哈希值。若信息被修改,哈希值就会不同。但中间人仍可能更改哈希值以对应自己篡改的信息。SSH用一种巧妙的方法证明这个哈希值没有被篡改。
带着这个疑问,我们了解一下ssh的握手过程。使用ssh命令后,会进行tcp三次握手,然后发生ssh握手。双方需要发送协议版本,因为ssh一和ssh二这两个协议不兼容,加密方式也不同。
抓包信息中能看到发送ssh版本字符,后面是软件版本open ssh。若看到ssh杠1.99字样,说明发送方支持ssh一和ssh二。
声明协议版本后,需要进行密钥交换初始化,即key exchange initialization,缩写为KEXINIT。若展开抓包信息,可能会看到协商应使用什么算法的复杂过程。密钥交换包括host key认证、压缩等。简单来说,就是双方应选择哪种算法来生成不为人知的密钥。
接下来双方正式开始生成密钥。我们先看抓包信息,Elliptic Curve Diffie-Hellman,可理解为加强的DH算法,用加强版算法交换密钥。我们还可以看到客户端给服务端发送了公钥,敏感的同学能嗅到私钥的味道,因为公钥和私钥通常成对出现,客户端手里有对应私钥,这对密钥叫客户端临时密钥。这对临时密钥用于后续生成共享安全密钥,且一般会销毁,即使加密会话被截获也难解密。服务端也会生成自己的临时密钥,我们用服务端临时密钥来区分。
服务端临时密钥也用于生成共享安全密钥,服务端用自己的临时公钥、临时私钥以及收到的客户端临时公钥,生成共享安全密钥。共享安全密钥能发给客户端吗?答案是不能。共享安全密钥可用于加密以后会话信息,只要客户端有共享安全密钥就很难解密通话。为了让客户端也能生成同样共享安全密钥,服务端需把临时公钥发送给客户端,即抓包信息里的reply这一步。
但reply里还发送了别的东西,我们先不急着学新的,先看看客户端收到服务端临时公钥后会进行什么操作?客户端同样会生成共享安全密钥,用自己的临时公钥和私钥,以及服务端的临时公钥。客户端和服务端的共享安全密钥必须一模一样。
当然也可能不一样,因为信息可能被截获,可能一直在和中间人沟通,得到的共享安全密钥和中间人一样,而不是和服务端一样,那肯定不行。因此,双方需用哈希证明信息没被篡改。现在最难也是最有意思的部分开始了,大家仔细听。如果两边都生成同样的交换哈希值,就有办法证明是否被篡改。
我们先看简单版本,服务端生成host密钥用来证明服务端身份,接着服务端生成一串交换哈希值。 这串哈希值需用共享安全密钥及其他信息生成交换hash值,具体生成方式先不管。接着这串hash值用服务端的host私钥加密签名,服务端把host公钥以及加密后的交换hash值发送给客户端。其实就是ECDH密钥交换初始化这一步,客户端发送临时公钥,服务端回复临时公钥、host公钥和签名哈希值,因为客户端同样有共享安全密钥。因此,客户端会用和服务端相同的方法生成交换哈希值,接着客户端用服务端的host公钥解密收到的交换哈希值,得到的结果是一个哈希值。如果结果一致,就证明两边都有相同的交换哈希值。
可能你还不太明白原因,因为服务端用自己的host私钥加密了交换哈希值,中间人不知道服务端的私钥,中间人如果用其他私钥加密哈希值,得到的哈希值会和服务端那边不一样。
但中间人就没办法了吗?虽然实现起来有难度,中间人完全有可能从一开始就截获你们之间的对话,有可能你一直都只是在和中间人生成共享安全密钥,这就像你以为在和美女聊天,其实对方是个抠脚大叔。
所以,如果你第一次连接服务器或者以前连接过服务器,一般来说会有提示,提示是否可相信发过来的host公钥,因为一般会和你的本地主机数据做对比,没出现过或者有更改就会产生提示,如果你输入yes,表示相信。下一步就是输入服务器登录密码,此时如果通话被监听,那么你的登录密码就会直接暴露。
其实并不是很多人都知道这样登录服务器的风险,不过因为比较难知道客户端什么时候与服务器连接,中间人一般不会一直等着。因此,第一次用密码登录相对比较安全,但是如果你频繁这样操作,被截获密码的机会就变多了。
那怎么来规避这样的风险呢?其实是可以像https那样使用ssh证书,如果你的本地主机里有证书。就能够验证主机是否可以被成功连接。另外还有一个常用的方法就是公钥认证。一般会在客户端这边使用ssh-keygen命令,这样就可以生成密钥对,私钥放在本地,公钥发给服务器,接着用ssh-copy-id把公钥拷贝到服务器那边。当然,拷贝的时候会要求密码验证,下一次用ssh登录就不用密码了,只要确保公钥放到服务器那边,中间人就很难搞了。很多git服务器也是把公钥添加到服务器上的,原理是一样的。
还有人会把服务器的host公钥直接用网页的形式展示出来,这样在登录的时候就可以进行对比,每种方法都有各自的优缺点。
了解这里的安全问题后,我们回到前面还没讲完的交换哈希值。交换哈希值其实需要好几个值来生成,第一个是双方确认的版本号字符串,也就是握手第一步的信息;第二个是双方在密钥交换初始化发送的那些算法名称的字符串负载;第三个是服务端的host公钥;第四个是客户端的临时公钥;第五个是服务端的临时公钥;第六个是双方的共享安全密钥。正是用这些元素,双方生成相同的交换哈希值,这就是reply这一步涉及到的核心知识。
很多人以为这就结束了,其实还没有,下一步是new keys,两边都有这个步骤。
这一步双方需要生成六个密钥,其中两个密钥是用来加密数据用的,还有两个密钥是配合MAC用的,也就是确保数据完整性,为使得黑客更难得出原始信息。还有两个密钥是用来加强对称密钥加密的,因对同样信息加密两次不易出现相同密文。有了六个密钥后,后续通信就是加密的信息了, 这就是SSH握手的核心过程。
十一、虚拟网络模式:NAT|NAT网络|桥接Bridged|内部网络|仅主机
如果不懂虚拟机配置,可能面临内存、处理器、存储空间不足的问题。但如果不懂虚拟机里的网络配置,就只能默认选择。不同虚拟机软件的网络模式种类有所不同,但原理相似。因此,本视频以网络模式较多的Virtual Box作为示范。
首先要讲的是NAT模式(网络地址转换),因为大部分家庭网络都会用到NAT。假设家庭申请到了公网IP地址,因为属于公网,可以访问网络,其他IP也能访问你。但如果家中多人上网,只有一个IP地址不够用。
于是可以利用路由器的NAT功能,让路由器给要上网的设备分配不同的私有地址。当这些设备发送数据时,NAT会把私有地址转成公有地址,并用端口进行标识。数据回来时,再把公有地址转成私有地址。私有地址有特定范围,不能被公有地址直接访问。
目前Virtual Box的默认网络模式就是NAT。创建虚拟机时,会默认提供NAT模式,此模式下会有一台虚拟的DHCP服务器。DHCP服务器和网关默认是10.0.2.2,因为是NAT模式,所以会分配私有地址,默认私有地址是10.0.2.15。每创建一台使用NAT模式的虚拟机,它们都有同样的私有地址,因为它们都在独立网络里,所以这些虚拟机不能直接访问彼此。
注意,本视频不讲端口转发等操作,端口转发会在单独讲解NAT模式的视频里讲解。有个问题,大部分人都知道这些虚拟机可以正常上网,怎么做到的呢?首先,虚拟机的数据出去,经过网关时,软件会对数据包进行改写。使得数据包像是在宿主环境里生成的,再从宿主环境经过自身的NAT转换,发送到互联网,可以简单理解为这里面有两层NAT。
现在我们来看看虚拟机里面的情况,它们都有一个私有地址,且一样,显然它们没法直接互通。接着看看它们是否能ping宿主,注意看这里虚拟机是可以ping通的宿主机IP的,毕竟是通过宿主出去的数据,但是宿主是ping不通虚拟机的。可以想象宿主对于虚拟机来说是公网,而公网是不能直接访问这些虚拟机的私有地址。NAT模式正常是只出不进的,所以我们还得测试它们的联网能力。结果肯定是没问题的。NAT模式下,虚拟机之间正常不能互通,虚拟机可以访问宿主,也可以访问物联网。但是宿主和局域网里的设备正常不能访问虚拟机,因此互联网要正常访问虚拟机就更不能了。
接下来的NAT网络模式比刚才的NAT模式多了“网络”二字,主要让虚拟机在NAT模式下都可以互通。软件在虚拟机前加了一台虚拟的交换机,为网络分配地址的虚拟DHCP服务器地址和之前不一样,网关地址也不一样。重点是这些虚拟机可以互通,因为它们都在同一个网络里。
NAT网络模式操作很简单,首先设置net网络,包括名字、网络掩码和dhcp。
设置完成后,再在虚拟机的网络模式里选择对应的nat网络名字。注意虚拟机的mac地址需要不一样,如果克隆了虚拟机,记得刷新mac地址,否则dhcp握手时可能会出问题。
进入虚拟机后,可以查看网关地址是否和我刚才说的一样,两台虚拟机显示的一样,再互相ping一下,对方没问题,说明它们在同一个网络里。现在我们就知道net网络和nat的区别了。主要是虚拟机之间可以互通,其余的和nat模式一样,可以访问互联网,但不能直接访问内部网络。
Briged Adapter桥接网卡,桥接模式听起来难,其实很简单,想象为把虚拟机放在了宿主的局域网里,这些虚拟机相当于和宿主平级,也就是说宿主在哪里获得ip地址,虚拟机也一样从那里获取。所以会消耗宿主所在局域网的ip地址。
配置方法很简单,直接选择桥接网卡模式,并选择适配器,比如数组用wifi联网,就选wifi,然后还是要确保桥接的虚拟机mac地址需要不一样。
现在我们进入虚拟机时,可以看到虚拟机和宿主的网关都是一样的。先试一下虚拟机之间能否互ping,结果肯定没问题。宿主能否ping虚拟机呢,结果也是肯定的,毕竟它们都在同一个网络里。虚拟机能否ping宿主呢,这个也必须可以。最后正常的联网测试也不会有问题。
所以桥接模式全部选项亮灯,某种程度上比前面的模式都要方便。但要注意,如果要让互联网直接访问到虚拟机,需要给虚拟机分配公网地址。
如果说桥接模式是一个极端,另一个极端就是内部网络模式Internal Network。这个模式下的虚拟机虽然可以互通,但是虚拟机不能访问宿主,更不能访问网络,可以想象虚拟机和宿主分割开来了,而且virtualbox默认不提供dhcp服务器。也就是说需要手动设置静态的ip地址。
因此在设置为内部网络前,为了不让虚拟机在启动时一直卡在dhcp服务里,建议提前设置一下虚拟机,比如可以设置ubuntu系统里的netplan文件夹下的yaml文件,添加optional为true的值。
现在我们就可以设置网络模式了,直接选择内部网络即可。这里有个默认的名字,记得让虚拟机选择同样的名字。
我们进入虚拟机以后,可以发现根本没有本机的ip地址。因此,我们需要手动配置一下,方法有好几种,比如还是一样可以设置netplan里的yaml文件,添加addresses并指定ip地址。两台虚拟机同样需要这样的操作,因此这个模式稍微有点麻烦。保存文件后重启虚拟机,重启后可以看到虚拟机已配置IP地址。按照前面理论,虚拟机之间可以互相访问,但无法ping通宿主,因为这是一个隔离的网络。因此,它们无法访问互联网,需要使用网络进行环境配置时需要使用其他模式。
桥接模式已开启后,内部网络模式几乎都关闭了,桥接模式仅让多台虚拟机互通,是一个隔离的环境。
在进行下一个模式之前,先删除刚才的静态IP地址设置,以便更清楚地了解接下来的模式。
仅主机模式Host-Only和内部网络模式非常相似,依旧是一个隔离的网络,虚拟机之间可以互通,但虚拟机依旧无法访问外部网络。虽然有DHCP服务器分配地址,但虚拟机不能直接访问宿主所在局域网的私有地址,因为它们没有设置网关,不过可以访问虚拟网卡。当然,宿主可以访问它们,宿主以外的设备都不能访问或被访问。
在设置之前,需要先像NET网络那样进行设置,创建一个仅主机网络,设置名字、子网掩码和地址范围,然后可以为虚拟机设置网络模式。选择刚才创建的名字,即可进入虚拟机。我们可以看到,虚拟机自动被分配了IP地址,不像内部网络模式需要手动配置。查看IP地址后,基本知道它们可以互通,这和内部网络模式一样。重点是它们不能直接ping宿主,没有网关让他们出去,只能访问虚拟网卡,基本在这里就被止步了。我们查看网关配置,确实没有显示,如果要访问外部网络也不行,但让宿主直接访问虚拟机是没问题的。虽然是隔离的,但没有完全隔离。里面要出去的“门”是关的,外面要进去的“门”是开的。