用户报障,说在一台安装了Asianux 3.0 的机器上测试网络时,发现拔掉某网卡的网线后,该网卡上的IP 地址仍可继续ping 通,怀疑硬件或系统配置有问题。经查证,这实际上是因为核心中arp_ignore 参数的默认设置导致的。月初时,我才写了一篇有关arp_ignore 与arp_announce 参数的设置的文章,这次为了更清晰的说明问题,特模拟一个实验。
一、实验环境
实验环境很简单,两台机器,设置如下:
eth0:192.168.228.161
eth1:192.168.228.162
B机:Windows 平台,作为测试客户端,IP是192.168.228.221
※ 经测试,若两台机器都是Linux 平台,不会发生下面的情况。
下面是A 机上的IP 和MAC 地址配置信息:
eth0 Link encap:Ethernet HWaddr 00:11:5B:D1:0E:F8
inet addr:192.168.228.161 Bcast:192.168.228.255 Mask:255.255.255.0
—
eth1 Link encap:Ethernet HWaddr 00:F0:BF:70:00:EE
inet addr:192.168.228.162 Bcast:192.168.228.255 Mask:255.255.255.0
二、默认参数下的测试情况
首先,我们在保持系统默认参数的环境下进行测试。
1、清空B 机的arp 表缓存信息
Win 7 使用下面的命令清空arp 缓存:
2、从B机分别ping A机上的两个IP 地址
正在 Ping 192.168.228.161 具有 32 字节的数据:
来自 192.168.228.161 的回复: 字节=32 时间<1ms TTL=64
C:\Users\linuxing>ping -n 1 192.168.228.162
正在 Ping 192.168.228.162 具有 32 字节的数据:
来自 192.168.228.162 的回复: 字节=32 时间<1ms TTL=64
此时的arp 表如下(忽略其他IP地址的MAC信息,下同):
接口: 192.168.228.221 — 0xc
Internet 地址 物理地址 类型
192.168.228.161 00-11-5b-d1-0e-f8 动态
192.168.228.162 00-f0-bf-70-00-ee 动态
3、测试
ping A机上的192.168.228.162,同时,禁用eth1网卡,B机显示的结果如下:
正在 Ping 192.168.228.162 具有 32 字节的数据:
来自 192.168.228.162 的回复: 字节=32 时间<1ms TTL=64
来自 192.168.228.162 的回复: 字节=32 时间<1ms TTL=64
请求超时。
来自 192.168.228.162 的回复: 字节=32 时间<1ms TTL=64
来自 192.168.228.162 的回复: 字节=32 时间<1ms TTL=64192.168.228.162 的 Ping 统计信息:
数据包: 已发送 = 11,已接收 = 10,丢失 = 1 (9% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 0ms,最长 = 0ms,平均 = 0ms
Control-C
^C
※ A机上用ifconfig eth1 down 禁用网卡,或拔去eth1的网线。
再看看B机的arp 表:
接口: 192.168.228.221 — 0xc
Internet 地址 物理地址 类型
192.168.228.161 00-11-5b-d1-0e-f8 动态
192.168.228.162 00-11-5b-d1-0e-f8 动态
可见,A机上的两块网卡的IP地址都指向了同一个MAC 地址(即eth0)。在ping 的过程中虽然发生过短暂的中断,但恢复后,IP 与MAC 的指向就改变了。后面再ping 162的地址,都是成功的(因为eth0 是连接的),成功模拟用户提到的问题。
三、解决问题
产生该问题的主要原因是,Linux 核心中的一个arp_ignore 参数,该参数默认值为0。即对ARP请求时,只要该IP在本地的机器任意网卡设备上存在都会响应。详细可参考下面的文档:
或有关arp_ignore 与arp_announce 参数的设置一文。
正如这些资料中提到的,如果把arp_ignore 设置为1时,当别人的arp请求过来的时候,如果接收的设备上面没有这个ip,就不响应。
我们在A 机上进行该操作:
若同时在B 机上测试,会有如下的结果:
正在 Ping 192.168.228.162 具有 32 字节的数据:
来自 192.168.228.162 的回复: 字节=32 时间<1ms TTL=64
来自 192.168.228.162 的回复: 字节=32 时间<1ms TTL=64
来自 192.168.228.221 的回复: 无法访问目标主机。
来自 192.168.228.221 的回复: 无法访问目标主机。
这说明,A机的eth0设备不再响应对192.168.228.162 的请求,因此,无法连通。此时,B机上该IP的arp 缓存也会被删掉。问题解决。
四、备注
1、对那个网卡设定
由于arp 上的缓存信息与交换机有很大的关系,因此,获取IP 对应的MAC 地址顺序不同,可能arp 缓存的结果也不一样。例如,B 机上初始的状态可能是这样的:
接口: 192.168.228.221 — 0xc
Internet 地址 物理地址 类型
192.168.228.161 00-f0-bf-70-00-ee 动态
192.168.228.162 00-f0-bf-70-00-ee 动态
这时,你设置eth0上的arp_ignore将没什么作用,需设置eth1的参数。所以,考虑到随机性,为避免该参数的影响,应在所有端口上配置该参数,这可写入/etc/sysctl.conf 文件中。
2、客户端的影响
不单Windows 客户端有影响,Linux 客户端同样也会出现,例如,下面的arp 缓存表:
? (192.168.228.161) at 00:11:5B:D1:0E:F8 [ether] on eth0
? (192.168.228.162) at 00:11:5B:D1:0E:F8 [ether] on eth0
当我们ping 161,同时禁用eth0,就会变成:
? (192.168.228.161) at 00:F0:BF:70:00:EE [ether] on eth0
? (192.168.228.162) at 00:F0:BF:70:00:EE [ether] on eth0
但Linux 上arp 的缓存时间较短,出现的几率少点。
3、Linux 上如何清空arp 缓存信息
Linux 的arp -d 不支持通配符,需用下面的方式执行,才能清空arp 缓存信息:
4、如何避免
除了调整上面提到的arp_ignore参数外,在日常的系统配置中,我们也应该尽量避免在同一台机器,不同网卡上配置相同网段的IP地址。特殊情况下,如LVS 环境、链路有环路等,这需考虑arp_ignore 与arp_announce 的参数。