从头学网络之--网络通信基本过程

Posted by Cooper on April 25, 2024

对于非科班出身的博主来说,计算机网络知识主要靠 伟大的 GFW 所赐,书到用时方恨少,为了能更自信地和身边的朋友交流(装13),是时候重新系统地 (瞎逛油管)学习下计网了。

从浏览器出发,到百度服务器

Screenshot 2024-04-25 at 16.11.55

当你在浏览器敲入“baidu.com“ 时:

  1. 浏览器缓存:首先,浏览器会检查自身的DNS缓存,看是否最近已解析过该域名。浏览器缓存了许多最近查询过的域名及其对应的IP地址,以加速未来访问。这个缓存只会保留一段时间。

  2. 操作系统缓存:如果浏览器缓存中没有找到对应的IP地址,浏览器接着会查询操作系统的DNS缓存。操作系统也维护了一个DNS解析的缓存。

    Chorme为例:通过chrome://net-internals/#dns 打开浏览器缓存查看

  3. 本地Hosts文件:如果在操作系统缓存中仍未找到IP地址,系统会检查本地的hosts文件。这个文件存储了域名到IP地址的静态映射,通常用于网络测试或当用户需要重写特定域名的解析结果时。

  4. DNS服务器:如果上述步骤都未能解析出IP地址,系统会向配置的DNS服务器发出DNS查询请求,以获取相应的IP地址。

    向DNS服务器发出DNS查询请求:

    1. 应用层:DNS请求是应用层的数据,它会先生成一个(请告诉我baidu.com的IP地址)的请求数据包,然后一层一层的往下传;
    2. 传输层:数据来到传输层,对数据进行端口的封装;在传输层,DNS请求通常使用UDP协议,封装数据包并分配到53号端口(DNS服务的标准端口)。
    3. 网络层:在网络层,数据包被封装IP头部信息,包括源IP和目标IP(即DNS服务器的IP地址)。
    4. 数据链路层:在这一层,数据包会被进一步封装,添加以太网头部,包括MAC地址信息等,为物理传输做准备。
    5. 物理层:最后在物理层,数据通过网络硬件如网卡发送出去,以电信号的形式通过网络到达DNS服务器。

数据包来到了路由器:

路由器从物理层接收到数据包,然后传给数据链路层,在数据链路层,解析了数据包的MAC地址信息,路由器发现目标MAC地址就是自己,然后把头部的MAC地址信息拿掉后继续传给网络层,网络层拿到数据包后,解析了源IP地址和目标IP地址。由于这里的源IP地址是内网的IP网段,不能在公网(外网)传输,此时就要用到NAT作IP地址映射。换句话说,就是将你原来的源IP地址,转换为路由器的WAN IP,再转发出去。

Screenshot 2024-04-26 at 14.12.20

然而,实际家里的路由器WAN IP地址为 192.168.1.2,明显也是个内网IP地址。这是因为我的运营商并没有给我分配公网IP,我的网络仍处于社区内的内部网络中,相当于我家路由器外面还有路由器。

假设现在数据包来到了社区网络的最外层路由器,那么它会把源IP地址转换成它的公网IP地址,目标IP地址不变,仍然为8.8.8.8;然后数据包从网络层传给数据链路层,在头部添加MAC地址信息;然后再传给物理层,物理层再通过电信号传输到互联网。

数据包来到了互联网:

数据包来到了互联网,它会经过十来个(瞎猜的)路由器,在这些路由器中跳跳跳跳…..最终,来到了目标DNS服务器。

数据包来到了目标DNS服务器:

目标DNS服务器可以将数据包解析到应用层。过程:目标DNS服务器从物理层接收到了数据包;然后传给数据链路层,数据链路层解析了上一跳路由器的MAC地址,然后把MAC头部信息拿掉;传给网络层,网络层解析了IP地址;然后传给传输层,传输层解析了端口,发现是转给自己的53号端口,发现这个数据包是想要作DNS查询,然后给这个数据包转发给DNS应用,返回相应的百度IP地址(假设为7.7.7.7)。

然后数据包又从应用层,一层一层封装到物理层,然后转发给上一跳发来的路由器……脑补往回跳的画面。

DNS服务器发出的数据包来到了浏览器:

浏览器接收了DNS服务器发回来的数据包,并知道了百度的IP地址,然后浏览器会重新构建一个请求:请求百度的首页,这是一个http协议的请求数据包,该数据包传到传输层封装端口,源端口随机起一个,目标端口为80(http协议默认的端口),然后传到网络层,此时目标IP为百度的IP,后面的步骤与DNS请求的发送过程类似,不再赘述。

百度服务器接收了来自浏览器的数据包:

百度服务器在接收了来自浏览器的数据包后,然后将百度的首页信息打包,通过http协议将数据包返回,直至浏览器接收,过程脑补。

使用Wireshark抓包分析

为了深入理解DNS查询过程,这里使用Wireshark 进行抓包分析,环境为MacOS中的虚拟Windows系统。

准备工作

首先,清除系统的DNS缓存:

1
ipconfig /flushdns

Screenshot 2024-04-26 at 18.50.32

查看本机IP:

1
ipconfig

Screenshot 2024-04-26 at 18.52.06

查看本地DNS服务器:

1
ipconfig /all

Screenshot 2024-04-26 at 18.48.28

