Linux内核参数arp_ignore和arp_announce

说明

内核的 arp_ignore 和 arp_announce 参数都和 ARP 协议相关,主要用于控制系统返回 ARP 响应和发送 ARP 请求时的动作。这两个参数很重要,特别是在 LVS 的 DR 场景下,它们的配置直接影响到 DR 转发是否正常。Linux 内核文档 中的描述:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
arp_ignore - INTEGER
Define different modes for sending replies in response to
received ARP requests that resolve local target IP addresses:
0 - (default): reply for any local target IP address, configured
on any interface
1 - reply only if the target IP address is local address
configured on the incoming interface
2 - reply only if the target IP address is local address
configured on the incoming interface and both with the
sender's IP address are part from same subnet on this interface
3 - do not reply for local addresses configured with scope host,
only resolutions for global and link addresses are replied
4-7 - reserved
8 - do not reply for all local addresses

The max value from conf/{all,interface}/arp_ignore is used
when ARP request is received on the {interface}

arp_ignore 参数的作用是控制系统在收到外部的 ARP 请求时,是否要返回 ARP 响应。参数常用到的有 0,1,2 三个值,3 ~ 8 较少用到:

  • 0:响应任意网卡上接收到的对本机IP地址的 ARP 请求(包括环回网卡上的地址),而不管该目的 IP 是否在接收网卡上。
  • 1:只响应目的IP地址为接收网卡上的本地地址的 ARP 请求。
  • 2:只响应目的IP地址为接收网卡上的本地地址的 ARP 请求,并且发送 ARP 请求的源IP必须和接收网卡同网段。
  • 3:如果 ARP 请求数据包所请求的IP地址对应的本地地址其作用域(scope)为主机(host),则不回应 ARP 响应数据包,如果作用域为全局(global)或链路(link),则回应 ARP 响应数据包。
  • 4~7:保留,未使用。
  • 8:不回应所有的 ARP 请求

/etc/sysctl.conf 中包含 all 和 eth/lo(具体网卡)的 arp_ignore 参数,取其中较大的值生效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
arp_announce - INTEGER
Define different restriction levels for announcing the local
source IP address from IP packets in ARP requests sent on
interface:
0 - (default) Use any local address, configured on any interface
1 - Try to avoid local addresses that are not in the target's
subnet for this interface. This mode is useful when target
hosts reachable via this interface require the source IP
address in ARP requests to be part of their logical network
configured on the receiving interface. When we generate the
request we will check all our subnets that include the
target IP and will preserve the source address if it is from
such subnet. If there is no such subnet we select source
address according to the rules for level 2.
2 - Always use the best local address for this target.
In this mode we ignore the source address in the IP packet
and try to select local address that we prefer for talks with
the target host. Such local address is selected by looking
for primary IP addresses on all our subnets on the outgoing
interface that include the target IP address. If no suitable
local address is found we select the first local address
we have on the outgoing interface or on all other interfaces,
with the hope we will receive reply for our request and
even sometimes no matter the source IP address we announce.

The max value from conf/{all,interface}/arp_announce is used.

Increasing the restriction level gives more chance for
receiving answer from the resolved target while decreasing
the level announces more valid sender's information.

arp_announce 的作用是控制系统在对外发送 ARP 请求时,如何选择 ARP 请求数据包的源IP地址。arp_announce 参数常用的取值有 0,1,2:

  • 0:允许使用任意网卡上的IP地址作为 ARP 请求的源IP,通常就是使用数据包的源IP。
  • 1:尽量避免使用不属于该发送网卡子网的本地地址作为发送 ARP 请求的源IP地址。
  • 2:忽略IP数据包的源IP地址,选择该发送网卡上最合适的本地地址作为 ARP 请求的源IP地址。

/etc/sysctl.conf 中包含 all 和 eth/lo(具体网卡)的 arp_announce 参数,取其中较大的值生效。

arp_ignore 参数示例

当 arp_ignore 参数配置为 0 时,eth0 网卡上收到目的IP为环回网卡IP的 ARP 请求,但是 eth0 也会返回 ARP 响应,并且把自己的 MAC 地址告诉对端。

当 arp_ignore 参数配置为 1 时,eth0 网卡上收到目的IP为环回网卡IP的 ARP 请求,发现请求的IP不是自己网卡(eth0)上的IP,就不会返回 ARP 响应。

arp_announce 参数示例

当 arp_announce 参数配置为 0 时,系统要发送的IP包源地址为 eth1 的地址,IP包目的地址根据路由表查询判断需要从 eth0 网卡发出,这时会先从 eth0 网卡发起一个 ARP 请求,用于获取目的IP地址的 MAC 地址。该 ARP 请求的源MAC 自然是 eth0 网卡的 MAC 地址,但是源 IP 地址会选择 eth1 网卡的地址。

当 arp_announce 参数配置为 2 时,eth0 网卡发起arp请求时,源IP地址会选择 eth0 网卡自身的IP地址。

DR 模式下的应用

arp_ignore

因为 DR 模式下,每个真实服务器节点都要在环回网卡上绑定虚拟服务IP。这时候,如果客户端对于虚拟服务IP的 ARP 请求广播到了各个真实服务器节点,如果 arp_ignore 参数配置为 0,则各个真实服务器节点都会响应该 ARP 请求,此时客户端就无法正确获取 LVS 节点上正确的虚拟服务IP所在网卡的 MAC 地址。假如某个真实服务器节点 A 的网卡 eth1 响应了该 ARP 请求,客户端把 A 节点的 eth1 网卡的 MAC 地址误认为是 LVS 节点的虚拟服务IP所在网卡的 MAC ,从而将业务请求消息直接发到了 A 节点的 eth1 网卡。这时候虽然因为 A 节点在环回网卡上也绑定了虚拟服务IP,所以 A 节点也能正常处理请求,业务暂时不会受到影响。但时此时由于客户端请求没有发到 LVS 的虚拟服务IP上,所以 LVS 的负载均衡能力没有生效。造成的后果就是,A节点一直在单节点运行,业务量过大时可能会出现性能瓶颈。

所以要求 arp_ignore 参数要求配置为1。

arp_announce

每个机器或者交换机中都有一张 ARP 表,该表用于存储对端通信节点IP地址和 MAC 地址的对应关系。当收到一个未知IP地址的 ARP 请求,就会在本机的 ARP 表中新增对端的IP和 MAC 记录;当收到一个已知IP地址( ARP 表中已有记录的地址)的 ARP 请求,则会根据 ARP 请求中的源 MAC 刷新自己的 ARP 表。

如果 arp_announce 参数配置为0,则网卡在发送 arp 请求时,可能选择的源IP地址并不是该网卡自身的IP地址,这时候收到该 ARP 请求的其他节点或者交换机上的 ARP 表中记录的该网卡IP和 MAC 的对应关系就不正确,可能会引发一些未知的网络问题,存在安全隐患。

所以要求 arp_announce 参数要求配置为2。

配置

配置 /etc/sysctl.conf ,然后使用 sysctl -p 刷新到内存即可立即生效:

1
2
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
有钱任性,请我吃包辣条
0%