互联网网络传输协议理解坑点

DNS 协议的用途和解析方式是什么样的?

所有应用层层面的数据,如果需要进行网络传输,必定需要 ip 地址这个核心参数。没有 ip 地址的包,是不可能发出去的,都过不了网卡。因为网卡不知道要把这个包传到哪里去。
而 ip 地址人类很难记忆,所以很多服务都是通过域名进行访问。域名是比较方便记忆,但是网络又不认,因为网络无法根据域名进行数据传输,即域名没有定位功能。
所以所有的应用层的域名访问,都需要 DNS 协议解析成 ip 地址后才能够封包发送,ip 有定位功能。如果一个应用层服务直接通过 ip 地址访问另一个服务,那么是完全不用 DNS 做一次 ip 地址解析的。
我们的域名是需要从特定的服务商进行购买,在服务商处会进行 ip 地址的配置。而 DNS 协议的根据就是层层服务商解析,问根域,返回顶级域,问顶级域,返回权威域,这样通过.com.cn 等不同服务商的判断,最终落实并返回一个确定的 ip 地址。
DNS 协议是系统层级的操作,应用层无需关心,系统通过 DNS 协议拿到 ip 地址后会给到应用层,然后应用层将 ip 地址传递到传输层进行网络数据封包。
为了效率问题,系统会进行 DNS 的缓存以加快解析速度,并且还会设置有效期以较少误差。
比较例外的是 hosts 文件。在这里配置的信息具有第一优先级,系统如果在 hosts 中找到了对应的域名和 ip 地址的映射,则不再进行 DNS 请求而直接返回映射数据。
DNS 会有劫持问题,在移动端会使用 HTTPDNS 技术。DNS 有一个非常重要的大杀器,就是做负载均衡。

ping 和 ICMP 是怎么样的关系?

ICMP 是网络层协议,ping 是对 ICMP 的应用层实现。
ICMP 和 IP 协议属于同一层。ICMP 工作是判断网络环境,通过返回包的时间、状态等确定网络复杂度。ping 使用了 ICMP 的 “查询报文” 功能,根据返回包的时间和状态等,判断当前主机是否可以访问及延时等信息。
ICMP 还有一个功能是 “差错报文”,Traceroute 是对该功能的应用。
ping 出去的包,是不过传输层的,即直接过滤 TCP 和 UDP,到达网络层封包然后通过下层协议及网卡将数据发送出去。
之所以不过传输层,是因为过它们没有实际用途,他们还会影响到 IMCP 的核心功能即网络判断。如:如果过 TCP,那么有三次握手等,本身判断网络包状态和三次握手没有关系,TCP 的稳定传输会导致所有包都能有顺序的抵达终点,完全背离了 ICMP 的初衷。应答方,在 IMCP 层就会返回应答数据,也不会在上报到传输层。所以传输层全程都不干涉到。

DHCP 用途是什么?是怎么实现的?

DHCP 即动态主机配置协议,就是用来动态配置 IP 的。要想能够联网,不管局域网还是外网,都需要 IP。
而电脑或者手机进行网络配置的时候,不仅仅需要配置 IP,还需要配置子网掩码和网关。有一个不对,网络就白配了。
为了方便,可以通过 DHCP 协议,动态的获取 IP、子网掩码、网关等重要信息。
当我们连接到一个新的 WIFI 后,设备首先广播信息,将自己的 mac 地址及默认 ip 0.0.0.0 还有 UDP 端口发送出去,因为这个时候设备还没有 ip 地址,所以不知道发给谁,只能广播。
然后网络服务也会通过广播的方式将 ip 等信息广播出来,广播信息里面有设备的 mac 地址(牵涉到 mac 地址的用途问题了)。
设备拿到这个信息后,依旧通过 ip 0.0.0.0 回复给网络服务,说明该 ip 及相关配置信息没有问题,自己确认使用。
然后网络服务给予 ack 回执,说明确认信息欢迎加入该网络。
后面设备均使用网络服务分配的 ip 地址进行网络数据传输了。
DHCP 还会设置有效期,设备需要主动联系网络服务进行有效期的续签。比如 10 个小时的有效期,那么在有效期过去一半(50%),即 5 个小时的时候,设备会主动给网络服务发送续签的消息包,根据收到的 ack 回执里的信息更新本地配置,如新的有效期等。

