linux arp相关参数
在 Linux 中,有多个内核参数可以控制 ARP(地址解析协议)的行为。这些参数可以通过 /proc/sys/net/ipv4/conf/*/
目录下的文件来配置,或者使用 sysctl
命令来设置。以下是一些常用的 ARP 内核参数及其含义:
arp_ignore:
-
- 控制系统对不同网络接口上收到的 ARP 请求的响应行为。
- 取值范围:
- 0:在任何网络接口上收到 ARP 请求时,系统都会进行响应(默认值)。
- 1:只有当目标 IP 地址在收到请求的网络接口上配置时,系统才会响应。
- 2:只有当目标 IP 地址是最接近请求源的地址时,系统才会响应
arp_announce:
-
- 控制系统在发送 ARP 请求时,源 IP 地址的选择策略。
- 取值范围:
- 0 (默认): 允许使用任意网卡上的 IP 地址作为 ARP 请求的源 IP 地址。通常情况下,会使用 IP 数据包的源 IP。
- 1: 尽量避免使用不属于该发送网卡子网的本地地址作为发送 ARP 请求的源 IP 地址。
- 2: 忽略 IP 数据包的源 IP 地址,选择该发送网卡上最合适的本地地址作为 ARP 请求的源 IP 地址。
arp_accept:
-
- 控制系统GARP处理,当IP不在ARP表中。(GARP的源地址和目标地址一样), 如果存在直接更新不会判断这个标志
- 取值范围:
- 0 (默认值): 始终接受 GARP 数据包并相应地更新 ARP 表。即使 GARP 数据包包含未分配给其任何接口的 IP 地址,系统也会更新其 ARP 缓存。
- 1: 仅当数据包中的源 IP 地址与分配给系统接口之一的 IP 地址匹配时,才接受 GARP 数据包。这是一种更保守的方法,因为它只更新系统实际使用的地址的 ARP 缓存。
- 2:(自 Linux 内核 v6.0起)仅当源 IP 地址与接收数据包的接口位于同一子网时,才接受 GARP 数据包。这通过确保仅从同一网络上的设备接受 GARP 数据包来增加另一层安全性。
-
- Linux 中的 arp_notify 参数控制在网络设备启动或其硬件地址(MAC 地址)更改时是否自动发送 Gratuitous ARP (GARP) 请求。GARP 请求是一种特殊的 ARP 数据包,设备发送该数据包是为了通知其 IP 地址到 MAC 地址的映射,即使没有收到 ARP 请求。
- 取值范围:
-
-
- 0 (默认值): 不自动发送 GARP 请求。
- 1: 当网络设备启动或其硬件地址更改时,自动发送 GARP 请求。
-
drop_gratuitous_arp
-
- drop_gratuitous_arp 是 Linux 内核中的一个参数,用于控制是否丢弃 Gratuitous ARP (GARP) 数据包。GARP 数据包是设备发送的特殊 ARP 数据包,用于宣布其 IP 地址到 MAC 地址的映射,即使没有收到 ARP 请求。
- 取值范围:
- 0 (默认值): 接受 GARP 数据包并相应地更新 ARP 表。
- 1: 丢弃所有 GARP 数据包。
验证:
之前在做LVS实验搭建DR环境的时候用到前面两个参数;arp_ignore, arp_announce
环境搭建可以参考 https://garlicspace.com/2024/06/02/%e8%b4%9f%e8%bd%bd%e5%9d%87%e8%a1%a1/
lb 10.1.1.10 5a:86:a3:16:85:0
rs1 10.1.1.11 56:ff:71:bd:27:40 veth-rs1
rs2 10.1.1.12 46:15:5c:b7:68:35
client 10.1.1.20 ee:86:01:ae:45:b0
arp_ignore设置1,只有目标地址在收到请求的网卡上才回应。
ip netns exec client arp Address HWtype HWaddress Flags Mask Iface 10.1.1.11 ether 56:ff:71:bd:27:40 C veth-client 10.1.1.10 ether 5a:86:a3:16:85:08 C veth-client 10.1.1.12 ether 46:15:5c:b7:68:35 C veth-client
使用 arp -d 清除arp记录, 并且将rs1 的 arp_ignore标识设置为1, 由于之前仅设置了net.ipv4.conf.all,修改这个参数即可。
ip netns exec client arp Address HWtype HWaddress Flags Mask Iface 10.1.1.10 ether 56:ff:71:bd:27:40 C veth-client
看下rs1地址信息
# rs1 #ip netns exec rs1 ip a 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 10.1.1.10/32 scope global lo valid_lft forever preferred_lft forever 264: veth-rs1@if263: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 56:ff:71:bd:27:40 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 10.1.1.11/24 scope global veth-rs1 valid_lft forever preferred_lft forever inet6 fe80::54ff:71ff:febd:2740/64 scope link valid_lft forever preferred_lft forever # client # ip netns exec client ip a 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 268: veth-client@if267: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether ee:86:01:ae:45:b0 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 10.1.1.20/24 scope global veth-client valid_lft forever preferred_lft forever inet6 fe80::ec86:1ff:feae:45b0/64 scope link valid_lft forever preferred_lft forever
由于arp_ignore设置为0, client客户端在做arp请求查询 10.1.1.10时 ,rs1将10.1.1.10在lo配置了VIP,rs1的veth-rs1,应答了arp请求, 于是更新arp信息。
#ip netns exec rs1 tcpdump -i veth-rs1 arp -netvv dropped privs to tcpdump tcpdump: listening on veth-rs1, link-type EN10MB (Ethernet), capture size 262144 bytes ee:86:01:ae:45:b0 > Broadcast, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Request who-has 10.1.1.10 tell 10.1.1.20, length 28 56:ff:71:bd:27:40 > ee:86:01:ae:45:b0, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Reply 10.1.1.10 is-at 56:ff:71:bd:27:40, length 28 56:ff:71:bd:27:40 > ee:86:01:ae:45:b0, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Request who-has 10.1.1.20 tell 10.1.1.11, length 28 ee:86:01:ae:45:b0 > 56:ff:71:bd:27:40, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Reply 10.1.1.20 is-at ee:86:01:ae:45:b0, length 28s
设置为1后, 查询10.1.1.10地址,lb 返回5a:xxx地址。后面rs1,rs2查询客户端client地址。
# ip netns exec client tcpdump -i veth-client arp -netvv dropped privs to tcpdump tcpdump: listening on veth-client, link-type EN10MB (Ethernet), capture size 262144 bytes ee:86:01:ae:45:b0 > Broadcast, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Request who-has 10.1.1.10 tell 10.1.1.20, length 28 5a:86:a3:16:85:08 > ee:86:01:ae:45:b0, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Reply 10.1.1.10 is-at 5a:86:a3:16:85:08, length 28 10.1.1.20 - - [03/Jun/2024 05:28:21] "GET / HTTP/1.1" 200 - 10.1.1.20 - - [03/Jun/2024 05:28:23] "GET / HTTP/1.1" 200 - 56:ff:71:bd:27:40 > ee:86:01:ae:45:b0, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Request who-has 10.1.1.20 tell 10.1.1.11, length 28 ee:86:01:ae:45:b0 > 56:ff:71:bd:27:40, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Reply 10.1.1.20 is-at ee:86:01:ae:45:b0, length 28 46:15:5c:b7:68:35 > ee:86:01:ae:45:b0, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Request who-has 10.1.1.20 tell 10.1.1.12, length 28 ee:86:01:ae:45:b0 > 46:15:5c:b7:68:35, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Reply 10.1.1.20 is-at ee:86:01:ae:45:b0, length 28
arp_announce设置2,发送arp请求时使用发送arp请求网卡的地址, 如果设置0,则可能不是
rs1的网卡配置
264: veth-rs1@if263: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 56:ff:71:bd:27:40 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 10.1.1.11/24 scope global veth-rs1 valid_lft forever preferred_lft forever inet6 fe80::54ff:71ff:febd:2740/64 scope link valid_lft forever preferred_lft forever 271: veth-rs1-extra@if270: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 66:82:27:71:76:15 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.168.1.2/24 scope global veth-rs1-extra valid_lft forever preferred_lft forever inet6 fe80::6482:27ff:fe71:7615/64 scope link valid_lft forever preferred_lft forever
通过给rs1添加一个网卡
ip link add veth-rs1-extra type veth peer name veth-rs1-extra-br ip link set veth-rs1-extra netns rs1 ip link set veth-rs1-extra-br master br0 ip link set veth-rs1-extra-br up ip netns exec rs1 ip addr add 172.168.1.2/24 dev veth-rs1-extra ip netns exec rs1 ip link set veth-rs1-extra up
在6.19内核版本是接口名称需要小于15
# ip link add veth-rs1-extra type veth peer name veth-rs1-extra^C # ip a|grep extr # ip link add veth-rs1-extra type veth peer name veth-rs1-extra-br Error: argument "veth-rs1-extra-br" is wrong: "name" not a valid ifname # ip link add veth-rs1-extra type veth peer name veth-rs1-extra RTNETLINK answers: File exists # ip link add veth-rs1-extra type veth peer name veth-rs1-ex-br # ip link set veth-rs1-extra netns rs1 # ip link set veth-rs1-ex-br master br0 # ip link set veth-rs1-ex-br up # ip netns exec rs1 ip addr add 172.168.1.2/24 dev veth-rs1-extra # ip netns exec rs1 ip link set veth-rs1-extra up
清除arp记录
ip netns exec client ip -s -s neigh flush all ip netns exec rs1 ip -s -s neigh flush all
设置arp_announce=0
ip netns exec rs1 sysctl -w net.ipv4.conf.all.arp_announce=0
使用tcpdump抓包br0,查看发送的arp报文
tcpdump -i br0 arp -netvv
在rs1发包
# ip netns exec rs1 ping -c 1 -I 172.168.1.2 10.1.1.20 PING 10.1.1.20 (10.1.1.20) from 172.168.1.2 : 56(84) bytes of data. --- 10.1.1.20 ping statistics --- 1 packets transmitted, 0 received, 100% packet loss, time 0ms
抓到的包, 可以看到mac是56:ff:71:bd:27:40, veth-rs1, 对应地址172.168.1.2
56:ff:71:bd:27:40 > Broadcast, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Request who-has 10.1.1.20 tell 172.168.1.2, length 28 ee:86:01:ae:45:b0 > 56:ff:71:bd:27:40, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Reply 10.1.1.20 is-at ee:86:01:ae:45:b0, length 28 ee:86:01:ae:45:b0 > Broadcast, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Request who-has 10.1.1.1 tell 10.1.1.20, length 28 1a:03:e9:42:52:6c > ee:86:01:ae:45:b0, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Reply 10.1.1.1 is-at 1a:03:e9:42:52:6c, length 28sshez
设置2时,再次ping
# ip netns exec rs1 sysctl -w net.ipv4.conf.all.arp_announce=2
# ip netns exec rs1 ping -c 1 -I 172.168.1.2 10.1.1.20
这时抓到包,第三行发出的arp已经从172.168.1.2 改为10.1.1.11
ee:86:01:ae:45:b0 > 1a:03:e9:42:52:6c, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Request who-has 10.1.1.1 tell 10.1.1.20, length 28 1a:03:e9:42:52:6c > ee:86:01:ae:45:b0, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Reply 10.1.1.1 is-at 1a:03:e9:42:52:6c, length 28 56:ff:71:bd:27:40 > ee:86:01:ae:45:b0, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Request who-has 10.1.1.20 tell 10.1.1.11, length 28 ee:86:01:ae:45:b0 > 56:ff:71:bd:27:40, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Reply 10.1.1.20 is-at ee:86:01:ae:45:b0, length 28
与GARP相关的三个参数 arp_accept, arp_notify, drop_gratuitous_arp
是否接收并更新arp table, 是否发送,是否抛弃。
GARP(Gratuitous ARP): 针对自己的IP和MAC进行广播的ARP,如果普通ARP是查找其他的主机地址,那么这个类型ARP就是主动推销自己。 在刚刚配置完网卡或者重启机器会发送这个GARP, 用于检测地址冲突。
另外在一些协议中如VRRP, HSRP中当主设备发送故障,备用设备接管也是通过发送GARP来更新虚拟IP的地址信息。
sudo arping -U <IP_address>
下面验证一下
# ip netns exec rs1 ip a 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 10.1.1.10/32 scope global lo valid_lft forever preferred_lft forever 264: veth-rs1@if263: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 56:ff:71:bd:27:40 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 10.1.1.11/24 scope global veth-rs1 valid_lft forever preferred_lft forever inet6 fe80::54ff:71ff:febd:2740/64 scope link valid_lft forever preferred_lft forever 271: veth-rs1-extra@if270: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 66:82:27:71:76:15 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.168.1.2/24 scope global veth-rs1-extra valid_lft forever preferred_lft forever inet6 fe80::6482:27ff:fe71:7615/64 scope link valid_lft forever preferred_lft forever # ip netns exec rs1 arp -a
ip netns exec rs1 sysctl -w net.ipv4.conf.veth-rs1-extra.arp_accept=0 net.ipv4.conf.veth-rs1-extra.arp_accept = 0 # ip netns exec rs1 sysctl -w net.ipv4.conf.all.arp_accept=0 net.ipv4.conf.all.arp_accept = 0 # ip netns exec client arping -U 10.1.1.20 ARPING 10.1.1.20 from 10.1.1.20 veth-client ^CSent 2 probes (2 broadcast(s)) Received 0 response(s) # ip netns exec rs1 arp -a # ip netns exec rs1 sysctl -w net.ipv4.conf.all.arp_accept=1 net.ipv4.conf.all.arp_accept = 1 # ip netns exec client arping -U 10.1.1.20 ARPING 10.1.1.20 from 10.1.1.20 veth-client ^CSent 3 probes (3 broadcast(s)) Received 0 response(s) # ip netns exec rs1 arp -a ? (10.1.1.20) at ee:86:01:ae:45:b0 [ether] on veth-rs1 ? (10.1.1.20) at ee:86:01:ae:45:b0 [ether] on veth-rs1-extra
可以看到设置为1 veth-rs1, veth-rs1-extra两个接口上都增加了arp记录, 内核在6.0上支持设置值为2 , 只在veth-rs1会增加记录。上面验证环境内核是 5.10.134, 下面用 6.1.9内核验证。
# ip netns exec rs1 sysctl -w net.ipv4.conf.all.arp_accept=2 net.ipv4.conf.all.arp_accept = 2 # ip netns exec client arping -U 10.1.1.20 ARPING 10.1.1.20 from 10.1.1.20 veth-client ^CSent 3 probes (3 broadcast(s)) Received 0 response(s) # ip netns exec rs1 arp -a ? (10.1.1.20) at 2e:46:eb:2f:33:37 [ether] on veth-rs1 ? (10.1.1.20) at 2e:46:eb:2f:33:37 [ether] on veth-rs1 # ip netns exec rs1 ip a 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 10.1.1.10/32 scope global lo:0 valid_lft forever preferred_lft forever 6: veth-rs1@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 0e:58:7e:b6:3e:d8 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 10.1.1.11/24 scope global veth-rs1 valid_lft forever preferred_lft forever inet6 fe80::c58:7eff:feb6:3ed8/64 scope link valid_lft forever preferred_lft forever 15: veth-rs1-extra@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 16:54:5c:45:63:31 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.168.1.2/24 scope global veth-rs1-extra valid_lft forever preferred_lft forever inet6 fe80::1454:5cff:fe45:6331/64 scope link valid_lft forever preferred_lft forever # ip netns exec client arping -U 10.1.1.20 ARPING 10.1.1.20 from 10.1.1.20 veth-client ^CSent 3 probes (3 broadcast(s)) Received 0 response(s) # ip netns exec rs1 arp -a gateway (10.1.1.1) at 06:aa:f9:6f:4b:42 [ether] on veth-rs1 ? (10.1.1.20) at 2e:46:eb:2f:33:37 [ether] on veth-rs1
相关内核提交
# ip netns exec rs1 tcpdump -i veth-rs1 -netvv 。。。 00:11:22:33:44:55 > Broadcast, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Request who-has 10.1.1.13 tell 10.1.1.13, length 28 00:11:22:33:44:55 > Broadcast, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Request who-has 10.1.1.11 tell 10.1.1.11, length 28
https://github.com/torvalds/linux/commit/e68c5dcf0aacc48a23cedcb3ce81b8c60837f48c
arp_notify;机器重启或mac地址更换是否发送arp
设置arp_notify
# ip netns exec rs1 sysctl -w net.ipv4.conf.all.arp_notify=1
更换mac
# rs1的veth-rs1更换mac # ip netns exec rs1 ip link set dev veth-rs1 address 00:11:22:33:44:55 [root@iZ8vbd88lmglnbsnad85q3Z ~]# ip netns exec rs1 ip a 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 10.1.1.10/32 scope global lo valid_lft forever preferred_lft forever 264: veth-rs1@if263: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:11:22:33:44:55 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 10.1.1.13/24 scope global veth-rs1 valid_lft forever preferred_lft forever inet 10.1.1.11/24 scope global secondary veth-rs1 valid_lft forever preferred_lft forever inet6 fe80::54ff:71ff:febd:2740/64 scope link valid_lft forever preferred_lft forever
# ip netns exec rs1 tcpdump -i veth-rs1 -netvv 00:11:22:33:44:55 > Broadcast, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Request who-has 10.1.1.13 tell 10.1.1.13, length 28 00:11:22:33:44:55 > Broadcast, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Request who-has 10.1.1.11 tell 10.1.1.11, length 28
通过tcpdump可以看到garp报文, 如果设置为0则不发送。
如果修改ip这个参数是不起作用的, redhat 有个修复是在ifup脚本中增加arping的指令发送garp
https://bugzilla.redhat.com/show_bug.cgi?id=1320366
https://github.com/fedora-sysv/initscripts/pull/24/commits/e7b5d95cb5d9ad73ce7c37b06dbf058034a95c72
https://medium.com/opsops/arp-stale-cache-and-a-rather-peculiar-arp-notify-behavior-in-linux-9c5105d07a49
drop_gratuitous_arp
https://patchwork.kernel.org/project/linux-wireless/patch/1454589080-21354-2-git-send-email-johannes@sipsolutions.net/
验证这个功能需要一个名字空间就可以
#查看arp table ip netns exec rs1 arp -a #如果存在, 使用arp -d删除 ? (10.1.1.20) at 00:11:22:33:55:99 [ether] on veth-rs1 ? (10.1.1.20) at 00:11:22:33:55:99 [ether] on veth-rs1-extra #ip netns exec rs1 arp -d 10.1.1.20 -i veth-rs1 #ip netns exec rs1 arp -d 10.1.1.20 -i veth-rs1-extra ip netns exec rs1 sysctl net.ipv4.conf.all.drop_gratuitous_arp net.ipv4.conf.all.drop_gratuitous_arp = 0
# ip netns exec client arping -U 10.1.1.20 ARPING 10.1.1.20 from 10.1.1.20 veth-client ^CSent 1 probes (1 broadcast(s)) Received 0 response(s) [root@iZ8vbd88lmglnbsnad85q3Z ~]# ip netns exec rs1 arp -a ? (10.1.1.20) at 00:11:22:33:55:99 [ether] on veth-rs1 ? (10.1.1.20) at 00:11:22:33:55:99 [ether] on veth-rs1-extras
设置drop_gratuitous_arp=1 , 并清理arptable
ip netns exec rs1 sysctl -w net.ipv4.conf.all.drop_gratuitous_arp=1 net.ipv4.conf.all.drop_gratuitous_arp = 1 # ip netns exec rs1 arp -d 10.1.1.20 -i veth-rs1 # ip netns exec rs1 arp -d 10.1.1.20 -i veth-rs1-extra # ip netns exec rs1 arp -a #再次发送garp, arp表未更新 # ip netns exec client arping -U 10.1.1.20 ARPING 10.1.1.20 from 10.1.1.20 veth-client ^CSent 2 probes (2 broadcast(s)) Received 0 response(s) # ip netns exec rs1 arp -a
参考及引用
关于arp 介绍
https://cizixs.com/2017/07/31/arp-protocol/
关于GARP
图片from曾彥博
Comments are closed.