继续来做(da)推(guang)介(gao)我自己的!由于这两年接触到了比较多的这方面的知识,不想忘了,我决定把他们记录下来,所以决定在GitBook用半年时间上面写下来,这是目前写的一节,目前已完成了九篇啦。后面会在gitbook上不断更新,欢迎大家star,主要是在写完之前欢迎各位给出指正的意见。最最重要的,地址在这里:https://www.gitbook.com/book/rogerzhu/-tcp-udp-ip/,或者在gitbook上搜索“三十天学不会TCP,UDP/IP编程”。

觉得我要以一个真实的故事来开始这一部分。在我上大二的时候,突然从某一天开始,我们那层连着的6个寝室全都不能上网了,但是有时候又能短暂的上一会儿网,没有规律。不过有一个同学例外,虽然他也处在这6个寝室之中,但无论何时他都能上网。我们很苦闷,于是他那段时间挨个寝室炫耀自己可以上网。就这样过了大约一个星期,后来他们寝室另外三个人突然发现一个规律,只要这个同学没有插网线我们就能上网,只要他一插网线我们就全完了。在用他的电脑做了几次开关机时间之后,我们确认了这个事实。这是个不得了的发现呐,考虑到之前他太高调了,我们6个寝室的人勒令他不允许开电脑,哈哈。但是我们还是有良心的,开始在网上搜索资料,后来架不住人(mei)多(wang)力(shang)量(bu)大(xing),我们在茫茫互联网资料中,搜索到了两个词“arp欺骗”和“arp病毒”。特别是想到那位同学前几天炫耀的表情,在兴(fen)趣(nu)的指引下,我们认真学习了其原理,确认了确实是那位同学的锅。然后下载了个杀毒软件,给那位同学的电脑彻底的杀毒,从此上面的现象再也没有出现过了。而且在后面长达一周的时间内,我们每天必做的一件事就是去问候一下那位同学,哈哈。

ARP是什么?

ARP学名Address Resolution Protocol,从英文上看意思已经跃然纸上了。地址解析协议,解析啥呢,解析IP地址到MAC地址。为什么要这么做呢,因为两个计算机通信本质上是通过MAC地址来识别对方的。我觉得在避免陷入一个协议复杂的细节之前,可以先从一个宏观上面弄明白协议的整个流程是什么样的,是时候再一次献上我的手绘版了。

ARP协议主要在两个场景下有所使用,第一个犹如图中绘制的,某一段想向另一端发送数据包之前,需要通过ARP协议来知晓对方的的地址,具体用文字描述就是如下:

首先,发送端会发出一个ARP请求以太网报文,由于现在发送端还不知道对端的MAC地址,所以ARP的请求报文利用了链路层广播,使得局域网内所有的主机都能接受到这个信息,这就像我们小时候站在别的班教室门口找人一样,大喊,谁谁谁,有人找你,所有人都能听到,但是只有正确的谁谁谁才会发出响应。

按照这个逻辑,回忆一下,其实就是点击一下“MAC地址与数据链路层”里介绍的数据链路层以太网帧格式,其中以太网头部填上目标链路层广播MAC地址,也就是在前一节里已经介绍过的全FF,接下来的填入自己的MAC地址,剩下的帧类型是0x0806,标识ARP协议。

接下来就是数据部分了,在ARP协议的数据部分, 要填入的数据类型的很多, 我想以一个表格的形式来表示会比较清晰(表中黑体部分标识以太网帧头部分,普通字体表示数据部分):

长度 数据类型
48 目标以太网地址(FF:FF:FF:FF:FF:FF)
48 发送端以太网地址
16 帧类型(0x0806)
16 硬件类型(0x0001表示以太网)
16 协议类型(0x8000表示IPv4,0x86DD标识IPv6)
8 硬件地址长度(6)
8 协议地址长度(4对应IPv4,6对应IPv6)
16 操作码(1)
48 发送端MAC地址
32 发送端IP地址
48 目标MAC地址(全0标识空)
32 目标IP地址

当这个请求数据帧构造后之后,发送端将其发送给整个网络,接下来的局域网中所有接口卡都会读入这个帧,但是在驱动程序读到数据部分的目标IP地址之后发现与自己的IP地址并不匹配,所以就什么也不做,简单的丢弃这个帧就好。直到正确的对端出现,他发现这个帧里面的IP地址就是自己,于是下面他就需要构造一个ARP应答帧。

这个应答帧的组成绝大部分和上表列出的一样,不同的只有这几点:

  1. 目标以太网地址不再是全FF的广播地址,而是刚才发送端A的MAC地址,因为该应答端B已经从A的ARP请求帧的数据部分可以知道A的MAC地址,没必要再广播了。
  2. 操作码改为2,2表示ARP应答。
  3. 其余将所有"发送端”相关的都填自己(B)的信息,目标端都填要回复的那一端的信息(A),这一点是显而易见的。

