proxy_arp原理

arp之calico本质

参考戳穿 Calico 的谎言

什么是代理ARP?
当 ARP 请求目标跨网段时,网关设备收到此ARP请求会用自己的MAC地址返回给请求者,这就是代理ARP .

知识点:

  • 跨网段通信时会发广播得到网关MAC
  • 之后发出的网络数据包目标MAC是网关的MAC
  • 网关的IP地址不会出现在任何网络包头中
  • 因此,没有人在乎网关地址是否真的存在,只要设备能响应ARP就行了

我这里用了2台linux主机实验,主机A:192.168.1.109 主机B:192.168.1.110
主机A:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ip  link add veth0 type veth peer name veth0_p
ip netns add ns0
ip link set veth0_p netns ns0
ip netns exec ns0 ip link set veth0_p name eth0
ip netns exec ns0 ip a add 10.10.10.10/24 dev eth0
ip netns exec ns0 ip link set eth0 up
ip netns exec ns0 ip route add 169.254.1.1 dev eth0
ip netns exec ns0 ip route add default via 169.254.1.1 dev eth0
[root@testarp-A ~]#ip netns exec ns0 route -n # 命名空间里的路由
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 169.254.1.1 0.0.0.0 UG 0 0 0 eth0
10.10.10.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
169.254.1.1 0.0.0.0 255.255.255.255 UH 0 0 0 eth0
ip link set veth0 up
ip route add 10.10.10.10 dev veth0
ip route add 10.10.10.20 via 192.168.1.110 dev eth0

主机B:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ip  link add veth0 type veth peer name veth0_p
ip netns add ns0
ip link set veth0_p netns ns0
ip netns exec ns0 ip link set veth0_p name eth0
ip netns exec ns0 ip a add 10.10.10.20/24 dev eth0
ip netns exec ns0 ip link set eth0 up
ip netns exec ns0 ip route add 169.254.1.1 dev eth0
ip netns exec ns0 ip route add default via 169.254.1.1 dev eth0
[root@testarp-B ~]# ip netns exec ns0 route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 169.254.1.1 0.0.0.0 UG 0 0 0 eth0
10.10.10.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
169.254.1.1 0.0.0.0 255.255.255.255 UH 0 0 0 eth0
ip link set veth0 up
ip route add 10.10.10.20 dev veth0
ip route add 10.10.10.10 via 192.168.1.109 dev eth0

Linux主机打开路由转发

1
net.ipv4.ip_forward = 1

网卡开启代理ARP功能

1
echo 1 > /proc/sys/net/ipv4/conf/veth0/proxy_arp

主机A上网络通信测试

1
2
3
4
5
[root@testarp-A ~]# ip netns exec ns0 ping 10.10.10.20
PING 10.10.10.20 (10.10.10.20) 56(84) bytes of data.
64 bytes from 10.10.10.20: icmp_seq=1 ttl=62 time=0.951 ms
64 bytes from 10.10.10.20: icmp_seq=2 ttl=62 time=0.484 ms
64 bytes from 10.10.10.20: icmp_seq=3 ttl=62 time=0.556 ms

1
2
3
4
5
6
7
[root@testarp-A ~]# tcpdump  -nni veth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth0, link-type EN10MB (Ethernet), capture size 262144 bytes
08:18:15.999200 IP 10.10.10.10 > 10.10.10.20: ICMP echo request, id 1486, seq 1, length 64
08:18:16.000288 IP 10.10.10.20 > 10.10.10.10: ICMP echo reply, id 1486, seq 1, length 64
08:18:21.008712 ARP, Request who-has 10.10.10.20 tell 10.10.10.10, length 28
08:18:21.008757 ARP, Reply 10.10.10.20 is-at ee:46:7c:2e:d9:ba, length 28

注意: 这里veth0充当路由角色代理ARP, who is 10.10.10.20 ,返回自己MACee:46:7c:2e:d9:ba来响应.

转发过程分析:
1 广播寻找目标IP对应MAC是谁?
2 根据路由规则所有数据包都会转发到169.254.1.1,寻找169.254.1.1MAC是谁?
2 vet0开启代理ARP进行ARP拦截,返回自己MACee:46:7c:2e:d9:ba给以响应
3 封包目标IP为10.10.10.20,MAC为ee:46:7c:2e:d9:ba,发出这样的数据包
4 主机A查询本地路由,匹配10.10.10.20 via 192.168.1.110 dev eth0 会把包发送给192.168.1.110
5 主机B收到10.10.10.20的包时,匹配本地路由10.10.10.20 dev veth0 scope link,数据包发送到veth0上
6 完成通信,回程类似