一个数据包,没有端口,还能够通过网卡发出去吗?

端口是传输层所使用的,一个数据包没有端口,一样是可以发出去的。但是不能没有 ip 地址和 mac 地址。这两个缺少了,网卡那边就过不去。

TCP 的三次握手,是怎么进行的?和 Socket 有什么关系?

TCP 三次消息通话的详细流程一定要清晰的,如 bind、connect 等等,并且知道客户端在第二次握手的时候已经确定连接并且可以发送数据(也叫抢跑)。TCP 的三次握手,根本目的是为了建立一个稳定的连接。这个连接并不是客户端和服务器之间有一条通道,而是客户端和服务器端建立稳定的套接字。每个连接,客户端都会有一个套接字对应这个连接,服务器端也是一样。因为服务器端一对多的关系,所以服务器端可以有成千上万甚至数十万个套接字(理论上限很高,因为 Socket 也是文件,文件打开需要耗费资源,所以实际上限远远低于理论上限)。每个套接字里面包含客户端 ip、客户端 port、服务器端 ip、服务器端 port 四个重要信息。只有一方套接字还在,一方就可以通过这个套接字给另一方发送消息,即使对方可能收不到消息了(对方关闭服务等原因导致对方已经不存在等)。所以 TCP 的三次握手,目的是为了建立一套稳定的连接,而该稳定连接的建立,是建立在 Socket 套接字的基础上。如果三次握手还没有成功,这个套接字就不是完备的套接字,即连接中状态。通过三次握手的套接字是连接状态,即 established 状态。

TCP 三次握手的时候,有没有网络层参与?

如果对网络分层模糊,很难理解该问题的意思,会感到模糊并思考该问题表达什么意思。TCP 三次握手,是传输层的问题。那么传输层在进行数据握手数据传输的时候,一定要进行网络包的传送和接收。而网络包的传输,一定需要经过网络层、链路层、物理层,没有这些层,只有传输层的端口,这个包是发不出去的。所以 TCP 三次握手还好,四次挥手也好,HTTPS 的 SSL 安全建立也好,一定都是需要有下层才能够发包的。即网络数据包可以有下层没有上层,但不能有上层没有下层。

TCP 和 UDP 的不同?

