前言

文本已收录至我的GitHub仓库,欢迎Star:https://github.com/bin392328206/six-finger
种一棵树最好的时间是十年前,其次是现在

叨絮

网关,路由,其实我们每个人上网都是需要的,但是具体的原理是不是得安排下。

  • 重学网络系列之(HTTP的前世今生)

  • 重学网络系列之(我的名字叫IP)

人生一世,如镜花水月,今朝姹紫嫣红,明日已成梦幻泡影。与其追忆故园芳菲,莫不如放下繁华,重觅一片竹海。一支瘦笛,一曲笑傲江湖。一弯冷月,一肩千古情仇。

ICMP和Ping

基本上我们都碰到过网络连不上的问题,那台机器明明就在那里,你甚至都可以通过机器的终端连上去看。它看着好好的,可是就是连不上去,究竟是哪里出了问题呢

一般来说我们都会想到用Ping,那你知道Ping是如何工作的吗?

ping 是基于 ICMP 协议工作的。ICMP全称Internet Control Message Protocol,就是互联网控制报文协议。这里面的关键词是“控制”,那具体是怎么控制的呢?

ICMP协议是一个网络层协议。

一个新搭建好的网络,往往需要先进行一个简单的测试,来验证网络是否畅通;但是IP协议并不提供可靠传输。如果丢包了,IP协议并不能通知传输层是否丢包以及丢包的原因。所以我们就需要一种协议来完成这样的功能–ICMP协议。

ICMP协议的功能

  1. 确认IP包是否成功到达目标地址

  2. 通知在发送过程中IP包被丢弃的原因

我们需要注意几点:

  1. ICMP是基于IP协议工作的,但是它并不是传输层的功能,因此仍然把它归结为网络层协议

  2. ICMP只能搭配IPv4使用,如果是IPv6的情况下, 需要是用ICMPv6

ICMP 协议的格式

ICMP报文包含在IP数据报中,IP报头在ICMP报文的最前面。一个ICMP报文包括IP报头(至少20字节)、ICMP报头(至少八字节)和ICMP报文(属于ICMP报文的数据部分)。当IP报头中的协议字段值为1时,就说明这是一个ICMP报文。ICMP报头如下图所示。

ping 的发送和接收过程。

假定主机 A 的 IP 地址是 192.168.1.1,主机 B 的 IP 地址是 192.168.1.2,它们都在同一个子网。那当你在主机 A 上运行“ping 192.168.1.2”后,会发生什么呢?

ping 命令执行的时候,源主机首先会构建一个 ICMP 请求数据包,ICMP 数据包内包含多个字段。最重要的是两个,第一个是类型字段,对于请求数据包而言该字段为 8;另外一个是顺序号,主要用于区分连续 ping 的时候发出的多个数据包。每发出一个请求数据包,顺序号会自动加 1。为了能够计算往返时间 RTT,它会在报文的数据部分插入发送时间。

然后,由 ICMP 协议将这个数据包连同地址 192.168.1.2 一起交给 IP 层。IP 层将以 192.168.1.2 作为目的地址,本机 IP 地址作为源地址,加上一些其他控制信息,构建一个 IP 数据包。

接下来,需要加入 MAC 头。如果在本节 ARP 映射表中查找出 IP 地址 192.168.1.2 所对应的 MAC 地址,则可以直接使用;如果没有,则需要发送 ARP 协议查询 MAC 地址,获得 MAC 地址后,由数据链路层构建一个数据帧,目的地址是 IP 层传过来的 MAC 地址,源地址则是本机的 MAC 地址;还要附加上一些控制信息,依据以太网的介质访问规则,将它们传送出去。

主机 B 收到这个数据帧后,先检查它的目的 MAC 地址,并和本机的 MAC 地址对比,如符合,则接收,否则就丢弃。接收后检查该数据帧,将 IP 数据包从帧中提取出来,交给本机的 IP 层。同样,IP 层检查后,将有用的信息提取后交给 ICMP 协议。

主机 B 会构建一个 ICMP 应答包,应答数据包的类型字段为 0,顺序号为接收到的请求数据包中的顺序号,然后再发送出去给主机 A。在规定的时候间内,源主机如果没有接到 ICMP 的应答包,则说明目标主机不可达;如果接收到了ICMP 应答包,则说明目标主机可达。