查看百度域名对应的IP地址:

1
nslookup wwww.baidu.com

Screenshot 2024-04-26 at 18.53.22

DNS报文格式

image-20240427180006759

整个DNS报文格式主要分为 3 部分内容,即基础结构部分问题部分资源记录部分。(对报文格式的具体分析,请查看下面抓包数据分析)

抓包操作

① 使用wireshark抓取网络请求包,启用开始捕获

② 访问www.baidu.com网址(使用ping命令模拟访问域名)

③ 查看抓包数据(记得保存抓包数据,便于后续分析)

DNS请求报文

image-20240427034332021

请求报文分析

可以看到,网络传输层使用 UDP 协议,源端口为63300,目标端口为53。

DNS报文基础结构部分

每个字段含义如下。

  • 事务 ID(Transaction ID):DNS 报文的 ID 标识。对于请求报文和其对应的应答报文,该字段的值是相同的。通过它可以区分 DNS 应答报文是对哪个请求进行响应的。
  • 标志(Flags):DNS 报文中的标志字段。
  • 问题计数(Questions):DNS 查询请求的数目。
  • 回答资源记录数(Answers RRs):DNS 响应的数目。
  • 权威名称服务器计数(Authority RRs):权威名称服务器的数目。
  • 附加资源记录数(Additional RRs):额外的记录数目(权威名称服务器对应 IP 地址的数目)。

    其中Flags字段中每个字段的含义如下:

  • QR(Response):查询请求/响应的标志信息。查询请求时,值为 0;响应时,值为 1。
  • Opcode:操作码。其中,0 表示标准查询;1 表示反向查询;2 表示服务器状态请求。
  • AA(Authoritative):授权应答,该字段在响应报文中有效。值为 1 时,表示名称服务器是权威服务器;值为 0 时,表示不是权威服务器。
  • TC(Truncated):表示是否被截断。值为 1 时,表示响应已超过 512 字节并已被截断,只返回前 512 个字节。
  • RD(Recursion Desired):期望递归。该字段能在一个查询中设置,并在响应中返回。该标志告诉名称服务器必须处理这个查询,这种方式被称为一个递归查询。如果该位为 0,且被请求的名称服务器没有一个授权回答,它将返回一个能解答该查询的其他名称服务器列表。这种方式被称为迭代查询。
  • RA(Recursion Available):可用递归。该字段只出现在响应报文中。当值为 1 时,表示服务器支持递归查询。
  • Z:保留字段,在所有的请求和应答报文中,它的值必须为 0。
  • rcode(Reply code):返回码字段,表示响应的差错状态。
    • 当值为 0 时,表示没有错误;
    • 当值为 1 时,表示报文格式错误(Format error),服务器不能理解请求的报文;
    • 当值为 2 时,表示域名服务器失败(Server failure),因为服务器的原因导致没办法处理这个请求;
    • 当值为 3 时,表示名字错误(Name Error),只有对授权域名解析服务器有意义,指出解析的域名不存在;
    • 当值为 4 时,表示查询类型不支持(Not Implemented),即域名服务器不支持查询类型;
    • 当值为 5 时,表示拒绝(Refused),一般是服务器由于设置的策略拒绝给出应答,如服务器不希望对某些请求者给出应答,,或者服务器不希望进行某些操作(比如区域传送zone transfer);
    • 6-15 保留值,暂时未使用。

DNS报文问题查询部分

每个字段含义如下:

  • 查询名(Name):一般为要查询的域名,有时也会是 IP 地址,用于反向查询。
  • 查询类型(Type):DNS 查询请求的资源类型。通常查询类型为 A 类型,表示由域名获取对应的 IP4 地址。(更多类型如 AAAA,CANME,SOA,PTR,NS 等)
  • 查询类(Class):地址类型,通常为互联网地址,值为 1。

那么,对于上面报文内容,翻译过后的意思就是,“该报文为标准查询(Opcode=0)请求(QR=1)报文,向本地域名服务器( IP 报文中目的地址为本地域名服务器地址,在上面准备工作中已经知道了)请求查询,发起请求内容为 ‘获取www.baidu.com (Name=www.baidu.com)所对应的IP4地址(Type=A)’,期待本地域名服务器递归查询(RD=1)请求”

DNS响应报文

image-20240427035234523

响应报文分析

对比请求报文发现,响应报文“基础结构部分”和请求报文结构对应相同,并返回字段说明服务器支持递归查询(RA=1),服务器响应记录的名称服务器为非权威服务器(AA=0),产生了1条响应记录(Answers RRs = 1),响应报文中多了answers字段且有1条数据

响应报文中,Queries字段完全和请求报文相同,answers字段为DNS资源记录部分的内容。

DNS资源记录

每个字段含义如下:

  • Name:DNS 请求的域名。
  • Type:资源记录的类型,与问题部分中的查询类型值是一样的。
  • Class:地址类型,与问题部分中的查询类值是一样的。
  • Time to live:生存时间,以秒为单位,表示资源记录的生命周期,一般用于当地址解析程序取出资源记录后决定保存及使用缓存数据的时间。它同时也可以表明该资源记录的稳定程度,稳定的信息会被分配一个很大的值。
  • Data length:资源数据的长度。
  • 资源数据:表示按查询段要求返回的相关资源记录的数据。(如 Address :IP地址,CNAME:服务器别名 ,等)