这真是一个可大可小的问题。但是如果简单的回答 TCP 比 UDP 多了稳定的连接状态,应该不会让人满意的。
下面我说出我对 TCP 和 UDP 的理解。
首先,我们一个 TCP 或者 UDP 的网络请求包,在经过传输层封包后,后面就全部都是一样的了。
一样经过网络层,经过链路层,通过网卡把包发送出去,到集线器进行以太网数据传输,通过交换机,再通过路由器,通过中继器加强信号,通过防火墙… 大家可以看到,TCP 和 UDP 仅仅是数据包传输过程中的一角,根本不是大的角色。而这两个两角色,对外面大的世界是产生不了多大影响的,或者说没有影响。TCP 的包,还是 UDP 的包,其他层都是不管的,对于其他层来说,都是包。
我们在乎的问题是数据传输,如果一个数据,可以 biu 的一下子就可以传递到另一方,那还需不需要有 TCP 呢?比如,我们一张图片,1M 大小,如果这 1M 大小,可以通过一个包传递到云存储去,那还需要 TCP 干嘛呢?毕竟 UDP 我们也可以根据是否有回执来判断这个图片是否发送成功了。如果回执一段时间没有回来,那我们就重发嘛。
而我们之所以需要 TCP,根本原因不还是这个 1M 的图片,不能一个包直接发送过去,因为包定义最大 1500 个字节,其中还有一些是头字段。因为一个数据需要拆分成很多个包发送,所以需要关注顺序和丢失问题,这才引入了 TCP 的概念。
UDP 做了什么事情?把数据封包后通过下层再次封包之后发出去。发成功了吗?不管,如果应用层要管请自行根据超时判断。发失败了会重发吗?不管,如果应用层要管的话请自行重发。
所以你发现了没有?如果我们把 1M 的图片二进制流,分割成 1000 字节大小,共计约 1000 个包,我们应用层主动处理这 1000 个包,一定可以成功的把包发到另一方。可是这样完美吗?不完美。应用层需要大量的处理逻辑,难度极大,而且性能不佳,比如当前网络真的比较卡,应用层很多次重发都将是无效的。比如服务器网卡缓冲区因为应用层没有及时消化数据,已经满了,这个时候发再多数据根本就是失败的,服务器的网卡缓冲区装不下更多数据了啊。
So,这个时候才是伟大的 TCP 出场的时候。TCP 出场,一口气做了这五件大事:通道连接、丢包控制、流量控制、顺序控制、拥堵控制。大家对照上面的说明可以理解,TCP 是啥?不就是另一个对 UDP 补充的升级版协议嘛。TCP 把 UDP 不足的地方,通过另一个协议,全部解决了。
本身,我们需要应用层为了 UDP 的不足做全量维护,而 TCP,通过协议层面,直接帮我们做了这些事情。我们再也不用管数据发送成功不成功的问题了,因为 TCP 的重发可以帮我们处理的很好。
So,TCP 和 UDP 有啥不同?

  1. 他们只是在数据传输链里面很小的一环,他们影响不了传输过程。
  2. UDP 的不足就是 TCP 的补充。他们之间没有关系,是两套协议,但是,TCP 却完美补充了 UDP 的先天不足。
  3. TCP 是万能的而 UDP 一文不值?瞎说!很多场景,根本不需要 TCP 的高稳定性,因为高稳定性带来的代价很大。而 UDP 轻量,性能很高。比如流媒体直播场景,丢一桢没啥所谓,但是因为丢了一桢而不断重发堵塞剩下的桢和网络通道,罪过可就大了。
  4. 高稳定性用 TCP,高性能用 UDP,善长不同。
  5. 但是最终我们一定要能够理解,产生 TCP 和 UDP 两个不同协议的根本原因,在于网络包大小只能小于 1500 字节。如果一个包能够有 1M 大小,那还要 TCP 这么复杂的处理流程干嘛呢?而 TCP 和 UDP 的表现不同,只是两个协议的维护方式不同。

传输层、网络层、Mac 层(链路层)各自填补了哪些重要信息?

传输层填补了端口号。网络层填补了 IP 地址。链路层填补了 Mac 地址。
为什么需要端口号?因为操作系统需要根据端口号,将网卡缓冲区里接收到的数据通知到应用层。
为什么需要 IP 地址?因为 IP 地址才有定位功能,有了 IP 地址,数据包才能够发到指定的一台公网计算机上。
为什么需要 Mac 地址?因为 IP 地址具有定位功能,能够定位到一台公网主机上。但是在定位过程中,不全是公网,过路由器的时候,因为 IP 地址个数限制,很多时候都是一个网段的内网,而内网就需要 Mac 地址来进行通信了。
这里需要特别注明一点,IP 地址和 Mac 地址,在数据传输过程中是必不可少的,但是端口号却不是必须的。毕竟端口牵涉到传输层,而不是所有的数据包都过传输层。比如 ping 使用的 ICMP。

HTTP 和 TCP 的关系是怎么样的?啥是 Socket 套接字?

