问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

详细的网络协议之ARP请求

创作时间:
作者:
@小白创作中心

详细的网络协议之ARP请求

引用
CSDN
1.
https://blog.csdn.net/qq_34556414/article/details/106801446

ARP协议是网络通信中一个基础且重要的协议,主要用于根据IP地址解析出对应的MAC地址。本文将从ARP协议的基本概念、工作原理、报文格式、相关命令和内核配置参数等多个方面进行深入讲解,帮助读者全面理解ARP协议的工作机制。

对于ARP协议,你想知道的,可能包括以下几点:

  • ARP是什么
  • 为什么需要ARP
  • ARP是如何工作的
  • ARP报文格式是什么样的
  • ARP安全吗
  • 有哪些命令可以操作ARP
  • ARP有哪些内核配置参数

带着这些问题,下面我们就来一一解答。

ARP是什么

ARP全称为Address Resolution Protocol,即地址解析协议,主要用于根据IP地址求出主机所对应的物理地址(或者叫MAC地址)。

它还有个孪生兄弟叫RARP(Reverse ARP),即反向地址解析协议,也就是根据主机MAC地址求出对应的IP地址,但是这个协议不常用,通常只用在无盘系统中。

ARP只用于IPv4,IPv6使用邻居发现协议(Neighbor Discovery Protocol, NDP)来代替ARP的功能。

为什么需要ARP

在网络通信中,主机和主机之间的通信需要根据OSI模型进行数据包的封装和解封装,这里面不仅需要封装源目的IP地址,也需要源目的MAC地址,那么MAC地址从哪里来呢,一般情况下,上层应用只知道IP地址,而并不关心MAC地址,所以就需要通过一个协议来获知目的MAC地址,完成数据的封装,这个协议就是ARP协议该干的活。

ARP是如何工作的

在介绍ARP如何工作之前,需要知道一个概念ARP缓存表。在每台安装有TCP/IP协议的电脑或网络设备里都有一个ARP缓存表,表中记录的是IP地址和MAC地址的映射关系,比如:

以上表中的主机A向主机B发送数据为例,说一下ARP的工作流程:

  1. 当发送数据时,主机A会在自己的ARP缓存表中寻找是否有目标IP地址,如果找到,就把对应的目标MAC地址封装进帧里进行发送。
  2. 如果没有找到,主机A就会向网络中发送一个广播(ARP request),和主机A同网段内的所有主机都会收到这个请求,该请求的目标MAC地址是"FF.FF.FF.FF.FF.FF",目标IP是主机B的IP。
  3. 只有主机B会接收这个请求,并且向主机A做出回应(ARP response),而其他主机接收到请求之后发现目标IP不是自己,就会选择丢弃。主机B从请求中获得主机A的MAC地址和IP地址,所以会以单播的方式进行回应,同时更新自己的ARP缓存表。
  4. 主机A接收到主机B的响应之后,也会更新自己的ARP缓存,下次再访问主机B时,就直接从ARP缓存里查找即可。

ARP缓存超时:既然是缓存表,意味着有时效性。ARP缓存表采用老化机制,在一段时间内如果表中的某一条目没有使用,就会被删除,这样可以减少缓存表的长度,加快查询速度。

缓存时间,一般是20分钟,但RFC也有规定一些不完整条目是3分钟,什么是不完整条目,比如下面这条,对一个不存在的主机执行了一次ARP请求,就是一条不完整的条目:

# arp -a
?(10.0.0.99) at <incomplete> on eth0

ARP报文格式是什么样的

首先看一个以太网帧中,ARP报文处在一个什么位置。

以下是一个以太网帧的简化图,这里只是为了说明ARP报文在整个以太网帧中所处的位置,所以这个以太网帧并不是完整的。

我们看到,以太网帧通过一个2字节的帧类型来表示它后面的数据负载(payload)部分具体是什么类型的数据,如果帧类型是16进制的0x0800,则表示payload是IP报文,如果是0x0806,就表示ARP报文,包括ARP请求报文和应答报文。当然,这里还有其他类型的数据,比如ARAP,我们就不一一列出了。

下面,继续走进ARP报文内部,看看它包含哪些字段:

  • 硬件类型:指出硬件地址类型,对于以太网,该值是1
  • 协议类型:指出网络层协议类型,对于IPv4,该值是0x0800
  • 硬件大小和协议大小:分别指出后面的硬件地址和协议地址的大小,对于使用IPv4的ARP报文,该值分别是6和4
  • Op:指出该报文是ARP请求(值为1)、ARP应答(2)、RARP请求(3)或RARP应答(4)
  • 后面的4个字段和前面4个字段对应,分别表示源目的MAC和源目的IP地址

我们通过Wireshark抓包看看。

ARP请求报文:

ARP应答报文:

可以看到Op字段,对于ARP请求和应答报文分别为1和2,其他字段大家也可以看看,比较直观。