MAC头和IP头的细节

一旦配置了 IP 地址和网关,往往就能够指定目标地址进行访问了。由于在跨网关访问的时候,牵扯到MAC 地址和 IP 地址的变化,这里有必要详细描述一下 MAC 头和 IP 头的细节。

在 MAC 头里面,先是目标 MAC 地址,然后是源 MAC 地址,然后有一个协议类型,用来说明里面是IP 协议。IP 头里面的版本号,目前主流的还是 IPv4,这里到了下一层的协议,也就是,是 TCP 还是 UDP。最重要的就是源 IP 和目标 IP。先是源 IP 地址,然后是目标 IP 地址。

在任何一台机器上,当要访问另一个 IP 地址的时候,都会先判断,这个目标 IP 地址,和当前机器的 IP地址,是否在同一个网段。怎么判断同一个网段呢?需要 CIDR 和子网掩码。

如果是同一个网段,例如,你访问你旁边的兄弟的电脑,那就没网关什么事情,直接将源地址和目标地址放入 IP 头中,然后通过 ARP 获得 MAC 地址,将源 MAC 和目的 MAC 放入 MAC 头中,发出去就可以了。

如果不是同一网段,例如,你要访问你们校园网里面的 BBS,该怎么办?这就需要发往默认网关Gateway。Gateway 的地址一定是和源 IP 地址是一个网段的。往往不是第一个,就是第二个。例如192.168.1.0/24 这个网段,Gateway 往往会是 192.168.1.1/24 或者 192.168.1.2/24。

如何发往默认网关呢?网关不是和源 IP 地址是一个网段的么?这个过程就和发往同一个网段的其他机器是一样的:将源地址和目标 IP 地址放入 IP 头中,通过 ARP 获得网关的 MAC 地址,将源 MAC 和网关的 MAC 放入 MAC 头中,发送出去。网关所在的端口,例如 192.168.1.1/24 将网络包收进来,然后接下来怎么做,就完全看网关的了。

网关往往是一个路由器,是一个三层转发的设备。啥叫三层设备?前面也说过了,就是把 MAC 头和 IP头都取下来,然后根据里面的内容,看看接下来把包往哪里转发的设备。

很多情况下,人们把网关就叫作路由器。其实不完全准确,而另一种比喻更加恰当:路由器是一台设备,它有五个网口或者网卡,相当于有五只手,分别连着五个局域网。每只手的 IP 地址都和局域网的 IP地址相同的网段,每只手都是它握住的那个局域网的网关。

任何一个想发往其他局域网的包,都会到达其中一只手,被拿进来,拿下 MAC 头和 IP 头,看看,根据自己的路由算法,选择另一只手,加上 IP 头和 MAC 头,然后扔出去。

IP头和MAC头哪些变、哪些不变?

MAC 地址是一个局域网内才有效的地址。因而,MAC 地址只要过网关,就必定会改变,因为已经换了局域网。两者主要的区别在于 IP 地址是否改变。不改变 IP 地址的网关,我们称为转发网关;改变 IP 地址的网关,我们称为NAT 网关。

结合下面的图

服务器 A 要访问服务器 B。首先,服务器 A 会思考,192.168.4.101 和我不是一个网段的,因而需要先发给网关。那网关是谁呢?已经静态配置好了,网关是 192.168.1.1。网关的 MAC 地址是多少呢?发送ARP 获取网关的 MAC 地址,然后发送包。包的内容是这样的:

  • 源 MAC:服务器 A 的 MAC

  • 目标 MAC:192.168.1.1 这个网口的 MAC

  • 源 IP:192.168.1.101

  • 目标 IP:192.168.4.101 包到达 192.168.1.1 这个网口,发现 MAC 一致,将包收进来,开始思考往哪里转发。

在路由器 A 中配置了静态路由之后,要想访问 192.168.4.0/24,要从 192.168.56.1 这个口出去,下一跳为 192.168.56.2。