你知道巴基斯坦和卡巴斯基是什么关系吗?没错,HTTP 和 TCP 没有啥关系啊。HTTP 是应用层协议,TCP 是传输层协议,一个是客户端直接操作用于数据封包解析展示的,一个用于网络数据传输的。
But,HTTP 使用了 TCP,因为 HTTP 的包在应用层封包后,紧接着就跑到网络层继续封包。但是 HTTP 直接操作的 TCP 吗?根本没有,HTTP 直接操作的是 Socket Api。啥是 Socket Api?首先 TCP 或者 UDP 是传输层协议,他们是不能直接供外部调用的,在他们之上,还有一个叫做套接字的东西。
套接字是啥?套接字,就是操作系统用来判断数据归属哪一个程序的判断标准,套接字中有三个参数:ip 地址、传输层协议、端口号。通过这三个参数的结合,就可以实现数据的并发传输。
Socket Api 是啥?为了将这个套接字提供给应用层使用,套接字开发了一套 Api,如 bind、connect 等。应用层通过这些 Api 就可以创建稳定的套接字。
所以 Socket 是 HTTP 和 TCP 直接的纽扣,也是应用层和传输层之间的纽扣。承上启下的作用。

HTTPS 和 HTTP 的不同,HTTPS 的实现原理是怎么样的(详细说明 SSL/TLS 协议的流程)?

