[Linux网络_70] ARP协议 | RARP | DNS | ICMP协议
目录
1.ARP协议
ARP 流程
ARP 请求
ARP应答
总结
APR 中间人欺骗
2.DNS
开放式问题
3.ICMP协议
3.1ping命令
2.2traceroute命令
先把问题本身解构,然后再谈细节
- ARP 根据目的ip找并转化为mac的协议
- RARP 根据目的Mac找ip
- DNS 域名解析
- ICMP 检测网络通畅,发arp请求包测试
1.ARP协议
- 虽然我们在这里介绍ARP协议, 但是需要强调,
- ARP不是一个单纯的数据链路层的协议, 而是一个介于数据链路层和网络层之间的协议
ARP数据报的格式
ARP协议是在一个局域网中,对一个陌生的主机,让路由器获取目标主机的MAC地址的协议。
- ARP协议,根据目的IP地址,得到目标主机的MAC地址,获得对方主机的MAC地址之后,在发送MAC帧
- 所以ARP协议的原理是什么呢?还是先讲故事,然后画图理解。
举个栗子:
网络寻址过程类比(IP→MAC)
- 角色映射
-
- 校长 → 外部网络
- 张三老师 → 路由器
- 教室 → 局域网
- 学号 → IP地址
- 姓名 → MAC地址
- 奖状 → 数据报文
- 核心流程
▩ 当校长(外部网络)下发奖状(数据报文)时,只标注学号(IP地址)
▩ 张三老师(路由器)在教室(局域网)中广播询问:"12号同学是谁?"(ARP请求)
▩ 王五同学(目标主机)举手回应:"我是12号,MAC地址是xx:xx:xx"(ARP响应)
▩ 张三老师建立「学号-姓名」映射表(ARP缓存表),后续可直接通过姓名(MAC地址)传递数据 - 技术对应
[!NOTE]
"教室内的喊话" = ARP广播请求
"举手应答" = ARP单播响应
"小本本记录" = ARP缓存表(有效期约2分钟)
"校长发奖状" = 网络层基于IP地址的通信
从刚才得故事我们得到一个简单得结构,当得到一个数据报文想要交给目标主机的时候,我得先做一次根据IP地址得到MAC地址的过程。
- 因为路由器收到一个千里迢迢来的数据报文,路由器只知道这个数据包要去的IP地址,并不清楚目的主机的MAC地址。
- 路由器必须要知道目的主机MAC地址,因为路由器要把IP报文重新封装MAC帧。
- 必须要添加源MAC地址和目的MAC地址,然后将MAC帧交付给目标主机。
下面具体了解ARP协议工作流程。
- 假设主机1是一个路由器,其实它也是一个局域网中的设备,连接一个外网,其中有数据从外网中转发到路由器中。
- 现在路由器收到一个报文,这个报文只包含它要去的目的IP,比如说IP7,可是路由器不一定能认识整个局域网所有主机。
- 所以可能它并不认识IP7,怎么办呢?
- 没关系,路由器在数据链路层封装一个ARP请求,向局域网广播一条消息,我是主机1,在座各位谁是IP7,如果你是就把你的MAC地址给我。
- 所有人都收到,但是只有主机7的IP地址是IP7,所有主机7把ARP请求处理之后在响应一个ARP应答,我是主机7,我的IP地址是IP7,我的MAC地址是M7
- 现在我告诉你了,我就直接发送给路由器。进而路由器知道IP7的MAC地址
然后把IP报文封装成MAC帧发给主机7。
总结:
- ARP请求阶段,先在局域网内广播
- ARP应答,目标主机一对一发送给请求方主机
ARP协议是在MAC帧上面的
所以MAC帧有效载荷里面不仅能包含IP数据报文,也能包含ARP请求/应答
下面具体认识一下ARP报文的格式
- 注意到源MAC地址、目的MAC地址在以太网首部和ARP请求中各出现一次,对于链路层为以太网的情况是多余的,但如果链路层是其它类型的网络则有可能是必要的。
- 硬件类型指链路层网络类型,1为以太网;
- 协议类型指要转换的地址类型,0x0800为IP地址;
- 硬件地址长度对于以太网地址为6字节(MAC地址长度);
- 协议地址长度对于和IP地址为4字节(IP地址长度);
- op字段为1表示ARP请求,op字段为2表示ARP应答。
这里可能会有一些疑惑,为什么会有目的以太网地址,我为什么要发起ARP请求,因为我不知道你的MAC地址是多少,当前不认识,那这个目的以太网地址填多少呢?
- 所以在ARP请求的时候并不知道对方MAC地址,但目的IP地址可以填。
- 目以太网地址没办法填了,但没关系,可以填充全F,代表你并不知道对方MAC地址是多少。所以一般用全F表示该字段并为设置概念。
ARP 流程
ARP 请求
下面结合ARP数据包格式再来理解一下工作流程
ARP上面没有了,MAC帧可能把ARP请求直接交给ARP,也有可能直接把数据帧直接交给IP
- 现在一个数据包千里迢迢送到主机1(路由器),但主机1只知道数据包目的IP是IP7,它想把数据包发送给IP7,可是这个报文向下交付必须要经过MAC帧要重新添加IP7对应的MAC地址,可是目前主机1并不知道IP7的MAC地址。
- 所以上层网络层来发起ARP请求,这个发起仅仅是调用了一下函数,不交给它数据。
构建好ARP请求是把ARP请求直接发送到网络中吗?
- 并不是,虽然ARP属于链路层,但是它其实是属于MAC帧协议的上层协议,所以ARP请求发送到局域网中,必须将ARP向下交付到数据链路层的MAC帧协议。添加MAC帧的报头。形成MAC帧然后才能发送到局域网。这才是在网络中发送的ARP请求。
细节
这个ARP请求最终都会被局域网中的所有主机在MAC帧层全部都要收到, 问题是:收到之后要不要处理报文(解包+向上交付)呢?
- 要!,因为这个目标MAC地址是全F,所以所有主机全部都能收到,收到之后这个MAC帧之后,提取MAC报头的目的MAC地址发它是广播的
- 然后去掉MAC报头,根据帧类型0806向上交付给ARP。
所以结论是局域网内所有主机都要处理这个ARP请求!
那交付给ARP之后,主机要先看ARP数据报那个字段呢?先看目的IP?
- 那就先看目的IP,发现这个目的IP和我自己IP地址不一样,就把这个请求直接丢弃, 我这样干,局域网中所有不是目的IP7的所有主机这样干。
- 在ARP层把这个请求丢弃。
问题是:主机1可能向主机7发信息,注定主机1要知道主机7MAC地址。
主机7未来也可能向主机1发信息,所有主机7也可能要知道主机1的MAC地址。
所以主机7也可能向主机1发送ARP请求,所以主机7可能
- 收到ARP请求
- 曾经向别人发起过ARP请求,所以别人也可以会主机7进行ARP应答
换句话说,任何一台主机收到一个ARP,可能是ARP请求,可能是ARP应答。
我们发现MAC帧协议的设计,ARP请求和应答类型都设计成0806.
所以先看目的IP主机,你怎么知道这个ARP是请求还是应答??
- 所以先看目的IP不对!任何一台主机在进行ARP请求时我们永远都是先看op,op是1说明是ARP请求,然后再看目的IP,不是我就丢弃。
所以现在目的IP不是IP7的局域网中所有主机都先看op,发现op是1,说明是ARP请求 ,然后再看目的IP不是我,就直接丢弃。
- 主机7数据链路层先收到这个ARP请求,发现目的MAC是广播的,所以报头和有效载荷分离,再看帧类型发现是0806,然后交给ARP。
- 主机7先看op是1,说明是请求,然后看目的IP是IP7,不就是说自己吗,发现MAC1向我发起请求了。
ARP应答
接下来就是给MAC1 ARP应答。
细节
前四个字段不变,op填2表示是ARP应答, 发送端MAC地址是我自己MAC7,发收端IP地址也是我IP7,目的以太网地址现在知不知道?
- 当然知道,我现在是在做ARP应答,一定是我曾经收到ARP请求了,而请求的时候对方早已经把它的MAC地址和IP地址给了我,所以目的以太网地址直接填MAC1,目的IP地址直接填IP1。
- 至此构建好一个ARP应答。
- 然后向下交付给数据链路层,添加MAC帧报头,这个时候已经知道给谁应答,知道对方MAC地址,IP地址等其他。直接在MAC帧报头填上即可。
这样MAC帧报头就填加好了。然后再发送到局域网中。
这个应答所有主机都能收到吗?都能!收到之后会不会做处理(对报文解析后向上交付)?
不会!,因为主机在数据链路层判断时发现目的MAC地址不是自己就直接丢弃。最后只有主机1收到了。收到做报头和有效载荷解析,发现目的MAC地址不就是我吗,然后帧类型是0806,然后将有效载荷交给上层ARP。
主机1先看op发现是2,说明是ARP应答,然后直接提取ARP中发送端MAC地址。 并且这个MAC地址对应的IP地址是IP7。自此主机1就得知了IP7所对应MAC地址是MAC7。自此完成一次ARP请求和响应整个过程。
总结
所以ARP协议在整个局域网里,所有主机做法都一样,抓取数据包先看帧类型, 帧类型0806交给ARP,每一个主机在自己ARP层永远只先看op,先确认是请求还是应答,如果是请求并且是给我的就给别人构建ARP响应,否则就丢弃。
- 如果是应答就直接提取发送端以太网地址和发送端IP地址,构建对应关系,就知道对方的MAC和IP地址了。
- 现在一个主机得到另一个主机的IP和MAC地址,那局域网上所有主机想要互相通信时,在通信之前都可以这样做得到对方MAC地址。
- 所以回到刚才场景,数据包到达入口路由器主机1,可是入口路由器并不知道IP7的MAC地址是谁,所以进行ARP之后,现在知道IP7对应的MAC地址了,所以自此对IP数据包重新封装成真正的数据帧,帧类型是0800,然后发送给主机7。
现在我们在把整个网络发送拉通一下:
- 当一个数据经过路由选择到入口路由器处, 入口路由器只知道目的主机的IP地址
- 我们能确定的是路由器里面配的有目的网络和子网掩码,而且对应的网络和路由器是直接相连的
- 拿着目的主机的目的IP和路由器的子网掩码按位与,发现你这个主机一定在这个局域网
- 可是路由器只知道目的IP,没关系在局域网内ARP找到你的MAC地址
- 然后封装成数据帧,单向的交给主机D,就完成了找到目标网络和目标主机,数据就可以交付了。
难道整个网络就只会在最后入口路由器发生吗?
- 刚开始的时候,主机A要把数据交给路由器A,那主机A可能不知道路由器A的MAC地址,只知道路由器A的IP地址,所以当主机A想转发一个数据包时,主机A也工作在网络层,也有自己的目的网络和子网掩码,从上面交过来的报文也有自己的目的IP
- 所以在主机A在自己的路由表查的时候并不认识这个目的IP是谁,但是根据目的IP和子网掩码按位与,对比和自己直连的局域网发现两个目标网络不相等,立马判断我要发送的目的主机和我不再同一个局域网
- 所以虽然我不知道你在哪,但我知道谁知道,路由器知道。
- 在我的路由表中也配置了下一跳路由IP地址,但是我并不知道路由器的MAC地址,所以封装ARP请求得到路由器的MAC地址,然后封装成MAC帧交给路由器。
- 路由器在转发的时候发现也可能去某个目标网络,找到下一跳路由器,但是也不认识下一跳路由器MAC地址
没关系在路由器和路由器之间也可以ARP找到目标路由器。
所以ARP过程可以在网络通信过程中,伴随着网络通信一直在进行。
- 其次一个局域网顶多上百台机器,只要我有子网掩码那局域网所有可能的IP地址都能构建起来,所以作为一个路由器是不是可以简单粗暴向和我处在同一个局域网所有主机,全部发起ARP请求,最终路由器不就得到了和我之间相连的所有主机的IP地址和MAC地址,所以在路由器中就能够知道周边所有主机的情况。
- 因为有ARP的存在,所以允许路由器,如果是一堆路由器可以彼此发现,然后结合对应的IP地址构建出更加详细的网络转发路由表结构。
现在我知道主机D对应目标MAC地址了,下一次来的数据包去的还是主机D,难道每一次都要进行ARP请求吗?
ARP过程是一个稍微繁琐的过程,所有并不是,ARP的结果,会被暂时缓存起来的。
- 第一次不认识,进行ARP,第二次直接查缓存表,就找到MAC地址直接发就行了。
这个缓存,一是暂时,二叫缓存说明可能被丢弃。 - 每台主机都维护一个ARP缓存表,可以用arp -a命令查看。缓存表中的表项有过期时间(一般为20分钟),如果20分钟内没有再次使用某个表项,则该表项失效,下次还要发ARP请求来获得目的主机的硬件地址
为什么会自动清掉?
- 因为局域网中IP地址会变的,可能这个主机你关机了下次重新申请时IP地址就变了,所以IP和MAC地址映射关系就变了。
- 如果你愿意可能网卡换了那MAC地址也就换了,如果永久性保存ARP缓存,那么这个主机换完网卡就可能永远上不了网了。
其实还有一种情况,可能我们只知道对方MAC地址,不知道IP地址。
RARP逆地址解析,一定比ARP更简单,因为已经知道对方MAC地址了,直接给对方发让它把自己的IP地址给我。MAC->IP。
APR 中间人欺骗
再谈最后一个话题 ,ARP是可以缓存的。主机1要把数据跨网络送到另一台主机,首先要先把数据送到路由器。
- ARP缓存会定期更新,并且有一个特点,当ARP收到多个ARP应答时,ARP会以最新的为主!
- 假设今天主机1已经缓存过了知道路由器IP和MAC对应关系了。 现在有一个中间人主机3偷偷摸摸来到这个局域网,主机3伪造了一种ARP应答,ARP没有记忆,它也不知道自己请求多少次,所以主机3直接给主机1直接应答,我是IP4,我的MAC地址是MAC3。IP地址和MAC地址都是一堆数字本身并不能辨别。所以主机3给主机1发送大量的ARP应答。
主机1扛不住了最后就更新了ARP缓存,IP4:MAC3。路由器内部肯定也维护了更多的主机对应的IP地址和MAC地址信息。
同理,主机3向路由器发起大量ARP应答,我是IP1,我的MAC地址是MAC3。路由器也扛不住了,也更新了ARP缓存,把IP1对应的MAC1换成MAC3。 -
所以从此往后,主机1想向外网发信息,它把自己的数据发给路由器,它ARP缓存里有对应路由器的IP和MAC对应关系,IP4:MAC3,所以直接在数据链路层封装MAC帧,不过目的MAC变成了MAC3,所以数据直接就交给了中间人主机3 - 中间人主机3,冒充主机1,IP地址不变把数据包转发给路由器,
因为路由器在自己IP层之上包括IP层已经将MAC帧报头去掉了,所以其实在网络层及往上看到的报文完全都是一样的,就好像这个报文直接从主机1过来了。
同理当外网来的应答到了路由器发现是要给IP1的,然后查ARP缓存发现IP1:MAC3,所以封装成MAC帧交给主机3,主机3收到报文之后再把报文交给主机1。
自此主机收到应答,主机1和路由器就正常通信,因为IP及其以上的报文完全一样。可是它们俩并不知道在局域网中隔墙有耳,有人成功的成为你们两个人的中间人,这就叫做ARP欺骗。
所有上层所有的http的数据,各个报文最终不就是发送到网络里的数据帧吗,所有只要把你欺骗了,
最终你所有报文我都能收到,包括http里面的数据。
然后中间人当然了篡改了,所以需要有证书,对称密钥,非对称密钥,数字摘要让中间人即便拿到了也没办法。
现在为止我们已经懂了不同层的有不同的功能就表现出不同特性解决不同的问题,数据链路层+网络层+传输层,下三层组合就已经能保证数据从主机A可靠的跨网络送到主机D
- 可是送完还不够,还要把数据用起来,所以还需要应用层
- 根据TCP的端口号交付给应用层,而应用层是以进程为表现形式的
- 所以就可以做到把一个进程的数据经过网络可靠的转发到另一个主机上特定的进程来完成网络通信的进程间通信原理! 这就是TCP/IP。
TCP/IP是脱胎于OSI七层标准模型的。OSI七层标准定的非常完善
- 会话层主要是用来进行连接管理,以前我们在写网络版本计数器套接字的时候,建立好的连接当不通信了上层就把它关了,有没有一种可能连接建立好了但长时间不用,那应用层是不是要自己做一些连接管理。
- 所以连接管理的工作在会话层是需要的,一般由应用层来做,只不过我们没直接做罢了。
- 所以会话层对连接负责我们要需要有的。只不过在TCP/IP没有体现出来,因为由应用层完成。
- 其实表示层我们也曾经学过,什么是固有格式,这不就是自己定义好的协议字段吗,请求request,响应response,然后序列化+反序列化,这不就是表示层吗。
- 当数据反序列化拿到结构化数据之后,然后才在上面应用,针对特定应用的协议完成特定的功能。这叫做应用层。
所以会话层,表示层我们没有直接见过,但是在我们的代码里早就遇到过了。
2.DNS
DNS是一整套从域名映射到IP的系统。
- 域名是我们经常用的如www.baidu.com等,我们学了套接字和网络原理我们知道其实在网络通信里我们根本就不用域名,用的都是IP地址
- 而事实上在公网中进行网络通信只能用IP地址,因为网络协议栈里只有IP,所以域名这个东西并不是网络协议栈中必有的东西,可是现实生活中我们确实不是用的IP地址,访问百度用的从来都是域名。
- 原因在于IP地址是数字,数字对于机器很友好,对人非常不友好。
让你按照数字去访问别人网址记不住,不如用这个域名。域名存在的价值便于互联网商业化。
DNS背景
TCP/IP中使用IP地址和端口号来确定网络上的一台主机的一个程序. 但是IP地址不方便记忆.
于是人们发明了一种叫主机名的东西, 是一个字符串, 并且使用hosts文件来描述主机名和IP地址的关系.
最初, 通过互连网信息中心(SRI-NIC)来管理这个hosts文件的.
- 如果一个新计算机要接入网络, 或者某个计算机IP变更, 都需要到信息中心申请变更hosts文件.
- 其他计算机也需要定期下载更新新版本的hosts文件才能正确上网.
这样就太麻烦了, 于是产生了DNS系统.
- 一个组织的系统管理机构, 维护系统内的每个主机的IP和主机名的对应关系.
- 如果新计算机接入网络, 将这个信息注册到数据库中;
- 用户输入域名的时候, 会自动查询DNS服务器, 由DNS服务器检索数据库, 得到对应的IP地址
当用户输入域名时,会先问离自己最近域名服务器集群,问不到这些机器然后继续向上问,可能直接问道根域名服务器,如果有的话递归返回。
所以域名服务器就像一个多叉树的结构。最上面有一个根节点。
至今, 我们的计算机上仍然保留了hosts文件. 在域名解析的过程中仍然会优先查找hosts文件的内容
cat /etc/hosts
域名简介
主域名是用来识别主机名称和主机所属的组织机构的一种分层结构的名称.
www.baidu.com
域名使用 . 连接
- com: 一级域名. 表示这是一个企业域名. 同级的还有 “net”(网络提供商), “org”(非盈利组织) 等.
- baidu: 二级域名, 公司名.
- www: 只是一种习惯用法. 之前人们在使用域名时, 往往命名成类似于ftp.xxx.xxx/www.xxx.xxx这样的格式, 来表示主机支持的协议
域名解析过程大家自行搜索资料. 可以参考之前 TCP/IP 的讲解文章
使用 dig 工具分析 DNS 过程
安装 dig 工具
sudo apt install dnsutils
之后就可以使用 dig 指令查看域名解析过程了.
dig www.baidu.com
更多 dig 的使用方法,请点击了解。
浏览器中输入url后一敲回车,拿到首页,请描述整个过程发生的事情
这是一个经典问题. 一个问题就可以考察网络学的怎么样, 并且这是一个开放式问题,没有固定答案, 越详细越好. 可以参考:
浏览器中输入url后,发生的事情
开放式问题
一般在系统和网络中有很多这种开放式问题,或者口头上问你:你怎么理解指针?
- 这个时候虽然自己知道很多,但是好像不知道怎么给别人怎么谈,是先说概念还是应用场景,还是说指针的问题。
- 别人就想看你怎么给别人解释。所以对我们来讲对于回到开放式问题,并不是回答问题本身。而是要先想清楚这个问题你该怎么回答。
- 对于这种开放式问题,我们可以告诉首先告诉他,我想谈这种技术点的那些方面。比如,还是问你怎么理解指针?
我打算从如下几方面谈一谈关于指针的问题,第一指针概念,第二指针应用场景,第三指针常见问题。
- 第一指针概念,什么是指针?为什么有指针?等等。
- 第二指针应用场景,谈谈指针怎么用,如何传参,指针和数组之间的关系,包括特殊指针有那些。
- 第三指针常见的问题,野指针如何产生怎么解决等等。
当先把问题本身解构,然后再谈细节。这样回答是非常有条理的。 然后会觉得你的知识成体系了。
对于浏览器中输入url后一敲回车,拿到首页,请描述整个过程发生的事情。
- 通常先交代自己想怎么回答这个问题,一般建议分两方面,一站在纯应用层去解释这个问题,忽略掉OS为我们做的网络通信的所有细节。
- 把整个应用层结束完毕之后,我们在谈一谈底层通信的其他细节问题。
- 纯应用层当然介绍的是http请求和响应,请求格式有那些,响应格式有那些,然后通信之前建立好连接之后,双方就可以交换请求和响应了,当然请求之前有可能某些客户端比如浏览器先做域名解析找到IP在构建请求想目的IP和目的端口发起http请求。
- 然后给响应。然后再谈请求和响应里面常见的字段状态码,cookie等。
- 然后建立连接的过程,发请求和响应的过程可能面临各种各样技术通信细节问题
- 比如可能发生数据丢包问题,网络拥塞问题,数据路由的问题,路由过程中主机和子网问题,
- 确认子网划分问题,路由查找问题,确认到下一跳ARP过程等。
还可以说如果细节太多影响时间欢迎随时打断我。
这样回答体现出:
- 知识体现划分
- 沟通表达能力
- 考虑时间问题
3.ICMP协议
ICMP协议是一个 网络层协议
一个新搭建好的网络, 往往需要先进行一个简单的测试, 来验证网络是否畅通;
但是IP协议并不提供可靠传输. 如果丢包了, IP协议并不能通知传输层是否丢包以及丢包的原因.
我们一直谈的是网络通信功能,但如果网络出问题了是不是也要支持我们进行故障排查的功能。
所以IP协议不仅仅有通信能力,还要帮我们进行故障排查。
ICMP功能
ICMP正是提供这种功能的协议; ICMP主要功能包括:
- 确认IP包是否成功到达目标地址.
- 通知在发送过程中IP包被丢弃的原因.
- ICMP也是基于IP协议工作的. 但是它并不是传输层的功能, 因此人们仍然把它归结为网络层协议;
- ICMP只能搭配IPv4使用. 如果是IPv6的情况下, 需要是用ICMPv6;
ICMP的报文格式
关于报文格式, 我们并不打算重点关注, 稍微有个了解即可
ICMP大概分为两类报文:
- 一类是通知出错原因
- 一类是用于诊断查询
3.1ping命令
- 注意, 此处 ping 的是域名, 而不是url! 一个域名可以通过DNS解析成IP地址.
- ping命令不光能验证网络的连通性, 同时也会统计响应时间和TTL(IP包中的Time To Live, 生存周期).
- ping命令会先发送一个 ICMP Echo Request给对端;
- 对端接收到之后, 会返回一个ICMP Echo Reply
ping命令基本原理其实很简单,就是构建出不同生命周期报文,把TTL设置为1、2、3等等,比如说第一次TTL设置为1,然后ICMP报错,然后在构建一个报文TTL设为2 在发,最后知道对方主机收到了,通过这样的方式不就探测了从当前主机到远端主机需要经过多少跳数的路由器。
ping命令底层是通过使用ICMP协议,设置TTL跳数,然后进行检测网络连通性的一种做法。
一个值得注意的坑
有些人可能会问: telnet是23端口, ssh是22端口, 那么ping是什么端口?
千万注意!!! 这是圈套
ping命令基于ICMP, 是在网络层. 而端口号, 是传输层的内容. 在ICMP中根本就不关注端口号这样的信息.
2.2traceroute命令
能够打印出从当前主机到目的服务区所经过的路由器的IP地址。
也是基于ICMP协议实现, 把TTL设置1、2、3等等发起多次ICMP,每个ICMP最终都要给我应答,所以最后再ICMP返回时把路上路由器信息返回给我。