当应答帧构造完毕发送出去以后,A的网卡驱动程序就能筛选出发给自己应答帧,里面含有他需要的对端的B的MAC地址信息。这时候以备以后使用,A会把这个信息写入自己的一个cache里面存起来,这个缓存会有个老化机制,会定期淘汰很久没用的,这样可以保持这个表不至于太庞大,加快查询速度。这样下次再想和B通信的时候就不用再一次的广播消息重走长征路了,占用带宽而且也没有必要。而这个缓存信息,在每个机器上都能看到,在windows上用arp -a命令,在linux上使用arp命令就可以看到。

这里有个有趣的现象,我的局域网的广播地址对应的物理地址是全ff,这一点我在上一节也说过了,链路层广播地址和IP层次的广播地址没有完全直接的关系,可能好几类的IP层次的广播地址映射的都是全ff的链路层广播地址。

按照惯例,我会截图截个wireshark的数据包来看一下实际中的包表示标准没有欺骗我们,那么当然这一次也不例外:

看看wireshark这个相当用户友好化的界面说明,我的电脑要找到局域网的路由器的地址,先霸气的在网络里大叫,“谁TM的拥有192.168.8.1,告诉我192.168.8.124”,而且注意第一个消息的地址是Broadcast,是一个广播消息,接下来,路由器做出了应答,“我是192.168.8.1,我的MAC地址是。。。”,这里的发送地址已经准确的是我的电脑了。

为了更一步的看看包里面到底有啥,就选取ARP请求包展开看一下其中内容,对比一下前面表中的内容,又一次发现,标准说明没有骗我们:

免费ARP和免费一点也没有关系

前面我说了,ARP协议主要用在两个场景,在上一节中已经介绍了第一个,第二个就是这个翻译的令人感到很困惑的免费ARP了。免费ARP,其实学名是gratuitous ARP, gratuitous这个词主要有三个意思,无端的,没有理由的和免费的。我觉得翻译成另外两个都比免费的这个翻译好。

废话不多说了,那么这个gratuitous ARP到底是干啥的呢?不知道大家有没有遇到过这样一个现象,在公司里用电脑用的好好的,突然会右下角会出现一个气泡提示,说你的IP地址冲突了。这个提示就来源于gratuitous ARP,每个机器在DHCP(后面会详细介绍这个重要协议的)拿到这个IP之后,会向局域网中广播一个ARP请求,但是这个请求中的目标IP地址是自己已经分配了的IP地址,按照前面的逻辑,如果局域网上还有一个主机具有同样的IP地址的主机,那么他就会发送一个回复,而这个回复中会包含自己MAC地址。发送端如果接收到这么一个回复,那么意味着在网络中有一个和自己一模一样的IP地址的主机,他自己就知道自己的IP地址重复了,于是就会给出这个么一个提示给用户。

ARP欺骗

有了前面这个免费ARP的例子,那么ARP欺骗就很好理解了。只要做一个如下的想象:

如果有一个程序,他可以篡改ARP应答包里的MAC地址,也就是把MAC地址改成自己规定好的主机,那么按照我们上面说的,,发送包在收到这个ARP应答后会把cache起来以防下次再做不必要的努力。那么你以后本来想发送到B的包就会被发到一个指定的主机上,因为数据层的MAC地址已经被邪恶的入侵者所改掉,不会填入B的MAC地址。

这也就是为什么最开始的故事中我们都上不了网,唯独我那一个同学能上网的原因,因为他机器上的ARP病毒将所有包的地址都改为他自己的主机,我们其余的电脑都根本无法完成通信,或者也可能是说根本收不到消息。

