ARP与Proxy ARP 电脑版发表于:2022/5/11 22:24  >#ARP与Proxy ARP [TOC] ARP简介 ------------ tn2>当我们有两个PC通过三层路由进行通信时,我们的路由既希望拿到目标主机的IP也希望拿到目标主机的Mac地址的时候(因为IP报文必须封装成帧才能通过物理网络发送,因此发送方还需要找到接收方的物理MAC地址),ARP就产生了,它会获取目标主机的Mac地址与IP地址(也可以理解为将IP地址解析尾MAC地址的协议)。并且会产生一张ARP的表,用于存储IP地址和MAC地址的关系。一般ARP表项包括动态ARP表项和静态ARP表项。 ARP实验与分析 ------------ tn2>首先创建`AR1220`的三层路由器,然后添加两台PC配置分别如下。  ```bash PC6 192.168.1.2/24 255.255.255.0 192.168.1.1 PC7 192.168.2.2/24 255.255.255.0 192.168.2.1 ```   tn2>然后我们可以通过如下命令去配置路由器,绑定接口与网关。 ```bash # 查看ARP表 dis arp system-view # 配置PC6接口与网关地址 int G0/0/1 ip a 192.168.1.1 24 # 查看当前配置情况 dis this # 配置PC7接口与网关地址 int G0/0/0 ip a 192.168.2.1 24 # 查看当前配置情况 dis this # 查看配置表情况 dis ip int b # 禁用当前接口 undo shut ```  tn2>然后我们来抓`GE0/0/1`的接口,然后我们通过PC6向PC7发包来进行分析。   tn2>首先第一个包,是一个广播包`54-89-98-CA-13-B5`物理Mac是我们PC6主机的,发了一个广播包(全`f`)。 接着我们来看第二个Arp包。   tn2>我们发现它是从AR2的网关`192.168.1.1`发往PC6的。为什么会这样? 其实就好像PC6说我要找PC7,然后网关`192.168.1.1`(G0/0/1接口)说我帮你找到了,你要找PC7找我就好了,我帮你转告PC7。然后PC6就在本地记录了网关的ip与mac地址。 我们可以通过`arp -a`查看本地记录的arp表  tn2>然后我们来看我们的ping包,可以看到首先PC6把包发往了网关,然后路由再根据路由表发往了指定的IP地址的mac主机PC7。  tn2>关于包中字段的意思如下:  tn2>获取接口的Mac地址 ```bash # 查看g0/0/0接口信息,其中有MAC地址 dis int g0/0/0 ``` tn2>从PC6发往PC7时,源IP和目的IP一直都没变,但是源MAC和目的MAC一直在变。 ```mermaid graph LR PC6[PC6 MAC]-->GE0((GE 0/0/1 MAC)) GE0((GE 0/0/1 MAC))-->GE1((GE 0/0/0 MAC)) GE1((GE 0/0/0 MAC))-->PC7[PC7 MAC] ``` ## Proxy ARP tn2>企业内部进行子网划分时,可能会出现两个子网网络属于同一网段,但是却不属于同一物理网络的情况,两个子网网络间被路由器分割。这时可以通过网络内主机的路由信息,使发往其他子网的数据先发送到连接不同子网的网关设备上,再由网关设备转发此数据报文。但是这种解决方案需要配置子网中所有的主机的路由,并不便于管理和维护。 在网关上部署路由式Proxy ARP功能,可以有效解决子网划分带来的管理和维护方面的问题。路由式Proxy ARP的功能可以使IP地址属于同一网段却不属于同一物理网络的主机间能够相互通信,并且主机上不需要配置缺省网关,便于管理和维护。 路由式Proxy ARP组网如图所示。Router通过接口IF1和IF2连接两个子网网络,接口IF1和接口IF2的IP地址不在同一个网段。子网1内的主机Host_1与子网2内的主机Host_2的IP地址也在同一网段。主机Host_1和Host_2上未配置缺省网关。在Router上配置路由式Proxy ARP可以使子网1和子网2内主机间能够互相通信。  tn2>注意:Host1主机的`192.168.1.1/16`与Host2主机的`192.168.2.1/16`是在同一网段下,因为在以前我们讲到过,ip一位占8bit,这里写的`16`占两位,所以他们都是在`192.168.0.0`下,所以他们是在同一网段中。 要想使同一网段不同子网通信,只需要在R1路由器中启动ARP Proxy就可以了。 (下面我们来操作演示一下)  tn2>首先需要更具我们刚刚讲的PC进行配置。   tn2>然后我们需要在ARP中进行配置启动ARP代理 ```bash # 找到0/0/0接口 interface GigabitEthernet0/0/0 # 配置ip ip address 192.168.1.254 255.255.255.0 # 启动arp代理 arp-proxy enable interface GigabitEthernet0/0/1 ip address 192.168.2.254 255.255.255.0 arp-proxy enable # 查看配置情况 dis ip int b ```  tn>注意:如果不进行启动arp代理,包发出去后就回不来了。 tn2>运行测试:  ## Linux ARP Proxy tn>接下来我们来实现Linux下的ARP Proxy。  tn2>我这里的环境是两台Ubuntu系统,所以在此之前请关闭防火墙。 ```bash # 关闭防火墙 sudo ufw disable ``` tn2>下载抓包工具 ```bash apt-get install bison flex wget http://www.winpcap.org/install/bin/WpcapSrc_4_1_2.zip unzip WpcapSrc_4_1_2.zip cd winpcap/wpcap/libpcap chmod +x configure runlex.sh CFLAGS=-static ./configure make cd rpcapd ``` tn2>按照上面的图,首先我们在第一台机器创建虚拟网卡对,创建`ns0`网络名称空间,然后为`ns0`网络名称空间的`eth0`配置IP`10.1.1.10/24`并激活网卡。 ```bash # 创建虚拟网卡对eth0 ip l a veth0 type veth peer name eth0 # 创建名称空间 ip netns add ns0 # 关联网络名称空间于虚拟网卡 ip l s eth0 netns ns0 # 配置网络名称ip ip netns exec ns0 ip a a 10.1.1.10/24 dev eth0 # 激活网卡 ip netns exec ns0 ip l s eth0 up # 查看网络情况 ip netns exec ns0 ifconfig ```  tn2>然后我们添加一个不存在且受保护的ip`169.254.1.1`,让它作为网关发出去,然后通过ARP代理又以相同的接口返回回来。 目的是:当ns0发送 ARP 请求服务器 `169.254.1.1` 的 MAC 地址,`veth0` 收到这个请求时会进行判断,由于目标 `169.254.1.1` 不属于本网段(即跨网段),此时便返回自己的接口 MAC 地址给 ns0,后续ns0(`10.1.1.10`)访问ns1(`10.1.1.20`)时,目标 MAC 直接封装为 MAC254。  ```bash # 添加本地交换路由 clico ip netns exec ns0 ip route add 169.254.1.1 dev eth0 scope link # 添加默认路由 ip netns exec ns0 ip route add default via 169.254.1.1 dev eth0 # 启动arp_proxy代理 echo 1 > /proc/sys/net/ipv4/conf/veth0/proxy_arp ```  tn2>查看路由表,并删除ns0默认路由`10.1.1.0`的记录,然后激活网卡,并在路由表中添加好接收有`10.1.1.10`的路由记录。 以及添加`10.1.1.20`的出处为Host1的Ip,并且是从ens3出去的。(这里根据自己的实际情况做调整) ```bash # 查看路由表 ip netns exec ns0 route ip netns exec ns0 route -n # 删除虚拟网卡对 ip netns exec ns0 route delete -net 10.1.1.0 netmask 255.255.255.0 # 激活网卡 ip l s veth0 up # 添加路由 ip route add 10.1.1.10 dev veth0 scope link ip route add 10.1.1.20 via 10.0.0.3 dev ens3 ```  tn2>veth0的mac。  tn2>接下来Host1需要执行的是一样的命令。 ```bash arp -a # 创建虚拟网卡对 ip l a veth0 type veth peer name eth0 # 添加网络名称空间 ip netns a ns1 # 绑定虚拟网卡到ns1中 ip l s eth0 netns ns1 # 绑定IP到ns1中的eth0网卡 ip netns exec ns1 ip a a 10.1.1.20/24 dev eth0 # 激活ns1中的eth0网卡 ip netns exec ns1 ip l s eth0 up # 添加路由 ip netns exec ns1 ip route add 169.254.1.1 dev eth0 scope link ip netns exec ns1 ip route add default via 169.254.1.1 dev eth0 echo 1 > /proc/sys/net/ipv4/conf/veth0/proxy_arp # 删除默认路由记录 ip netns exec ns1 route delete -net 10.1.1.0 netmask 255.255.255.0 # 激活eth0网卡 ip l s veth0 up # 查看网卡 route -n # 访问 10.1.1.20 从默认路由出去 ip route add 10.1.1.20 dev veth0 scope link # 要想访问 10.1.1.10 从ens33出去找到172.12.1.10的ip ip route add 10.1.1.10 via 10.0.0.2 dev ens3 # 查看网络名称空间ns1的路由规则 ip netns exec ns1 route -n ``` tn2>然后我们开启一个新的终端进行抓包。 ```bash # Host1抓包 tcpdump -i veth0 -e -nn # Host2抓包 tcpdump -i veth0 -e -nn # 运行测试 ip netns exec ns0 ping 10.1.1.20 ```  tn2>测试没有问题。下图是我们抓的包。   tn2>通过抓包我们会发现,ns0的eth0会先去问veth0谁是`169.254.1.1`?veth0说他也不晓得,但是我可以把我的mac给你,我这边的路由可以给你用。ns0说好好好。然后他就去请求`10.1.1.20`但这个`10.1.1.20`我本身没得但是我有veth0的mac地址,veth0所处的路由表有我以它的身份去访问就行。(所以就把ns0的mac身份证改成veth0的mac身份证,IP不变然后就去访问)。到了Host1那边veth0又问谁是`10.1.1.20`?然后那边eth0就回答我是。 ## 好处 tn2>这样做的好处如下: 1.通过将所有流量引导到一个特殊的网关 `169.254.1.1`,从而引流到主机的 `veth0` 网络设备上,最终将二三层流量全部转换成三层流量来转发。 2.在主机上通过开启代理 ARP 功能来实现 ARP 应答,使得 ARP 广播被抑制在主机上,抑制了广播风暴,也不会有 ARP 表膨胀的问题。(也就是只在veth0和eth0之间有arp包不会向其他网卡发送广播) tn>如果是Bridge的话将会向所有连接的进行广播,从而造成网络瘫痪。 tn2>其他:https://cloud.tencent.com/developer/article/1495301