于是,路由器 A 思考的时候,匹配上了这条路由,要从 192.168.56.1 这个口发出去,发给192.168.56.2,那 192.168.56.2 的 MAC 地址是多少呢?路由器 A 发送 ARP 获取 192.168.56.2 的MAC 地址,然后发送包。包的内容是这样的:

  • 源 MAC:192.168.56.1 的 MAC 地址

  • 目标 MAC:192.168.56.2 的 MAC 地址

  • 源 IP:192.168.1.101

  • 目标 IP:192.168.4.101 包到达 192.168.56.2 这个网口,发现 MAC 一致,将包收进来,开始思考往哪里转发。在路由器 B 中配置了静态路由,要想访问 192.168.4.0/24,要从 192.168.4.1 这个口出去,没有下一跳了。因为我右手这个网卡,就是这个网段的,我是最后一跳了。

于是,路由器 B 思考的时候,匹配上了这条路由,要从 192.168.4.1 这个口发出去,发给192.168.4.101。那 192.168.4.101 的 MAC 地址是多少呢?路由器 B 发送 ARP 获取 192.168.4.101 的MAC 地址,然后发送包。包的内容是这样的:

  • 源 MAC:192.168.4.1 的 MAC 地址

  • 目标 MAC:192.168.4.101 的 MAC 地址

  • 源 IP:192.168.1.101

  • 目标 IP:192.168.4.101

包到达服务器 B,MAC 地址匹配,将包收进来。

通过这个过程可以看出,每到一个新的局域网,MAC 都是要变的,但是 IP 地址都不变。在 IP 头里面,不会保存任何网关的 IP 地址。所谓的下一跳是,某个 IP 要将这个 IP 地址转换为 MAC 放入 MAC 头。

上面的过程遇到的问题

大家想想看哈,局域网之间没有商量过,各定各的网段,因而 IP 段冲突了,如下图最左面的地址是 192.168.1.101,最右面的地址也是 192.168.1.101,如果单从 IP 地址上看,简直是自己访问自己,其实是 192.168.1.101 要访问 192.168.1.101

怎么解决这个问题呢?既然局域网之间没有商量过,你们各管各的,那到国际上,也即中间的局域网里面,就需要使用另外的地址。就像出国,不能用咱们自己的身份证,而要改用护照一样,而不能用自己国家的身份证。

首先,目标服务器 B 在国际上要有一个国际的身份,我们给它一个 192.168.56.2。在网关 B 上,我们记下来,国际身份 192.168.56.2 对应国内身份 192.168.1.101。凡是要访问 192.168.56.2,都转成192.168.1.101。

于是,源服务器 A 要访问目标服务器 B,要指定的目标地址为 192.168.56.2。这是它的国际身份。服务器 A 想,192.168.56.2 和我不是一个网段的,因而需要发给网关,网关是谁?已经静态配置好了,网关是 192.168.1.1,网关的 MAC 地址是多少?发送 ARP 获取网关的 MAC 地址,然后发送包。包的内容是这样的:

  • 源 MAC:服务器 A 的 MAC

  • 目标 MAC:192.168.1.1 这个网口的 MAC

  • 源 IP:192.168.1.101

  • 目标 IP:192.168.56.2 包到达 192.168.1.1 这个网口,发现 MAC 一致,将包收进来,开始思考往哪里转发。

在路由器 A 中配置了静态路由:要想访问 192.168.56.2/24,要从 192.168.56.1 这个口出去,没有下一跳了,因为我右手这个网卡,就是这个网段的,我是最后一跳了。

于是,路由器 A 思考的时候,匹配上了这条路由,要从 192.168.56.1 这个口发出去,发给192.168.56.2。那 192.168.56.2 的 MAC 地址是多少呢?路由器 A 发送 ARP 获取 192.168.56.2 的MAC 地址。

当网络包发送到中间的局域网的时候,服务器 A 也需要有个国际身份,因而在国际上,源 IP 地址也不能用 192.168.1.101,需要改成 192.168.56.1。发送包的内容是这样的:

  • MAC:192.168.56.1 的 MAC 地址

  • 标 MAC:192.168.56.2 的 MAC 地址

  • IP:192.168.56.1

  • 标 IP:192.168.56.2

包到达 192.168.56.2 这个网口,发现 MAC 一致,将包收进来,开始思考往哪里转发。路由器 B 是一个 NAT 网关,它上面配置了,要访问国际身份 192.168.56.2 对应国内身份192.168.1.101,于是改为访问 192.168.1.101。