三十天学不会TCP,UDP/IP网络编程-ARP -- 连接MAC和IP的更多相关文章

  1. 三十天学不会TCP,UDP/IP网络编程-IP头格式祥述

    我又来了,这篇文章还是来做(da)推(guang)介(gao)我自己的!俗话说事不过三,我觉得我下次得换个说法了,不然估计要被厌恶了,但是我是好心呐,一定要相信我纯洁的眼神.由于这两年接触到了比较多的 ...

  2. 三十天学不会TCP,UDP/IP编程--MAC地址和数据链路层

    这篇文章主要是来做(da)推(guang)介(gao)的!由于这两年接触到了比较多的这方面的知识,不想忘了,我决定把他们记录下来,所以决定在GitBook用半年时间上面写下来,这是目前写的一节,后面会 ...

  3. 三十天学不会TCP,UDP/IP网络编程-UDP,从简单的开始

    如果对和程序员有关的计算机网络知识,和对计算机网络方面的编程有兴趣,欢迎去gitbook(https://www.gitbook.com/@rogerzhu/)star我的这一系列文章,虽然说现在这种 ...

  4. 三十天学不会TCP,UDP/IP网络编程 - UDP的实践--DHCP

    在经历了一顿忙碌加出去玩了玩之后,我又开始重新更新了~这是最新的一篇~完整版可以去gitbook(https://www.gitbook.com/@rogerzhu/)看到,在gitbook的后台流量 ...

  5. 三十天学不会TCP,UDP/IP网络编程-TraceRoute的哲学

    新年快乐,继续来部分粘贴复制我的这一系列文章啦,如果对和程序员有关的计算机网络知识,和对计算机网络方面的编程有兴趣,欢迎去gitbook(https://www.gitbook.com/@rogerz ...

  6. 三十天学不会TCP,UDP/IP网络编程 - 绅士的开始

    经过了过年的忙碌和年初的懈怠一切的日子,我又开始重新更新了~这是最新的一篇~完整版可以去gitbook(https://www.gitbook.com/@rogerzhu/)看到. 如果对和程序员有关 ...

  7. 三十天学不会TCP,UDP/IP网络编程 - RST的用法

    不知不觉也写了这么多了,继续我的自己的推广大业~完整版可以去gitbook(https://www.gitbook.com/@rogerzhu/)看到. 如果对和程序员有关的计算机网络知识,和对计算机 ...

  8. 三十天学不会TCP,UDP/IP网络编程 -- TCP中的智慧之连续ARQ

    突然发现上一篇文章贴图有问题,关键我怎么调也调不好,为了表达歉意,我再贴一篇gitbook上的吧,虽然违背了我自己的隔一篇在这里发一次的潜规则~其余完整版可以去gitbook(https://www. ...

  9. 三十天学不会TCP,UDP/IP网络编程 -- RTT的计算

    欢迎去gitbook(https://www.gitbook.com/@rogerzhu/)看到完整版. 如果对和程序员有关的计算机网络知识,和对计算机网络方面的编程有兴趣,虽然说现在这种“看不见”的 ...

随机推荐

  1. JavaScript简易缩放程序

    一.前言: 上一篇随笔中已经把拖动程序完成了,这篇主要把缩放程序完成,后面合并后可以做成一个图片裁剪的功能 简易缩放程序DEMO:http://jsfiddle.net/UN99R/ 限制缩放程序DE ...

  2. linux下javaEE系统安装部署

    最近公司在将服务器往阿里云上面迁移,所以需要重新在linux上面安装相关的软件以及部署项目,这里用到的linux版本为centos7.0,需要安装的软件有 jdk1.7.mysql5.6.mongo3 ...

  3. Linux Shell脚本入门--(linux空设备文件和重定向)>/dev/null 2>&1

    linux空设备文件和重定向 输出/输入重导向 >      >>   <   <<   :>   &>   2&>   2< ...

  4. C++中string类的基本用法

    #include <iostream> #include <set> using namespace std; int main() { string line; getlin ...

  5. 全局scope与Isolate scope通信

    AngularJS 全局scope与Isolate scope通信 在项目开发时,全局scope 和 directive本地scope使用范围不够清晰,全局scope与directive本地scope ...

  6. 用tensorflow迁移学习猫狗分类

    笔者这几天在跟着莫烦学习TensorFlow,正好到迁移学习(至于什么是迁移学习,看这篇),莫烦老师做的是预测猫和老虎尺寸大小的学习.作为一个有为的学生,笔者当然不能再预测猫啊狗啊的大小啦,正好之前正 ...

  7. Kettle从excel导入数据到sql server

    从excel工作表中读取数据逐行执行insert语句插入到sqlserver 为了简单起见只选取了三个个字段作为参数,日期,字符类型的需要加上'' Spoon是作业配置的GUI界面,配置好后可以通过控 ...

  8. POJ 3107.Godfather 树形dp

    Godfather Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7536   Accepted: 2659 Descrip ...

  9. 使用keytool生成公钥、私钥、证书并且读取出来,使用私钥签名jar并验证(转)

    参考链接:http://happyqing.iteye.com/blog/2139504 :https://blog.csdn.net/arjelarxfc/article/details/52461 ...

  10. ThreadPoolExecutor 中的 shutdown() 、 shutdownNow() 、 awaitTermination() 的用法和区别

    Java并发编程中在使用到ThreadPoolExecutor时,对它的三个关闭方法(shutdown().shutdownNow().awaitTermination())的异同点如下: shutd ...