有哪些命令可以操作ARP

① arp

用法:

# arp (选项)(参数)
-a <主机IP>:显示arp缓冲区中的所有条目
-e:以Linux的显示风格显示arp缓冲区中的条目
-v:显示详细的arp缓冲区条目,包括缓冲区条目的统计信息
-i <接口>:显示指定接口的arp缓存条目
-s <主机IP><MAC>:配置主机的IP地址与MAC地址的静态映射
-d <主机>:删除arp条目
-f <文件>:从文件/etc/ethers(默认)或者指定文件中记录的arp条目配置静态映射

② ip neigh

ip neigh是和arp相同功能但不同用法的另一套命令,全称为ip neighbour。

用法:

# ip neigh help
ip neigh { add | del | change | replace }
         { ADDR [ lladdr LLADDR ] [ nud STATE ] | proxy ADDR } [ dev DEV ]
ip neigh { show | flush } [ proxy ] [ to PREFIX ] [ dev DEV ] [ nud STATE ][ vrf NAME ]
# 其中几个选项的意思解释
- to ADDR: 协议地址,指定主机的IP地址
- dev DEV: 指定网口
- lladdr LLADDR: 指定MAC地址
- nud STATE: 状态值,有以下几个值:
- permanent:永久有效
- noarp:有效,不会验证此条目,但可以在其生命周期到期时将其删除
- reachable:有效,直到可达性超时到期
- stale:有效但可疑
- all:列出所有状态
# 常用操作
1. 列出所有arp条目
# ip neigh show
2. 添加arp静态条目
# ip neigh add 192.168.10.11 lladdr 00:01:02:03:04:05 dev eth0
3. 删除指定IP或者网口的arp条目
# ip neigh del 192.168.10.11 dev eth0
4. 刷新arp表
# ip neigh flush 192.168.10.11
# 此外还有两个命令,可以更改arp条目
# ip neighbour change - 更改
# ip neighbour replace - 添加新的或更改

③ arping

arping和ping相似,主要是通过发送ARP请求查看IP和MAC的映射关系,以及探测IP的冲突问题。更多的用法可以参见这篇文章xxx

④ arpwatch

arpwatch主要用于监听网络中的ARP数据的变化关系并记录,可以将监听到的变化通过E-mail发送。

用法:

# arpwatch [-d][-f <记录文件>][-i <接口>][-r <记录文件>]
监听eth0的ARP信息
# arpwatch -i eth0
将监听到的ARP记录存储到文件
# arpwatch -i eth0 -f /var/arpwatch/arp.dat
从指定文件中读取ARP记录,而不是从网络中监听
# arpwatch -r /var/arpwatch/arp.dat

ARP有哪些内核配置参数

从上文我们知道,ARP是一个无状态协议,就是说它不管自己是否发过请求,也不管应答是否合理,再加上广播的特性,有时候通信上会出现一些匪夷所思的问题,系统会通过以下几个配置参数来规避这些问题。

要说清楚这些参数,我们先上个图:

在这样一个局域网的图示中,B向A的eth0接口发送ARP请求,由于是广播,并且IP地址针对的是整个主机,而不是特定的某个接口,所以,A的两个口eth0和eth1都会接收请求并发出应答,而B则以最后应答的MAC地址为准。

这就会带来第一个问题,如果B本来想获取eth0的MAC地址,但却得到eth1的,这就会导致后续发送数据的不准确。

解决这个问题可以用两个内核参数,这两个参数都是在ARP应答上做文章,让它能够正确应答。

① arp_ignore

  • 0 - (默认值): 回应任何网络接口(网卡)上对任何本机IP地址的arp查询请求。比如eth0=192.168.0.1/24,eth1=10.1.1.1/24,那么即使eth0收到来自10.1.1.2这样地址发起的对10.1.1.1 的arp查询也会给出正确的回应;而原本这个请求该是出现在eth1上,也该有eth1回应的。
  • 1 - 只回答目标IP地址是本机上来访网络接口(网卡)IP地址的ARP查询请求 。比如eth0=192.168.0.1/24,eth1=10.1.1.1/24,那么即使eth0收到来自10.1.1.2这样地址发起的对192.168.0.1的查询会回应,而对10.1.1.1 的arp查询不会回应。
  • 2 -只回答目标IP地址是本机上来访网络接口(网卡)IP地址的ARP查询请求,且来访IP(源IP)必须与该网络接口(网卡)上的IP(目标IP)在同一子网段内 。比如eth0=192.168.0.1/24,eth1=10.1.1.1/24,eth1收到来自10.1.1.2这样地址发起的对192.168.0.1的查询不会回应,而对192.168.0.2发起的对192.168.0.1的arp查询会回应。
  • 3 - do not reply for local addresses configured with scope host,only resolutions for global and link addresses are replied。(不知道怎么翻译合适,网上有一个参考但我认为无法理解它的含义:不回应该网络界接口的arp请求,而只对设置的唯一和连接地址做出回应)
  • 4-7 - 保留未使用
  • 8 -不回应所有(本机地址)的arp查询