在路由器 B 中配置了静态路由:要想访问 192.168.1.0/24,要从 192.168.1.1 这个口出去,没有下一跳了,因为我右手这个网卡,就是这个网段的,我是最后一跳了。

于是,路由器 B 思考的时候,匹配上了这条路由,要从 192.168.1.1 这个口发出去,发给192.168.1.101。

那 192.168.1.101 的 MAC 地址是多少呢?路由器 B 发送 ARP 获取 192.168.1.101 的 MAC 地址,然后发送包。内容是这样的:

  • 源 MAC:192.168.1.1 的 MAC 地址

  • 目标 MAC:192.168.1.101 的 MAC 地址

  • 源 IP:192.168.56.1

  • 目标 IP:192.168.1.101 从服务器 B 接收的包可以看出,源 IP 为服务器 A 的国际身份,因而发送返回包的时候,也发给这个国际身份,由路由器 A 做 NAT,转换为国内身份。

从这个过程可以看出,IP 地址也会变。这个过程用英文说就是Network Address Translation,简称NAT。

其实这第二种方式我们经常见,现在大家每家都有家用路由器,家里的网段都是 192.168.1.x,所以你肯定访问不了你邻居家的这个私网的 IP 地址的。所以,当我们家里的包发出去的时候,都被家用路由器NAT 成为了运营商的地址了。

如何配置路由?

路由器就是一台网络设备,它有多张网卡。当一个入口的网络包送到路由器时,它会根据一个本地的转发信息库,来决定如何正确地转发流量。这个转发信息库通常被称为路由表。一张路由表中会有多条路由规则。每一条规则至少包含这三项信息。

  • 目的网络:这个包想去哪儿?

  • 出口设备:将包从哪个口扔出去?

  • 下一跳网关:下一个路由器的地址。

例如,我们设置 ip route add 10.176.48.0/20 via 10.173.32.1 dev eth0,就说明要去 10.176.48.0/20这个目标网络,要从 eth0 端口出去,经过 10.173.32.1。

动态路由算法

在大学里面学习计算机网络与数据结构的时候,知道求最短路径常用的有两种方法,一种是Bellman-Ford 算法,一种是 Dijkstra 算法。在计算机网络中基本也是用这两种方法计算的。

  • 距离矢量路由算法

  • 链路状态路由算法

结尾

问大家几个问题

  • 当你访问www.taobao.com的时候,你发送的包需要通过NAT转换成公网ip,然后淘宝返回的数据又要从公网IP变成你的局域网IP,假设我局域网很多IP,他怎么知道哪个对应的是哪个

NAT在进行地址替换时不仅仅包含IP地址,还有端口号。具体说来就是,我们在进行连接外网服务器请求的数据包中,除了源、目的IP地址外,还有源、目的端口号。其中目的端口号是固定的,比如21或80等等。但源端口号是随机生成的。当数据包到达进行NAT的设备时,除了私有IP地址会被替换成公网IP地址外,端口号也会被替换成NAT随机生成的端口号。NAT的端口号和局域网中的主机一一对应,同时NAT设备维护一张端口号和主机对应的表。当外网服务器返回数据到NAT设备时,NAT设备通过返回数据包中的端口号找到局域网中的主机并将数据转发。这样就完整的实现了局域网主机上外网的功能。

  • 当我们网络中的包在网络中传输的时候,目标mac地址 和源mac地址的变化,目标ip和源Ip的变化。

这个答案在文章中。

参考

  • 趣谈网络

  • ICMP作原理

日常求赞

好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是真粉

创作不易,各位的支持和认可,就是我创作的最大动力,我们下篇文章见

微信 搜 "六脉神剑的程序人生" 回复888 有我找的许多的资料送给大家

