Linux之(19)IP命令总结
Author:OnceDay Date:2023年2月4日
漫漫长路,有人对你微笑过嘛…
参考文档:
- arp(8) - Linux manual page (man7.org)、
- 彻底搞懂系列之:ARP协议 - 知乎 (zhihu.com)
- RFC 826: An Ethernet Address Resolution Protocol: Or Converting Network Protocol Addresses to 48.bit Ethernet Address for Transmission on Ethernet Hardware (rfc-editor.org)
- 《TCP/IP详解:卷1协议》第四章
- Linux 命令(199)—— arp 命令 - 腾讯云开发者社区-腾讯云 (tencent.com)
1.概述
地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议。主机发送信息时将包含目标IP地址的ARP请求广播到局域网络上的所有主机,并接收返回消息,以此确定目标的物理地址;收到返回消息后将该IP地址和物理地址存入本机ARP缓存中并保留一定时间,下次请求时直接查询ARP缓存以节约资源。地址解析协议是建立在网络中各个主机互相信任的基础上的,局域网络上的主机可以自主发送ARP应答消息,其他主机收到应答报文时不会检测该报文的真实性就会将其记入本机ARP缓存;
网络设备一般都有一个ARP缓存(ARP Cache),ARP缓存用来存放IP地址和MAC地址的关联信息。在发送数据前,设备会先查找ARP缓存表。如果缓存表中存在对方设备的MAC地址,则直接采用该MAC地址来封装帧,然后将帧发送出去。
如果缓存表中不存在相应的信息,则通过发送ARP request报文来获得它。学习到的IP地址和MAC地址的映射关系会被放入ARP缓存表中存放一段时间。
在有效期内,设备可以直接从这个表中查找目的MAC地址来进行数据封装,而无需进行ARP查询。过了这段有效期,ARP表现会被自动删除。如果目标设备位于其他网络则源设备会在ARP缓存表中查找网关的MAC地址,然后将数据发送给网关,网关再把数据转发给目的设备。
ARP表项又分为动态ARP表项和静态ARP表项。
- 动态ARP表项由ARP协议通过ARP报文自动生成和维护,可以被老化,可以被新的ARP报文更新,可以被静态ARP表项覆盖。
- 静态ARP表项通过手工配置和维护,不会被老化,不会被动态ARP表项覆盖。直到重新启动计算机为止。配置静态ARP表项可以增加通信的安全性。静态ARP表项可以限制和指定IP地址的设备通信时只使用指定的MAC地址,此时攻击报文无法修改此表项的IP地址和MAC地址的映射关系,从而保护了本设备和指定设备间的正常通信。
2.ARP帧格式
目的地址、源地址、长度/类型等字段是以太网头部,这部分和其他以太网帧保持一致。可参考以下文档:
- 网络之以太网_ Once_day的博客-CSDN博客
下面看一个实际的ARP包(使用WireShark软件抓包):
可以看到,对于request
请求,目的MAC地址是ff:ff:ff:ff:ff:ff
,表示广播地址,在同一广播域的所有以太网口都可以接收这些帧。对于ARP请求和应答,长度/类型字段值必须为0x0806
。
数据部分存储的就是ARP请求或者应答消息了:
-
硬件类型:即硬件地址的类型,可参考Linux内核源码
include/uapi/linux/if_arp.h
. -
协议类型:指出映射的协议地址类型,可参考Linux内核源码
include/uapi/linux/if_ether.h Line:41
-
硬件/协议大小:指出硬件地址和协议地址的字节数。
-
操作类型(Opcode):指出操作的类型,如下:
#define ARPOP_REQUEST 1 /* ARP request */ #define ARPOP_REPLY 2 /* ARP reply */ #define ARPOP_RREQUEST 3 /* RARP request */ #define ARPOP_RREPLY 4 /* RARP reply */ #define ARPOP_InREQUEST 8 /* InARP request */ #define ARPOP_InREPLY 9 /* InARP reply */ #define ARPOP_NAK 10 /* (ATM)ARP NAK */
后面紧跟着的就是发送方/接收方的硬件地址+协议地址。常见的以太网+IP协议,ARP包大小为42 Bytes。
ARP请求最大频率最好不要超过1秒1个,并且根据不同协议可以进一步降低请求频率。
2.2 免费ARP
免费 ARP(Gratuitous ARP)包是一种特殊的ARP请求,一台主机发送ARP请求以获取自己的地址。
免费ARP报文与普通ARP请求报文的区别在于报文中的目标IP地址。普通ARP报文中的目标IP地址是其他主机的IP地址;而免费ARP的请求报文中,目标IP地址是自己的IP地址。
有两个作用:
- 确定是否有其他主机配置了相同的IPv4地址。
- 更新其他主机上的ARP缓存。
在RFC
中描述了一种 IPv4地址冲突检测(ACD) 机制,可用来检测IPv4地址冲突情况。
ACD定义了两种ARP分组:
- ARP探测分组,是一个ARP请求,其中发送方协议地址被设置为0,目的协议地址为候选IPv4地址。
- ARP通告分组,发送方协议地址和目的地址都为候选IPv4地址。
2.3 ARP代理
当局域网内部主机发起跨网段的ARP请求时,出口路由器/网关设备将自身MAC地址回复该请求时,这个过程称为代理ARP,也被称为混杂ARP(Promiscuous ARP)。
如上图所示,PC1和PC2位于两个网段,PC1发送ARP请求PC2的硬件地址,此时Router回复该ARP请求,并且将MAC地址填为自身地址,然后将PC1发给PC2的数据包再转发给PC2。
PC1和PC2看起来互相隐身,可以屏蔽复杂网络拓扑。
2.4 ARP欺骗和攻击
ARP的解析是依赖于主机内部的高速缓存,如果恶意主机发送ARP应答或者免费ARP等,那么就会返回一个错误的MAC地址,从而导致数据报文发送到错误主机上。
黑客向对方计算机不断发送有欺诈性质的ARP数据包,数据包内包含有与当前设备重复的Mac地址,使对方在回应报文时,由于简单的地址重复错误而导致不能进行正常的网络通信,或者如果不及时处理,便会造成网络通道阻塞、网络设备的承载过重、网络的通讯质量不佳等情况。
3. ARP命令设置
3.1 windows系统
windows上使用powershell就可以轻松设置arp表项了,如下:
PS C:\Users\cg> arp -ac显示和修改地址解析协议(ARP)使用的“IP 到物理”地址转换表。ARP -s inet_addr eth_addr [if_addr]
ARP -d inet_addr [if_addr]
ARP -a [inet_addr] [-N if_addr] [-v]-a 通过询问当前协议数据,显示当前 ARP 项。如果指定 inet_addr,则只显示指定计算机的 IP 地址和物理地址。如果不止一个网络接口使用 ARP,则显示每个 ARP 表的项。-g 与 -a 相同。-v 在详细模式下显示当前 ARP 项。所有无效项和环回接口上的项都将显示。inet_addr 指定 Internet 地址。-N if_addr 显示 if_addr 指定的网络接口的 ARP 项。-d 删除 inet_addr 指定的主机。inet_addr 可以是通配符 *,以删除所有主机。-s 添加主机并且将 Internet 地址 inet_addr与物理地址 eth_addr 相关联。物理地址是用连字符分隔的 6 个十六进制字节。该项是永久的。eth_addr 指定物理地址。if_addr 如果存在,此项指定地址转换表应修改的接口的 Internet 地址。如果不存在,则使用第一个适用的接口。
示例:> arp -s 157.55.85.212 00-aa-00-62-c6-09.... 添加静态项。> arp -a .... 显示 ARP 表。
3.2 Linux系统
Linux系统也是通过arp
命令来设置,如下:
onceday->~:# arp --help
Usage:arp [-vn] [<HW>] [-i <if>] [-a] [<hostname>] <-Display ARP cachearp [-v] [-i <if>] -d <host> [pub] <-Delete ARP entryarp [-vnD] [<HW>] [-i <if>] -f [<filename>] <-Add entry from filearp [-v] [<HW>] [-i <if>] -s <host> <hwaddr> [temp] <-Add entryarp [-v] [<HW>] [-i <if>] -Ds <host> <if> [netmask <nm>] pub <-''--a display (all) hosts in alternative (BSD) style-e display (all) hosts in default (Linux) style-s, --set set a new ARP entry-d, --delete delete a specified entry-v, --verbose be verbose-n, --numeric don't resolve names-i, --device specify network interface (e.g. eth0)-D, --use-device read <hwaddr> from given device-A, -p, --protocol specify protocol family-f, --file read new entries from file or from /etc/ethers<HW>=Use '-H <hw>' to specify hardware address type. Default: etherList of possible hardware types (which support ARP):ash (Ash) ether (Ethernet) ax25 (AMPR AX.25) netrom (AMPR NET/ROM) rose (AMPR ROSE) arcnet (ARCnet) dlci (Frame Relay DLCI) fddi (Fiber Distributed Data Interface) hippi (HIPPI) irda (IrLAP) x25 (generic X.25) eui64 (Generic EUI-64)
这里列出来了各种支持ARP的硬件类型。
在Linux系统上,可以通过下面文件来查看当前的ARP情况:
文件路径 | 描述 |
---|---|
/proc/net/arp | arp表项信息 |
查看arp表项的命令如下:
arp -a
,使用BSD风格查看。arp -e
,默认的Linux风格查看。arp -ev
,输出更多的信息。arp -n
,表示不解析IP地址为域名,直接输出数字形式的地址。
onceday->~:# arp -ev
Address HWtype HWaddress Flags Mask Iface
_gateway ether fe:ee:8f:bf:86:99 C eth0
Entries: 1 Skipped: 0 Found: 1
这个Flags Mask有三个值:
C
,代表complete entry
,是动态ARP表项,通过分组报文学习而来。M
,代表Permanent entry
,是静态ARP表项,通过手动设置。P
,代表published entry
,是免费ARP表项,对外主动应答。
下面指定显示固定网络接口的ARP表项:
onceday->~:# arp -en -i eth0
Address HWtype HWaddress Flags Mask Iface
10.0.4.1 ether fe:ee:8f:bf:86:99 C eth0
onceday->~:# arp -en -i eth1 //不存在该网络接口,所以无匹配项
arp: in 1 entries no match found.
onceday->~:# arp -en -i eth0 10.2.3.4 //不存在协议地址为10.2.3.4的表项
10.2.3.4 (10.2.3.4) -- no entry
删除指定接口的ARP表项,地址也可以填写主机名,会自动解析为IP地址:
onceday->~:# arp -en
Address HWtype HWaddress Flags Mask Iface
172.20.35.46 ether 30:0d:9e:43:11:2a C Ge0_7
172.20.35.1 ether c0:b8:e6:15:78:2c C Ge0_7
172.20.35.1 ether c0:b8:e6:15:78:2c C Ge0_0
onceday->~:# arp -d 172.20.35.46
onceday->~:# arp -en
Address HWtype HWaddress Flags Mask Iface
172.20.35.1 ether c0:b8:e6:15:78:2c C Ge0_7
172.20.35.1 ether c0:b8:e6:15:78:2c C Ge0_0
如果多个网络接口都有同一个IP地址的ARP表项,那么就需要通过指定网络接口的方式来删除。
arp -i Ge0_7 -d 172.20.35.1
3.3 Linux arp命令设置ARP表项
直接设置一个arp表项如下:
onceday->~:# arp -s 172.20.35.48 30:0d:9e:43:11:2a
onceday->~:# arp
Address HWtype HWaddress Flags Mask Iface
172.20.35.48 ether 30:0d:9e:43:11:2a CM Ge0_7
172.20.35.47 ether 30:0d:9e:42:e8:d3 C Ge0_0
172.20.35.46 ether 30:0d:9e:43:11:2a C Ge0_7
172.20.35.1 ether c0:b8:e6:15:78:2c C Ge0_7
172.20.35.1 ether c0:b8:e6:15:78:2c C Ge0_0
需要注意,设置静态表项的时候没有指定网络接口,因此内核会根据路由表来择取一个接口作为ARP表项的归属。现在基本每个主机上都有多个接口,因此使用该命令的稳妥方式是指定网络接口名:
onceday->~:# arp -i Ge0_0 -s 172.20.35.48 30:0d:9e:43:11:2a
onceday->~:# arp
Address HWtype HWaddress Flags Mask Iface
172.20.35.48 ether 30:0d:9e:43:11:2a CM Ge0_0
172.20.35.48 ether 30:0d:9e:43:11:2a CM Ge0_7
可以尝试设置一个动态的ARP表项:
onceday->~:# arp -i Ge0_0 -s 172.20.35.48 30:0d:9e:43:11:2a temp
onceday->~:# arp
Address HWtype HWaddress Flags Mask Iface
172.20.35.48 ether 30:0d:9e:43:11:2a C Ge0_0
172.20.35.48 ether 30:0d:9e:43:11:2a CM Ge0_7
还可以设置ARP代理,当接收到目的IP的ARP请求时,返回对应表项的MAC地址,如下:
//使用Ge0_0的Mac地址作为172.20.35.225的设备地址,ARP表项配置在接口Ge0_7下。
onceday->~:# arp -i Ge0_7 -Ds 172.20.35.225 Ge0_0 pub
onceday->~:# arp
Address HWtype HWaddress Flags Mask Iface
172.20.35.225 (incomplete) Ge0_0
172.20.35.225 * <from_interface> MP Ge0_7
Linux代理ARP需要满足如下条件:
-
Linux开启数据包转发和ARP代理功能。
使能:echo “1” > /proc/sys/net/ipv4/conf/eth2/proxy_arp
-
目标IP在ARP代理主机上路由可达
-
代理主机上对目标IP的转发设备与收包设备不同
上述展现出来的ARP表项说明不满足条件,因为Ge0_0下的172.20.35.225地址不可达(没有完整的ARP表项)。
3.4 使用文件来批量设置ARP表项
arp -i Ge0_0 -f file_path
,如果文件路径没有给定,那么默认是/etc/ethers
文件。
格式如下:
onceday->~:# arp -i Ge0_0 -f
onceday->~:# arp
Address HWtype HWaddress Flags Mask Iface
172.20.111.4 ether 00:15:5d:20:78:70 CM Ge0_0
172.20.111.3 ether 00:15:5d:20:78:71 CM Ge0_0
172.20.111.1 ether 00:15:5d:20:78:73 C Ge0_0
172.20.111.2 * <from_interface> MP Ge0_0
onceday->~:# cat /etc/ethers
172.20.111.1 00:15:5d:20:78:73 temp
172.20.111.2 00:15:5d:20:78:72 pub
172.20.111.3 00:15:5d:20:78:71
172.20.111.4 00:15:5d:20:78:70
不同表项之间使用空格(whitespace)分开即可,后面可添加temp
,pub
,netmask
等内容。