在设置参数的时候将arp_ignore 设置为1,意味着当别人的arp请求过来的时候,如果接收的网络接口卡上面没有这个ip,就不做出响应。默认是0,只要这台机器上面任何一个设备上面有这个ip,就响应arp请求,并发送mac地址。

在内核参数中,除了每个网口都有自己的arp_ignore配置外,还有两个(一个是默认 default,一个是全局 all),如下。一般,如果网口自身的arp_ignore不配置的情况下,使用 default 的配置,如果 all 和网口自身都配置的情况下,使用两者中较大的那一个。

# sysctl -a | grep arp_ignore
net.ipv4.conf.default.arp_ignore=1
net.ipv4.conf.all.arp_ignore=1
net.ipv4.conf.lo.arp_ignore=1
net.ipv4.conf.eth0.arp_ignore=1
net.ipv4.conf.eth1.arp_ignore=1

关于配置这块,有临时生效和永久生效的配置方式,文末有进一步说明。

② arp_filter

这个参数和arp_ignore能够达到相同的目的,但arp_filter会更严格一些,它在选网口应答的时候会按照路由来选。它是一个bool值,具体为:

  • 0:默认值,所有网口都可以响应ARP请求
  • 1:会根据本机路由表来验证哪个网口应该进行应答,优先选择在路由表前面的网口,也就是会有一个反向路由验证的过程。

同样,他也有以下的参数:

$ sysctl -a | grep arp_filter
net.ipv4.conf.all.arp_filter = 0
net.ipv4.conf.default.arp_filter = 0
net.ipv4.conf.eth0.arp_filter = 0
net.ipv4.conf.eth1.arp_filter = 0
net.ipv4.conf.lo.arp_filter = 0

上面两个参数解决的是ARP应答方向上的问题,而下面的arp_announce是解决ARP请求方向上的问题。它可以控制本机发出的ARP请求中的源IP地址使用哪个网口的地址。

③ arp_announce

它有以下3个整数值:

  • 0:默认值,可以在任意网口上发送ARP请求,但是请求的源IP地址与当前发送的网口没有关系。也就是说如果源IP地址与当前发送网口的地址不同(使用其他网口作为源IP地址),使用原本的源IP地址。
  • 1:要求尽量避免使用不在当前发送网口子网段内的IP地址作为ARP请求的源IP地址,也就是说系统会遍历所有网口的IP,然后看哪个网口的IP和ARP请求包中的源IP在同一个网段内,优先选择哪个进行发送,如果都不在,就采用下面级别2的方式来选择。
  • 2:1是看源IP地址,这种方式是看目标IP地址,选择与目标IP地址在同一个网段内的网口IP作为ARP请求的源IP地址,如果还是没找到,则直接选择当前网口的IP或者能够接受到ARP回应的网口IP来发送ARP请求,并设源IP为发送网口的IP。

此外,还有两个参数:

④ arp_accept

默认对不在ARP表中的IP地址发出的APR包的处理方式

  • 0:不在ARP表中创建对应IP地址的表项
  • 1:在ARP表中创建对应IP地址的表项

⑤ arp_notify

ARP通知链操作

  • 0:不做任何操作
  • 1:当设备或硬件地址改变时自动产生一个ARP请求

修改方法

临时修改方法:

  1. 修改/proc文件系统:
echo "1">/proc/sys/net/ipv4/conf/all/arp_ignore
echo "1">/proc/sys/net/ipv4/conf/eth0/arp_ignore
echo "2">/proc/sys/net/ipv4/conf/all/arp_announce
echo "2">/proc/sys/net/ipv4/conf/eth0/arp_announce
  1. 使用sysctl -w直接写入内存:
sysctl -w net.ipv4.conf.all.arp_ignore=1
sysctl -w net.ipv4.conf.eth0.arp_ignore=1
sysctl -w net.ipv4.conf.all.arp_announce=2
sysctl -w net.ipv4.conf.eth0.arp_announce=2

永久修改需要写入配置文件:

修改/etc/sysctl.conf文件,然后sysctl -p刷新到内存

net.ipv4.conf.all.arp_ignore=1
net.ipv4.conf.eth0.arp_ignore=1
net.ipv4.conf.all.arp_announce=2
net.ipv4.conf.eth0.arp_announce=2

备注:arp_ignore和arp_announce参数分别有all,default,lo,eth0等对应不同网卡。当all和具体网卡的参数值不一致时,配置为较大值的生效。一般只需修改all和某个具体网卡的参数即可。

然后一定记得执行sysctl -p使之生效。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号