重学网络系列之(Ping与网关)相关推荐

  1. 《重学Java系列》之 反射(上)

    不诗意的女程序媛不是好厨师~ 转载请注明出处,From李诗雨-https://blog.csdn.net/cjm2484836553/article/details/103350829] <重学 ...

  2. 重学JavaScript系列——(六)集合引用类型

    重学JavaScript系列--(六)集合引用类型 博主以扎实JavaScript基础为目的,以<JavaScript高级程序设计(第四版)>为核心参考资料,以一个"复习者&qu ...

  3. go 函数名之前括号中的内容_2020 重学 Go 系列:09. 一篇文章理解 Go 里的函数

    1. 关于函数 函数是基于功能或 逻辑进行封装的可复用的代码结构.将一段功能复杂.很长的一段代码封装成多个代码片段(即函数),有助于提高代码可读性和可维护性. 在 Go 语言中,函数可以分为两种: 带 ...

  4. c++ gdb 绑定源码_2020重学Go系列:30. 非常详细的 Go 语言 GDB 调试指南

    做为新手,熟练掌握一个好的调试工具,对于我们学习语言或者排查问题的时候,非常有帮助. 你如果使用 VS Code 或者 Goland ,可以直接上手,我就不再写这方面的文章了. 其实相比有用户界面的 ...

  5. 重学JavaScript系列之一_引用类型

    重学JavaScript系列之一_引用类型 ECMAScript中,引用数据是一种数据结构,用于将数据和功能组织在一起,有时候被称为类 ES6中使用Class定义一个类 引用类型的值(对象)是引用类型 ...

  6. 重学JavaScript系列——(四)变量、作用域与内存

    重学JavaScript系列--(四)变量.作用域与内存 博主以扎实JavaScript基础为目的,以<JavaScript高级程序设计(第四版)>为核心参考资料,以一个"复习者 ...

  7. 《重学Java系列》之 泛型(下)

    不诗意的女程序媛不是好厨师~ 转载请注明出处,From李诗雨-https://blog.csdn.net/cjm2484836553/article/details/103302194] 在 < ...

  8. 《重学Java系列》之 注解基础

    不诗意的女程序媛不是好厨师~ 转载请注明出处,From李诗雨-[https://blog.csdn.net/cjm2484836553/article/details/104432728] <重 ...

  9. 《重学Java系列》之 泛型(上)

    不诗意的女程序媛不是好厨师~ [转载请注明出处,From李诗雨-https://blog.csdn.net/cjm2484836553/article/details/103278750] ✍ [篇外 ...

最新文章

  1. ​老男孩教育每日一题-第105天-Linux如何设置每天凌晨三点重启nginx服务
  2. A pure java code of unrar. Decryption is supported.
  3. android 中空饼图控件,android饼状图内是空心的怎么做
  4. Asp.Net MVC4入门指南(9):查询详细信息和删除记录
  5. centos7 日志文件
  6. [原]解决win2003 iis6 部署MVC 无法访问 403 的问题
  7. Google在东京召开了一场AI座谈会
  8. access数据库拆分的用途_在Access中手动拆分数据库
  9. 网上打开与关闭gps几种方案测试,其中方案3可行
  10. win10进入bios步骤
  11. 从程序员角度看“上帝“玩游戏
  12. 看这篇就够了——ubuntu扩展屏幕及装显卡驱动后黑屏问题
  13. linux3.0字符设备驱动,linux字符设备驱动的 ioctl 幻数
  14. 微信公众号支付 使用基于thinkphp 使用微信官网的sdk
  15. vue 防止多次点击重复提交v-preventReClick
  16. 批量绘图 | EXCEL绘制基站扇区地图
  17. 统计正数和负数的个数用C语言数组,输入10个整数统计其中的正数和负数的个数,用数组实现...
  18. 技术升级 | 戴着口罩也能识别人脸啦
  19. 第三方支付“快钱”的经营策略
  20. 如何快速开发灵活自定义报表

热门文章

  1. R语言实现前向逐步回归(前向选择模型)
  2. win7连接sftp_虚拟机安装linux,与本机win7可以ping通,win7能ftp连上linux,linux能sftp本地环回地址,但flashfxp报错...
  3. 小学奥数题Java编程(2)
  4. 俄罗斯套娃(LCS)
  5. partprobe使用方法_教程方法;linux下使用fdisk结合partprobe命令不重启系统添加一块新的磁盘分区电脑技巧-琪琪词资源网...
  6. 美国俚语:Dark meat?什么意思
  7. Python算法实战视频课程--栈的应用-刘硕-专题视频课程
  8. python爬取CRMEB3.2 后台订单数据并导出excel
  9. vim vi操作文件
  10. css3动画会转动的骨头