
网关Ping不通了换了好几台电脑还是这个症状。排查到最后十有八九都要回到ARP协议上来。我在现场见过不少类似故障电脑右下角明明显示“网络已连接”访问局域网却时好时坏ping网关丢包严重重启网卡能好一阵过一会儿又犯。这类问题通常不是IP配错而是负责“IP到MAC”解析的ARP出了岔子。ARPAddress Resolution Protocol是TCP/IP网络里最基础也最容易被忽视的协议它把逻辑上的IP地址翻译成物理网卡的MAC地址没有它任何基于IP的通信都跑不起来。这篇文章打算把ARP从原理到实战完整梳理一遍先讲清楚它到底在链路层做什么再逐字段拆报文用GNS3搭一个双路由器转发实验看ARP如何逐跳工作接着分析内网里常见的ARP欺骗结合SMB未强制签名的攻击场景最后给出华三S5110交换机上的ARP防护配置。适合网络运维、安全工程师以及正在网络模拟器里练手的初学者。1. 从一个“网络已连接却不通”的现场说起ARP到底在干什么1.1 IP地址与MAC地址的分工以及为什么不能直接用IP发帧以太网交换机的转发依据是数据帧二层头部里的目的MAC地址。交换机收到帧后查自己的MAC地址表看目的MAC对应哪个端口然后把帧从那个端口送出去。也就是说在一个局域网内部帧真正依赖的是MAC地址而不是IP地址。有人会问既然每台设备都有IP地址为什么不直接用IP地址发帧这要回到两种地址的设计定位上。IP地址是逻辑地址它解决的是“数据想到哪里去”的问题可以跨网段规划、聚合、路由MAC地址是物理地址出厂烧录解决的是“数据在这段物理链路上交给谁”的问题。可以这样理解IP地址像城市的门牌号逻辑清晰方便跨城市寻址MAC地址像身份证号全球唯一适合当面核对身份。寄信时地址写在信封上但快递员最终要把包裹递到具体某个人手上就必须核对身份证。二层帧在每一段物理链路上传输时源MAC和目的MAC都会被重写。这也就意味着以太网帧本身并不理解跨网段的“逻辑终点”它只需要知道“下一跳的物理身份”。这个“下一跳物理身份”的翻译任务就是ARP的核心职责。1.2 ARP的一次完整工作过程当一台主机要和另一台主机通信时它先把目的IP和自己的掩码做与运算判断目的IP是否在同一网段。如果在同一网段直接解析目的IP对应的MAC。如果不在同一网段主机查阅路由表发现报文要交给默认网关于是解析的是网关IP对应的MAC而不是最终目标IP的MAC。初学者最容易在这里绕晕后面GNS3实验里会看得非常清楚。ARP的工作过程其实很朴素就四步主机检查本地ARP缓存看目的IP有没有对应的MAC记录有就直接用没有就继续。主机在局域网内广播一条ARP请求“谁是192.168.1.1请把你的MAC地址告诉192.168.1.100我。”网段内所有设备都会收到这条广播但只有IP地址为192.168.1.1的设备才会回复。目标设备以单播方式回复自己的MAC地址请求方收到后更新ARP缓存之后就可以封装二层帧正常通信了。这里有个值得注意的设计ARP请求是广播ARP应答却是单播。原因是ARP请求报文里已经携带了发送方的MAC和IP应答方把这个信息记下来后可以直接给发送方回单播没必要再广播一次。在IPv6网络中ARP被NDP邻居发现协议取代。NDP基于ICMPv6的NS邻居请求和NA邻居通告报文实现地址解析功能比ARP更丰富但这篇文章聚焦IPv4环境因为绝大多数存量内网和运维故障还是ARP的天下。1.3 ARP缓存——为什么第二次ping总是快ARP缓存是ARP协议能够“一次解析、多次使用”的关键。如果每次发一个包都广播一次局域网早就被广播报文淹没了。缓存机制把IP到MAC的映射保存一段时间在这段时间内通信直接查表不重新解析。所以你会看到一种很常见的现象ping一个设备第一包可能超时第二包开始恢复。第一次ping触发ARP解析广播请求发出去后目标设备回复然后ICMP Echo Request才被封装成帧发出去整个过程要多花几毫秒到几十毫秒。如果对方服务器临睡、CPU忙第一包超时就更是常态。很多运维看到第一包丢了就紧张其实这是正常现象。查看和清空ARP缓存的命令也不复杂Windows下用arp -a查看arp -d清空。Linux下用ip neigh查看ip neigh flush all清空。华为/华三设备上用display arp查看reset arp all清空。思科设备上用show arp查看clear arp-cache清空。清ARP缓存这个动作在网络变更时很实用。比如更换网关设备、改动服务器网卡后终端上残留的旧ARP缓存会导致通信异常这时去终端上清一下缓存往往比重启网卡更快。要注意在生产网络高峰期清设备ARP缓存会导致设备重新广播解析瞬时CPU和广播流量会有小高峰批量操作前要评估影响。2. ARP报文逐字拆解请求、应答与免费ARP2.1 28字节报文的每一段以及为什么它这么“抠门”在Wireshark里抓一个ARP包展开后能看到非常紧凑的28字节报文体。这28字节一个字节都没浪费字段长度说明硬件类型2字节链路层类型以太网为0x0001协议类型2字节网络层协议类型IPv4为0x0800硬件地址长度1字节MAC地址长度通常为6协议地址长度1字节IP地址长度通常为4操作码2字节1表示ARP请求2表示ARP应答发送方MAC6字节发起方的MAC地址发送方IP4字节发起方的IP地址目标MAC6字节请求时全0应答时填实际MAC目标IP4字节请求方想解析的IP地址以太网帧头里类型字段是0x0806表示这个帧承载的是ARP报文。整个帧最小长度是64字节含前导码和FCSARP报文体28字节加以太网帧头14字节一共42字节不足64字节的部分由PAD填充。所以Wireshark里看一个纯ARP广播帧经常显示“Ethernet II, Src: …, Dst: …”和42字节的Length但实际线上传输长度是64字节。初次抓包的人容易对不上这个数知道填充机制就不困惑了。一个典型的ARP请求抓包关键字段如下Ethernet II, Src: 08:00:27:2a:3b:4c, Dst: ff:ff:ff:ff:ff:ff Type: ARP (0x0806) Address Resolution Protocol (request) Hardware type: Ethernet (1) Protocol type: IPv4 (0x0800) Opcode: request (1) Sender MAC address: 08:00:27:2a:3b:4c Sender IP address: 192.168.1.100 Target MAC address: 00:00:00:00:00:00 Target IP address: 192.168.1.1对应的ARP应答则把Opcode改为reply发送方MAC和IP填目标设备自己的信息目标MAC和IP填发起方的信息目的MAC也从广播地址变成了发起方的单播MAC。整个交换过程只有两条报文简洁高效。2.2 免费ARP一个被低估的“自我介绍”免费ARPGratuitous ARP是一种特殊的ARP请求特点是发送方IP和目标IP完全相同。设备主动发送这种报文本质上是在广播宣告“我是192.168.1.1我的MAC是00:50:79:66:68:00。”免费ARP有三个很实际的用途IP地址冲突检测新设备上线时发一条免费ARP看看有没有人应答如果有人回复说明网内已经存在相同IP的设备就会触发冲突告警。主动通告MAC变化设备更换网卡、启用备用链路、服务切换后通过免费ARP让周边设备尽快更新ARP缓存缩短黑洞期。VRRP/HA主备切换虚拟IP从主设备漂移到备设备后新主设备立刻向外发免费ARP交换机才会把虚拟IP对应的MAC表项刷新到新主设备所在的端口上。我在排查VRRP切换后业务中断时经常第一件事就是检查交换机上虚拟IP对应的MAC有没有更新过来。如果免费ARP没发出去交换机的MAC表还指向旧端口流量就会一直往黑洞里送。免费ARP在Wireshark里也能直接看到特征很明显请求报文里Sender IP和Target IP完全相同。很多内网攻击的第一步也是发大量免费ARP这点在后面场景分析里会再提到。2.3 协议栈眼中的ARPLinux内核里的解析模块ARP不是一个独立运行的进程它内嵌在内核协议栈的网络层和链路层之间。了解Linux下几个关键参数能让网络排障少走弯路。第一个是arp_accept。它控制内核收到“未请求的ARP应答”时是否更新ARP缓存表。默认情况下Linux对收到的ARP应答比较宽容即使之前没发过请求也会根据应答内容更新缓存。这在安全上是个隐患攻击者不需要等主机发出ARP请求直接发一条伪造应答就能把受害者的ARP表改掉。在安全要求高的环境里可以把arp_accept设为0降低对无请求应答的信任度。第二个是arp_ignore和arp_announce这两个参数在做LVS负载均衡或者多网卡服务器时非常关键。回想一个常见故障服务器上有两个网卡一个内网IP一个VIP虚拟IP内网其他设备在局域网里广播查询VIP的MAC时服务器的非VIP网卡也抢着应答导致VIP流量进了错误接口。解决办法就是在相关接口上设置net.ipv4.conf.all.arp_ignore 1 net.ipv4.conf.all.arp_announce 2arp_ignore1表示只对本机已配置且属于接收请求的接口IP进行ARP应答其他接口不代答arp_announce2表示发送ARP通告时使用最佳本地地址避免把VIP带出去乱宣告。这两个参数对做高可用方案的人来说属于必须吃透的“救命参数”。3. GNS3仿真实验两个路由器接力转发时ARP的逐跳解析过程3.1 实验拓扑与基础配置光看协议描述不够直观我在GNS3里搭过一个经典拓扑来验证ARP的逐跳行为两台路由器中间互联两边各接一台终端。地址规划如下设备接口IP地址掩码网关PC1VPCS192.168.1.10255.255.255.0192.168.1.1R1G0/0192.168.1.1255.255.255.0-R1G0/1172.16.1.1255.255.255.252-R2G0/0172.16.1.2255.255.255.252-R2G0/1192.168.2.1255.255.255.0-PC2VPCS192.168.2.10255.255.255.0192.168.2.1拓扑连接关系是PC1接R1的G0/0R1的G0/1接R2的G0/0R2的G0/1接PC2。在GNS3里我用的是c7200镜像PC用VPCS轻量而且用起来方便。路由器配置很常规R1(config)# interface GigabitEthernet0/0 R1(config-if)# ip address 192.168.1.1 255.255.255.0 R1(config-if)# no shutdown R1(config)# interface GigabitEthernet0/1 R1(config-if)# ip address 172.16.1.1 255.255.255.252 R1(config-if)# no shutdown R2(config)# interface GigabitEthernet0/0 R2(config-if)# ip address 172.16.1.2 255.255.255.252 R2(config-if)# no shutdown R2(config)# interface GigabitEthernet0/1 R2(config-if)# ip address 192.168.2.1 255.255.255.0 R2(config-if)# no shutdown路由用静态方式逻辑最清晰R1(config)# ip route 192.168.2.0 255.255.255.0 172.16.1.2 R2(config)# ip route 192.168.1.0 255.255.255.0 172.16.1.1VPCS配置PC1 ip 192.168.1.10 255.255.255.0 192.168.1.1 PC2 ip 192.168.2.10 255.255.255.0 192.168.2.1全部配好后先确认PC1能ping通自己的网关PC2也能ping通自己的网关。如果这段都通不了说明模拟器里的链路或者接口配置有误先解决基础连通性再看ARP。3.2 第一次ping三段链路上的ARP请求与应答在PC1上发起ping 192.168.2.10同时在三段链路上分别抓包。第一次通信时PC1和R1的ARP缓存都是空的整个流程会非常有层次地展开。链路1PC1到R1之间PC1发现192.168.2.10不在自己的网段先查本地路由表命中默认网关实际要转发给192.168.1.1。PC1的ARP缓存里没有192.168.1.1的条目于是发出ARP广播请求谁有192.168.1.1请把MAC告诉我。R1的G0/0接口收到后发现目标IP是自己单播回复。PC1拿到R1 G0/0的MAC后把ICMP Echo Request封装成帧发出去帧头目的MAC填R1 G0/0的MAC源MAC填PC1自己的MAC。链路2R1到R2之间R1收到数据帧后剥离二层头部看到目的IP是192.168.2.10查路由表发现出接口是G0/1下一跳是172.16.1.2。这时R1检查自己的ARP缓存如果没有172.16.1.2对应的MAC就会在G0/1接口上广播ARP请求谁有172.16.1.2R2的G0/0收到后单播应答。R1拿到MAC后重新封装二层帧从G0/1发出。此时帧的源MAC已经变成R1 G0/1的MAC目的MAC是R2 G0/0的MAC但内层IP报文的源IP仍然是192.168.1.10目的IP仍然是192.168.2.10。链路3R2到PC2之间R2收到帧后同样剥离二层头部发现目的IP是192.168.2.10是自己直连网段。R2查ARP缓存如果没有PC2的MAC就在G0/1接口上广播ARP请求谁有192.168.2.10PC2单播回复。R2封装新帧发送给PC2。PC2收到ICMP Echo Request后按原路径反向回复。这个实验最直观的结论是同一份ICMP报文从PC1到PC2要经过三次独立的ARP解析每一跳的源MAC和目的MAC都被改写了。IP地址从始至终不变但MAC地址每一跳都不同。这也解释了为什么说“二层帧是点到点的IP报文是端到端的”。3.3 为什么每一跳都要重新做ARP以及实验里容易踩的坑有人会问既然PC1知道PC2的IP是192.168.2.10为什么不让路由器之间直接传递“PC2的MAC”原因在于以太网帧的二层地址在传输过程中没有“透传”能力。路由器收到一个以太网帧后它不知道也不关心原始帧的目的MAC是什么它只根据IP层的目的IP查路由表然后决定“我这个出接口的下一跳是谁”再在当前网段里重新解析下一跳的MAC地址。通俗地说IP层的逻辑路由决定了“往哪走”ARP决定“这段路交给谁”每走一段路都要重新问一次。所以你在R1上执行show arp能看到它自己接口的MAC、PC1的MAC、R2 G0/0的MAC但看不到PC2的MAC。R1和PC2之间从没有在同一个以太网网段内直接通信过自然不需要解析PC2的MAC。实验里容易踩的坑我列几个实测过的经验抓包位置要和观察目标对应。想看PC1发出去的ARP广播就在PC1和R1之间的链路上抓想看R1转发时的ARP解析就在R1和R2之间的链路上抓。GNS3里对着链路右键选Start Capture比在路由器上用debug spooling更直观。第一次ping丢包不要慌。首次通信必然伴随ARP解析缓存为空时第一包超时完全是正常流程。等ARP表建立后再ping延迟就稳了。可以用debug ip arp观察实时状态但路由器CPU小的模拟器环境下输出量大时会卡建议只盯着某台设备开一段时间就关。清缓存的命令要记牢。VPCS里用arp -d清空host端缓存真实设备上R1和R2用clear arp-cache清空路由器缓存否则复现实验时ARP表已经建好看不到完整的广播解析过程。代理ARP的干扰。很多路由器接口默认为ip proxy-arp开启状态。在特定情况下路由器的某个接口会对跨网段的ARP请求代为应答抓包时就会看到一些意料之外的ARP应答。如果在实验里发现网络通但抓包结果和理论对不上先检查接口下的proxy-arp是不是被意外触发。4. ARP欺骗遇上SMB未强制签名一条成熟的内网攻击链4.1 为什么一个老协议能骗到今天ARP协议设计得太“单纯”了。它运行在以太网这个缺乏认证的广播域里主机收到ARP应答时不会验证“这个应答是不是我发起的请求对应的响应”甚至不会验证“发送方IP对应的MAC是不是真的”直接就按收到的内容更新ARP缓存。攻击者不需要等受害者发请求主动塞一条应答就完成了投毒。典型的ARP欺骗流程是这样的攻击者持续向受害主机发送伪造的ARP应答内容大致是“192.168.1.1网关的MAC是攻击者的MAC”。为了做得更彻底攻击者还会向真正的网关发送伪造的ARP应答内容大致是“192.168.1.100受害主机的MAC是攻击者的MAC”。这样一来受害主机发给网关的所有报文都会先到达攻击者网关发给受害主机的报文也会先经过攻击者攻击者就处在了双向的中间人位置。抓包时这类攻击最常见的特征是某个IP对应的MAC地址在短时间内频繁变化而且网关IP会不明原因地出现在多台设备的ARP表里。Wireshark的Expert Info有时候会直接提示“Duplicate IP address detected”这是一个很明显的信号。需要强调ARP欺骗的测试只应该在隔离的实验网里做。在真实办公网里搞这套轻则断线瘫痪重则惹上麻烦完全没有必要。4.2 SMB签名机制与“未强制”意味着什么SMBServer Message Block协议是Windows环境下文件共享、打印机共享、远程管理的基础协议。内网里大量Windows机器之间共享文件夹、互相拷文件走的都是SMB。SMB签名机制就是在每条SMB消息上附加一个消息级别的认证标记接收方校验这个标记来确认消息没有被篡改过。问题在于Windows系统对SMB签名的传统默认策略是“客户端自动协商服务器已启用但尽可能使用”并不是强制要求。换句话说如果通信双方都允许不签名那么新会话完全可以建立成无签名模式。一旦SMB会话运行在无签名状态下中间人就可以在转发SMB流量的过程中修改文件内容、替换传输数据甚至把用户请求的应用下载包换成恶意程序接收方完全察觉不到因为根本没有签名校验这一层保护。这也是为什么“ARP欺骗SMB未强制签名”会成为内网里很常见的一种攻击组合。ARP欺骗负责拿下中间人位置SMB未签名负责让篡改不被发现。两者缺一不可没有ARP欺骗攻击者上不了“中间人”的牌桌没有SMB未签名流量即使被截到也无法无痕篡改。防住这类攻击需要两头堵。在终端与服务器侧域环境里应当通过组策略强制开启SMB签名计算机配置 → Windows设置 → 安全设置 → 本地策略 → 安全选项“Microsoft 网络服务器对通信进行数字签名始终”设置为“已启用”“Microsoft 网络客户端对通信进行数字签名始终”设置为“已启用”同时尽量禁用SMBv1协议SMBv1存在过多老旧的兼容和安全问题现代网络里已经没必要保留它。在网络侧则要尽可能让攻击者无法建立中间人链路这就引出了下一节的接入交换机防护。4.3 如何发现网内是否有人在打ARP欺骗对运维和普通用户来说最实用的排查方法是“两侧对比找不一致”在受影响的电脑上打开命令提示符执行arp -a查看网关IP对应的MAC地址。在核心交换机或防火墙上执行display arp查看真正的网关IP对应MAC。两个MAC如果不一致说明终端到网关之间出现了异常节点大概率是ARP欺骗在做手脚。从交换机侧来看还可以查MAC地址表的分布。正常情况下一台PC的一个MAC地址应该只出现在一个端口上如果发现同一个MAC地址出现在多个端口或者一个端口上的MAC数量异常多那就要警惕了。检查点正常情况异常情况终端arp -a中的网关MAC与核心侧一致与核心侧不一致交换机MAC表端口对应一个MAC对应一个端口一个MAC对应多个端口单端口MAC数量与接入设备数量匹配异常增长Wireshark抓包偶尔有ARP请求/应答大量无请求的ARP应答广播5. 华三S5110接入交换机上的ARP防护落地配置5.1 先想清楚二层的攻击要靠在二层设备上挡住终端装杀毒软件、服务器开防火墙这些是针对应用层和主机的防御但ARP欺骗发生在二层最有效的拦截位置恰恰是终端接入的这台交换机。华三S5110这类二层接入交换机在硬件和软件层面具备一套完整的ARP防护机制日常运维中我会用到其中几个核心功能。防护思路可以分四层DHCP Snooping建立IP-MAC-PORT-VLAN绑定表。只有通过DHCP正常获取IP的主机才会生成合法绑定表伪造源、私自配置IP的设备没有表项。ARP Detection检查每个ARP报文的合法性。用户口收到的ARP报文如果IP-MAC对应关系和DHCP Snooping绑定表不一致直接丢弃。信任口/非信任口设计。交换机上联到核心交换机或路由器的口以及DHCP服务器所在的口设置为信任口不检查直接接用户终端的口设置为非信任口严格检查。ARP限速。即使攻击者想用大量ARP报文打满交换机CPU也通过限制每秒ARP包数量来降低影响。5.2 S5110上的具体配置下面是我在实际环境里部署过的一套基础配置适用于华三S5110系列运行Comware V5或V7的交换机。不同软件版本命令细节可能有差异配置前用display version确认一下版本即可大方向不会变。# 全局开启DHCP Snooping [H3C] dhcp snooping enable # 进入上联口该口接核心交换机设置为DHCP Snooping信任口 [H3C] interface GigabitEthernet1/0/24 [H3C-GigabitEthernet1/0/24] dhcp snooping trust # 同时设置该口为ARP Detection信任口 [H3C-GigabitEthernet1/0/24] arp detection trust [H3C-GigabitEthernet1/0/24] quit # 进入接入用户口限制ARP报文速率防止单端口ARP洪泛 [H3C] interface GigabitEthernet1/0/1 [H3C-GigabitEthernet1/0/1] arp rate-limit 64 [H3C-GigabitEthernet1/0/1] quit # 全局使能ARP Detection并校验ARP报文的源MAC、源IP和目的MAC [H3C] arp detection enable [H3C] arp detection validate dst-mac ip src-mac # 为固定IP的服务器或打印机手工配置静态绑定表 [H3C] arp detection-binding ip-address 192.168.1.50 mac-address 0001-0001-0001 vlan 10配置的逻辑串起来看是这样的DHCP Snooping先建立可信基础ARP Detection在这个基础上做实时检查信任口保证上联和DHCP服务器不受阻碍接口限速兜底防洪泛。整个方案不需要对终端做任何改动对办公网最友好。网关如果不在核心交换机上而是在防火墙上S5110上联防火墙的口也要做同样的arpl detection trust。原则是到默认网关方向的链路必须信任否则正常网关ARP应答被交换机误删反而造成全网掉线。5.3 验证防护是否生效以及最容易翻车的几个现场配置完成后不能直接收工要做几个验证。先在交换机上查看绑定表是否建立[H3C] display dhcp snooping binding如果终端是通过DHCP获取IP的这里能看到IP、MAC、VLAN、接口一一对应的绑定条目。再查看ARP检测的统计信息[H3C] display arp detection这个命令会显示各端口上检查通过和丢弃的ARP报文计数。正常环境下discard统计应该基本不动如果有人试图伪造ARP报文计数会快速增长同时网络里也会出现对应症状。验证环节最容易翻车的几个场景我单独拎出来说固定IP打印机被误杀。开启ARP Detection后打印机、门禁控制器、服务器这些手工配置IP的设备如果之前在交换机上没有绑定表它们的ARP报文会被当作非法报文丢弃直接表现是“打印机打印时好时坏”“服务器间歇性断网”。应对方式是把固定IP设备提前做成静态绑定表别等业务断了再排查。DHCP服务器接在非信任口。如果DHCP服务器不在上联口的“上游”而是单独用一台服务器跑在某个接入端口上记得在该端口配置dhcp snooping trust。否则DHCP Offer报文会被交换机丢弃终端压根获取不到地址。AR P Detection信任口和下联口搞反。信任口和DHCP信任口都只应配置在真正可信的上联、服务器方向一旦把用户口设成信任口等于防护功能形同虚设所有用户口的ARP报文都不检查了。老设备掉线问题。部分老旧操作系统的终端在启用ARP检测的严格模式下可能会有兼容性波动。建议先在测试VLAN里灰度跑两天观察是否有终端异常掉线再逐步推广到全网。还可以配合端口安全加固把端口允许学习的MAC数量限制为1能进一步防止私接路由器和MAC仿冒[H3C] interface GigabitEthernet1/0/1 [H3C-GigabitEthernet1/0/1] port-security enable [H3C-GigabitEthernet1/0/1] port-security max-mac-count 1这条命令的风险在于如果用户自行更换电脑或网线换端口需要重新学习MAC要提前做好解释和变更流程。生产网里用端口安全时要谨慎更需要配合完善的IT管理制度。我几次部署下来感受最深的一点是ARP防护不是“开一个开关就能永久无事”的功能它依赖于网络基础数据准确。网内DHCP服务要稳定、固定IP设备要有规范台账、交换机端口要提前梳理角色防护才能真正发挥作用。如果网内DHCP本来就乱、地址经常冲突直接开ARP Detection反而会把问题放大。所以第一步永远是盘点资产、理清IP-MAC对应关系而不是急着敲命令。