1. 先还原现场从一次“诡异断网”说起那天下午的体感非常典型办公网突然开始丢包ping网关一会儿延迟正常一会儿飙到几千毫秒网页时不时被插进一个假的“安全认证”页面输入账号密码后毫无反应。登录机房里的Linux服务器一看arp -a里的网关MAC已经变成一个眼生的地址而它在几分钟前还是我亲手记录的官方地址。这就是标准的ARP欺骗攻击属于局域网内最容易发生、也最容易被低估的安全事件。这篇文章想把我在Linux上防御ARP欺骗的整套思路和配置讲清楚从ARP协议为什么会被人利用到静态绑定、arptables过滤、sysctl加固、arpwatch监控这些手段分别怎么用、为什么这么用最后再补上我在实际环境里踩过的坑。适合Linux运维、网络管理员以及第一次接触内网安全的新手——尤其是那些负责固定服务器、机房设备的同学这套方案可以直接抄作业。1.1 ARP协议为什么天生就“不设防”ARPAddress Resolution Protocol地址解析协议的作用很单纯在局域网里把IP地址翻译成MAC地址。IP是逻辑地址真正在以太网上传输数据靠的是MAC地址。当主机A想和192.168.10.1通信时它先查自己的ARP缓存表查不到就在整个广播域发一条广播“谁是192.168.10.1请把你的MAC地址告诉我。”目标主机收到后回一句“我是192.168.10.1我的MAC是xx:xx:xx:xx:xx:xx。”A就把这个映射记下来之后直接按这个MAC发包。问题出在两个地方。第一ARP请求和应答都默认“无条件信任”任何人都可以发一条ARP回复说“192.168.10.1的MAC是我”而且很多操作系统即使收到非请求的ARP应答也会直接更新缓存也就是攻击者不需要先问就能投毒。第二ARP处于以太网和IP之间不是完整的网络层协议传统防火墙默认只认IP层ARP报文在iptables里基本是“透明”的。这两点叠加ARP欺骗才能在局域网里屡试不爽。1.2 攻击者的三种常见套路攻击者通常在同一个广播域内动手手段大同小异但目标分三类理解它们有助于防御时对症下药。一是中间人攻击。攻击者伪造网关MAC发给受害者让受害者的流量全部送到攻击者机器上同时再伪造受害者IP发给网关让网关的回包也送到攻击者机器。攻击者只要打开IP转发就能坐在中间完整地观看流量顺便篡改数据——网页挂马、账号密码嗅探、DNS劫持都靠这个套路。二是断网型攻击。攻击者根本不想看内容只向受害者或全网乱发假的ARP应答让ARP缓存彻底混乱受害者的流量被导向不存在的MAC表现就是频繁丢包、找不到网关整个网段濒临瘫痪。这类攻击成本极低甚至一个App就能做到。三是针对特定服务器的欺骗。攻击者只伪造某台数据库或办公系统的IP把指向它的流量全部劫持到自己的机器上骗登录、骗敏感数据隐蔽性更强受害主机往往毫无察觉。不管哪种套路本质都是同一件事攻击者让别人的ARP缓存相信了错误的IP-MAC映射。所以Linux下的防御重点也集中在“别让错误映射写进缓存”和“及时察觉异常映射”这两件事上。2. 防御设计的整体思路这个战场在链路层2.1 为什么常规防火墙拦不住它很多第一次接触这个问题的人会先问iptables不是可以配INPUT、OUTPUT规则吗把非网关MAC的流量都DROP掉不行吗行但拦不住ARP。iptables工作在网络层它看到的是IPv4报文头ARP帧的以太网类型是0x0806没有IP头iptables默认根本不处理这类帧。要过滤ARP必须用arptables针对ARP协议层或者ebtables针对以太网桥接层这才是链路层的“防火墙”。这解释了为什么“在网关服务器上开防火墙”这种常规操作对ARP欺骗几乎无效。攻击者发的是二层广播或单播帧三层防火墙连看都看不到更别说拦截。想防住它就必须到二层去想办法。2.2 三管齐下的设防模型我在实际环境里最终采用的思路是“防来源、过滤过程、盯结果”三层配合而不是迷信某一个工具。防来源把关键的IP-MAC映射做成静态绑定让攻击者的假应答根本没有机会写进缓存。这是最底层、最硬的一招。过滤过程用arptables在ARP协议层做白名单对声称是网关的ARP报文进行合法性校验不合法的一律丢弃。这一招防的是那些不直接改缓存、而是靠大量伪造报文扰乱网络的攻击。盯结果用arpwatch加自写脚本监控ARP流量的变化一旦发现网关MAC变更或异常的大量ARP广播立刻告警。防不住的时候至少要第一时间知道。如果网络里有可管理的交换机还可以在上游开启DHCP Snooping和DAIDynamic ARP Inspection在交换机层面就把伪造ARP报文拦掉主机侧的配置作为纵深防御的补充。没有交换机权限的小环境Linux主机的这套加固就是主力。3. 实操配置Linux主机上的完整防御步骤下面我以一个具体网络为例子把完整步骤走一遍。假设场景是内网192.168.10.0/24本机IP是192.168.10.50网卡eth0网关是192.168.10.1网关真实MAC是00:11:22:33:44:55。所有命令都需要root权限系统为Debian系Ubuntu同样适用RHEL系把安装命令换成yum/dnf即可。3.1 获取“标准答案”先记录正确的IP-MAC对照表防御的前提是知道什么是“对的”。在配置任何绑定之前先拿到一份可信的IP-MAC映射表。我推荐在攻击尚未发生时、或者确认网络正常的早期做这件事把它当作主机初始化的一部分。# 查看当前ARP缓存 ip neigh show dev eth0 # 主动向网关发ARP探测确认它的真实MAC arping -I eth0 -c 4 192.168.10.1看到返回的MAC后把它记录到/etc/ethers里格式是“MAC地址 IP地址”00:11:22:33:44:55 192.168.10.1如果局域网里还有需要重点保护的服务器比如数据库、业务网关也一并记录。这一步花不了两分钟但等出问题了你就会知道它有多值钱——没有这份记录攻击发生时你连“什么叫异常”都不知道只能对着抓包结果发呆。3.2 静态绑定把网关IP钉死在正确的MAC上拿到了标准答案最直接的做法就是用ip neigh把网关绑定为永久表项ip neigh replace 192.168.10.1 lladdr 00:11:22:33:44:55 dev eth0 nud permanentnud permanent表示这条表项永远有效、不会过期也不会被任何新的ARP应答更新。这个操作的原理很简单既然攻击的核心是诱导主机更新ARP缓存那我就把这个缓存的口子直接焊死。绑定后用ip neigh show dev eth0可以看到状态为PERMANENT的条目。如果想做成开机自动执行我建议写一个小的systemd服务而不是把命令塞进rc.local。新建/etc/systemd/system/gateway-arp-binding.service[Unit] DescriptionBind gateway MAC permanently Afternetwork-online.target Wantsnetwork-online.target [Service] Typeoneshot ExecStart/sbin/ip neigh replace 192.168.10.1 lladdr 00:11:22:33:44:55 dev eth0 nud permanent RemainAfterExityes [Install] WantedBymulti-user.target然后systemctl enable --now gateway-arp-binding即可。这里有个必须提醒的坑如果网关侧做了主备切换或链路聚合的MAC漂移永久绑定会让本机找不到新MAC而直接断网。所以静态绑定的对象一定要是“MAC长期稳定”的网关或服务器不能盲目绑所有主机尤其是别碰移动设备。3.3 arptables在ARP协议层做白名单过滤静态绑定保护的是本机缓存但局域网里其他主机可能还在被欺骗而且攻击者用大量伪造ARP报文做干扰时本机也会收到一堆错误的二层流量。这时候需要arptables在协议层做白名单。安装并启用apt install arptables下面的规则对input方向的ARP报文做校验凡是声称“我是192.168.10.1网关”的ARP请求或应答源MAC必须是真正的网关MAC否则直接丢弃其余ARP报文正常放行。# 1. 先确认当前规则为空 arptables -L -v # 2. 设置INPUT默认策略为DROP arptables -P INPUT DROP # 3. 放行网关发出的ARP请求opcode1包含免费ARP arptables -A INPUT -i eth0 --opcode 1 --source-ip 192.168.10.1 --source-mac 00:11:22:33:44:55 -j ACCEPT # 4. 放行网关产生的ARP应答opcode2 arptables -A INPUT -i eth0 --opcode 2 --source-ip 192.168.10.1 --source-mac 00:11:22:33:44:55 -j ACCEPT # 5. 放行其他所有ARP报文 arptables -A INPUT -i eth0 -j ACCEPT很多人会疑惑第5步不是把其他所有ARP都放行了吗那DROP还有什么意义关键在于规则是顺序匹配的。一个伪造的ARP应答它的IP是192.168.10.1但MAC不是00:11:22:33:44:55它过不了第4步而第5步要求的是“其他所有”它同样不属于“其他”——因为它也声称是网关只是身份不合法。匹配完前5条规则后它落到INPUT的默认策略上被DROP。换句话说第5步确保的是“和网关无关的正常ARP不受影响”默认DROP专门兜底“冒充网关的非法帧”。如果还要保护局域网里其他关键服务器按同样的模式追加成对规则即可注意把IP和MAC替换成目标服务器的正确值。规则配置完成后查看arptables -L -v规则需要持久化。Debian系可以安装arptables-persistent也可以手动保存arptables-save /etc/arptables.rules再写一个对应的restore服务或者把restore动作放到/etc/network/if-pre-up.d/下让网络启动时自动恢复。RHEL系没有现成的helper我建议直接写systemd unit跟上面网关绑定的写法一致。3.4 sysctl参数加固让协议栈更“冷静”静态绑定管的是指定表项arptables管的是网关IP但攻击者还可以用大量假冒本机IP或广播IP的请求骚扰整个网段。Linux内核本身就提供了几个抗ARP异常的参数虽然单独用效果有限配合起来很香。编辑/etc/sysctl.d/99-arp-hardening.confnet.ipv4.conf.all.arp_ignore 1 net.ipv4.conf.all.arp_announce 2 net.ipv4.conf.all.arp_filter 1 net.ipv4.conf.default.arp_ignore 1 net.ipv4.conf.default.arp_announce 2 net.ipv4.conf.default.arp_filter 1 net.ipv4.conf.all.drop_gratuitous_arp 1生效sysctl -p /etc/sysctl.d/99-arp-hardening.conf简单说这几个参数的作用。arp_ignore1要求本机只对“到达本网卡的、目标IP是本网卡地址”的ARP请求进行应答避免被伪装的请求牵着鼻子走arp_announce2要求发起ARP请求时使用出接口自身的最优IP地址减少多网卡场景下“报错门牌号”的概率arp_filter1则规定只有当源IP能通过该接口正常路由时才应答防止跨接口的ARP串扰。这三个参数主要解决主机本身的ARP行为异常对多网卡服务器尤其重要。drop_gratuitous_arp1则比较猛它让内核忽略所有“主动宣告”的ARP报文。前面说过免费ARPgratuitous ARP是攻击者最常用来投毒的手段这个参数等于一棍子把这类投毒全挡住。但要注意如果网络里用了keepalived这类靠免费ARP做虚拟IP漂移的方案打开这个参数会把漂移打断所以只建议在业务确实不需要免费ARP的普通服务器上开启。3.5 arpwatch部署一双盯着二层的眼睛硬防御做了还得有监控。arpwatch是一个老牌工具专门监听网卡上的ARP流量学习并记录IP-MAC对应关系发现变化或异常就报警。apt install arpwatch # 前台调试模式跑起来看效果 arpwatch -i eth0 -d确认正常后转后台运行。arpwatch会把学到的映射关系存到/var/lib/arpwatch/arp.dat报警默认发到root邮箱同时写syslog。如果服务器没配邮件就盯日志tail -f /var/log/syslog | grep -i arpwatch看到这类日志就意味着有人或某个程序在宣告新的MACarpwatch: changed ethernet address 192.168.10.1 00:11:22:33:44:55 (aa:bb:cc:dd:ee:ff)我个人的使用心得是arpwatch不适合当实时护栏它更像事后情报源。因为默认报警会随攻击流量数量爆炸几分钟内邮箱就被刷满而且发现异常时攻击可能已经开始。所以我的用法是“arpwatch留痕脚本告警”脚本见下一节。3.6 应急自动恢复脚本快速把缓存掰回来有些环境不允许长期静态绑定比如动态分配IP、主机经常迁移这时候可以写一个轻量脚本周期性检查网关ARP缓存发现异常立刻修正。我把这类脚本定位为“应急止血”不是长期方案。#!/bin/bash # /usr/local/sbin/arp-guard.sh GW_IP192.168.10.1 GW_MAC00:11:22:33:44:55 DEVeth0 LOG/var/log/arp-guard.log while true; do CUR_MAC$(ip neigh show $GW_IP dev $DEV | awk {print $5} | head -n1) if [ -z $CUR_MAC ]; then # 表项被清空重新绑定 ip neigh replace $GW_IP lladdr $GW_MAC dev $DEV nud permanent elif [ $CUR_MAC ! $GW_MAC ]; then # 缓存里出现了陌生MAC说明很可能被投毒立刻纠正并记录 echo $(date %F %T) WARNING: gateway MAC changed to $CUR_MAC, restore to $GW_MAC $LOG ip neigh replace $GW_IP lladdr $GW_MAC dev $DEV nud permanent fi sleep 5 done用systemd或nohup把它挂起来即可。原理很直白攻击者要得手必须先改变缓存里的MAC脚本一旦看到缓存里的MAC不是标准答案就把它掰回来。这算“反应式防御”速度比人类手工处理快得多。当然它有个先天局限——只能纠正本机缓存改不了局域网里其他主机的缓存所以能不能根治还得看攻击规模和上游设备的配合。4. 常见问题与排查实录防御配置本身不复杂复杂的是部署之后的各种副作用。下面这几个问题我基本都现场遇到过写出来帮大家少走弯路。4.1 网关绑定了外网还是断这是最让我头疼过的一个坑明明本机已经nud permanent绑定网关而且ip neigh看表项也正常但外网就是不通。后来才发现问题根本不在本机而是网关侧也中了招——攻击者给网关发送假的ARP应答让网关以为本机IP对应的MAC是攻击者的机器。于是网关把回包全发给攻击者攻击者再决定丢还是转发。这说明一个关键问题ARP欺骗是双向的。防守方只在受害主机上绑定只能保护自己攻击者同时污染网关缓存时你还是会被断。解决办法有两个一是在能登录的网关设备上也做静态绑定或开DAI二是走交换机的端口安全把可信主机的MAC绑定在端口上让攻击者的机器连入时直接被拒。主机上的防御从来不是孤岛。4.2 静态绑定和动态环境打架永久绑定最大的问题就是“太硬”。有一次我帮同事的笔记本也配了网关永久绑定结果他带着笔记本回家换了Wi-Fi和网关之后那台笔记本就再也上不了网了——因为缓存里还钉着公司网关的MAC。所以静态绑定只建议用在固定不动的服务器上笔记本、手机这类移动设备一律不要碰。如果确实需要给移动设备做保护优先靠交换机的DHCP Snooping和DAI而不是主机绑定。4.3 怎么把藏在暗处的攻击者揪出来防御做到位后下一个自然需求是定位攻击者。最实用的工具是tcpdump直接看二层头tcpdump -ne -i eth0 arp输出里会连续出现某个固定的MAC反复宣告“192.168.10.1 is-at xx:xx:xx:xx:xx:xx”这个MAC就是攻击机的网卡地址。拿到MAC之后登录交换机查MAC地址表定位到具体端口顺着网线就能找到物理机器。如果攻击MAC做了随机化那就配合arptables的规则计数统计DROP规则被命中的次数再看来源MAC的规律多看一会儿总能找到破绽。4.4 规则重启后全部消失arptables写好的规则重启就没了这是最常见的“假死”现场。检查两件事第一有没有把规则用arptables-save /etc/arptables.rules持久化第二有没有配置开机恢复。我见过很多人在线配置得很漂亮忘了持久化一重启全部失效然后误以为“防御没用”。另外注意如果网卡被ip link set down再up部分系统会清空ARP缓存绑定条目也可能不见所以我把网关绑定做成了独立的systemd服务跟网卡状态解耦能减少这类问题。还有一个容易踩的配置坑arptables规则里出现了一台内网服务器的MAC恰巧这台服务器做过高可用漂移MAC换了结果所有声称该IP的ARP都被当非法帧丢掉相关业务全部异常。排查方法是用tcpdump -ne -i eth0 arp对比看到的真实流量再看arptables计数两者一对照就能定位是规则误伤还是真有攻击。我把这些问题整理成了一张速查表方便运维时快速对照现象可能原因处理方向静态绑定后仍断网网关侧缓存被污染回包被劫持网关也做绑定/DAI或交换机端口绑定重启后绑定消失未持久化或网卡重置清空缓存做systemd unit绑定与网卡状态解耦arptables规则命中过多真有攻击或规则误伤正常主机tcpdump抓包对比检查是否有MAC漂移移动设备绑定后无法上网环境变更缓存锁死旧网关移动设备不要用永久绑定邮件报警刷屏arpwatch过度敏感改日志留痕脚本按条件告警5. 最后再分享几个现场才总结得出的经验第一个体会是“永远提前留底”。我一开始是出了事才去抓包、才去对MAC结果发现平时根本没记录过正确映射抓到假包都不知道拿什么对比。后来我把所有要保护的服务器IP-MAC做成了一张表存到wiki和/etc/ethers攻击发生时对照时间几乎为零。这个习惯比任何工具都重要。第二个体会是“别迷信单一手段”。永久绑定确实硬但它扛不住网关侧被污染arptables确实能过滤但攻击者换个IP接着发也能造成干扰arpwatch能告警可它拦不住。真正让我把问题控制住的是三层配合绑定保底、过滤拦路、监控留痕有条件再把交换机DAI开上。少任何一层防御都是有洞的。第三个体会是“防御要做减法”。刚接手时我恨不得把能开的参数全开上结果drop_gratuitous_arp把内网的虚拟IP漂移打断arp_announce又让多网卡业务出现路由异常。后来我养成了一个习惯每次只改一个参数观察两三天再决定要不要保留。网络世界最怕拍脑袋上一堆配置回头自己都说不清是哪条规则把业务搞挂了。如果局域网里也被ARP欺骗折磨得不轻照这个思路先把网关和关键服务器绑起来配上arptables的网关白名单再挂一个arpwatch留痕。三步走完能挡住绝大部分攻击。剩下的还是要靠平时积累留底、分层、做减法这句话在网络上哪里都适用。