在协议上,最直接的区别是:HTTP 是明文传输,HTTPS 是密文传输(这是在协议上,我们也可以自己做数据加密,但是牵涉到密钥泄漏问题)。
HTTP 和 HTTPS 相比,少了一个 S,S 代表 SSL/TLS 协议,在 OSI 七层模型里面属于会话层。正是因为这一层,导致 HTTPS 会 HTTP 复杂了不是一点点,但是也安全了不是一点点。
那 HTTP 和 HTTPS 相比,除了这个 SSL/TLS 之外,还有没有其他的不同?其实还真没有。两者都是应用层协议,下层数据封包都是一致的。如果真要说还有什么不同,我们就再加上端口号不同吧。HTTP 是 80 端口,HTTPS 是 443 端口。
那么重点来了,这个 SSL/TLS 就是两者差别的全部,分析完 SSL/TLS,也就理解了两者之间的根本不同。而 SSL/TLS 也是 HTTPS 协议的安全根本所在。
SSL/TLS 几乎就是为了安全而生的,它一生都在围绕安全做各种处理。怎么才叫安全?网络数据安全有四个决定性要素:身份认证不可否认完备性保密性。后面我们来验证 SSL/TLS 是如何确定四要素的。
First of all,为什么叫 SSL/TLS 协议?SSL 是什么?TLS 是什么?其实是一个东西,SSL 从 V1 发展到 V2 然后发展到 V3 后,才正式成熟,在成熟后,SSL V3.1 被直接改名为 TLS 1.0。而后 TLS 继续开始发展,先后出了版本 1.1(2006 年)、1.2(2008 年)、1.3(2018 年)。目前使用最广泛的是 TLS 1.2,之前版本都被验证为不安全的,已经被弃用。而 1.3 比 1.2 更加安全,目前也在大范围推广。而 1.3 和 1.2 却又有很大不同(新特性)和关联,所以了解了 1.2 和 1.3,才能理解安全四要素。
安全四要素身份认证不可否认完备性保密性,该如何保障?大家肯定都知道了,文字描述起来复杂不宜懂,但是我实在不想放图片。大家既然都知道了,那就直接入正题(公私钥这块复杂不容易理解的,一定要 Google 理解清楚)。
好了,那我们总结一些,RSA 等非对称加密方式,保障了保密性。签名保障了完备性。证书保障了身份认证和不可否认。似乎都齐了,我们需要有一套证书传递逻辑,然后将数据加密,就可以完美的将数据从一端传输到另一端。
这里我们还是要提一点,加密分对称加密和非对称加密。两者耗时不在一个数量级,其中非对称加密耗时非常厉害的。所以 TLS 使用了非对称加密的方式来传输并生成对称密钥,然后用对称密钥进行数据加密传输的。而 HTTPS 用了 TLS,所以 HTTPS 的非对称加密,只是在连接开始的时候用到了,拿到对称密钥后,就不再使用非对称加密了。
总体核心流程是什么样的呢?简单描述下:
1. C——TLS 协议支持列表、C-RandomNum、RSA 密码套件 ———->S
2. S——TLS 协议确认版本、S-RandomNum、RSA 密码套件 ———->C
3. S—— 服务器证书 ———->C
4. C 验证服务器证书的有效性
5. C 生成随机数 RandomNum-Secret 随机数
6. C—— 用服务器证书里的公钥加密 RandomNum-Secret 随机数 ———->S
7. 现在,服务器和客户端,均有三个随机数了,分别是:C-RandomNum、S-RandomNum、RandomNum-Secret。两端根据同样的一套运算,计算出对称密钥:Master-Secret
8. 对称密钥已经生成完成,后面通过对称密钥通信。所有数据都会通过对称密钥加密后,才能发到另一方。另一方也通过对称密钥解密后,拿到原数据。
大家可以看到,通过上面 8 个环节,就可以建立一套对称加密的安全通道。这里需要提醒一下,生成对称密钥,共需 3 个随机数,其中前两个是明文传输的,第三个才是加密传输的。因为第三个通过公钥加密,中间人无法破解。所以对称密钥是安全的。
那上面是不是就是 TLS 安全认证的全部了呢?很抱歉,上面的通道建立方式是大家比较熟知的,也认为一直在使用的,但并不是流行的。上面走的是 RSA 的公私钥认证逻辑,但是 RSA 在一些情况下也被认为不安全(具体就要说到 TLS 1.3 了)。而非对称加密还有一个更高效更安全的方案,那就是 ECC(ECDSA、ECDHE)方案。而 ECC 才是使用的最为广泛的,甚至 RSA 已经在 TLS1.3 里面被废弃了。
所以上面流程我们先忘记,来个全新却几乎一样的新流程:
1. C——TLS 协议支持列表、C-RandomNum、ECDHE 密码套件 ———->S
2. S——TLS 协议确认版本、S-RandomNum、ECDHE 密码套件 ———->C
3. S—— 服务器证书 ———->C
4. S—— 用服务器私钥加密 ECDHE Param1———->C
5. C 验证服务器证书的有效性
6. C—— 用服务器证书里的公钥加密 ECDHE Param2———->S
7. C 根据 Param1 和 Param2 作为 ECDHE 入参,生成 Param-Secret
8. S 根据 Param1 和 Param2 作为 ECDHE 入参,生成 Param-Secret
9. C 根据 C-RandomNum 和 S-RandomNum 和 Param-Secret,生成 Master-Secret
10. S 根据 C-RandomNum 和 S-RandomNum 和 Param-Secret,生成 Master-Secret
11. 现在,服务器和客户端,已经计算出对称密钥:Master-Secret。对称密钥已经生成完成,后面通过对称密钥通信。所有数据都会通过对称密钥加密后,才能发到另一方。另一方也通过对称密钥解密后,拿到原数据。
上面才是目前市场上最普遍使用的 TLS 安全流程。因为使用的是 ECC,而 ECC 需要两个参数计算最后值,所以使用 ECC 密码套件的流程比 RSA 密码套件的流程,多了 ECDHE Param1 和 ECDHE Param2。
还有一个巧妙的,在 RSA 中,第三个参数一定要一方发给另一方,最后才能发送第一条加密数据用作验证。而 ECC 方案里面,在一方还没有确认通信的时候,另一方就可以发送第一条加密数据用作验证了。和 TCP 三次握手里面一样,在第二次握手完成,C 端就可以向 S 端发送数据包了。这个 “抢跑”,不失为 TLS ECC 密码套件和 TCP 三次握手的亮点。