谁把网关换了?局域网里的 DHCP、ARP 与 DNS 三角骗局

2026/08/26 网络安全 运维 共 4920 字,约 15 分钟

💡 办公室里最会演戏的,不是同事,是“看起来一切正常”的网络。网页偶尔打不开、刚接入的电脑拿不到地址、同一个网关一会儿一个 MAC,这些小毛病凑在一起,就可能是局域网的信任边界出了问题。

本文把一份攻击主题的学习材料改写成防守视角:不复述攻击命令,不使用真实公司信息,也不提供钓鱼或凭据拦截步骤。你将得到一套可以在自有网络、授权环境或隔离实验室里执行的排查流程:先观察,后取证,再恢复,最后让交换机替你挡住重复事故。

先认识三个“前台接待”

把局域网想成一栋办公楼:

角色它负责的事出问题时的典型症状
DHCP给设备分配 IP、网关和 DNS新设备拿不到地址,或者拿到一套奇怪的网络参数
ARP在同一网段里把 IPv4 地址对应到 MAC 地址网关 MAC 反复变化、连接忽快忽慢
DNS把域名翻译成 IP只有部分域名打不开,或解析结果与其他网络不一致

正常情况下,这三位各司其职。异常时,设备可能收到一个不该出现的 DHCP 响应,随后把网关的 ARP 记录改成另一个 MAC,最后再被错误的 DNS 引到不该去的地址。用户看到的只是“网断了”,管理员看到的却是一条完整的证据链。

先建立基线,再谈异常

没有基线的告警,和没有尺子的裁缝差不多:两边都很忙,结果都靠感觉。建议为每个 VLAN 记录以下四项:

  • 合法 DHCP Server 的 IP 和 MAC。
  • 默认网关的 IP 和 MAC。
  • 合法 DNS Server 的 IP。
  • 正常工作日的地址池范围和租约时长。

示例使用 192.0.2.0/24198.51.100.0/24 等文档保留网段,不能直接拿去替换真实生产地址。

Windows:五分钟拿到现场证据

先不要清缓存,也不要马上重启。保存现场比“让它暂时恢复”更重要。

1. 记录完整网络参数

New-Item -ItemType Directory -Force .\network-evidence | Out-Null
ipconfig /all | Tee-Object .\network-evidence\ipconfig.txt
route print | Tee-Object .\network-evidence\routes.txt
arp -a | Tee-Object .\network-evidence\arp.txt
Get-DnsClientServerAddress -AddressFamily IPv4 |
    Format-Table -AutoSize |
    Out-File .\network-evidence\dns-servers.txt -Encoding utf8

重点看三件事:

  1. DHCP Server 是否是已登记的地址。
  2. Default Gateway 是否落在预期网段。
  3. DNS Servers 是否出现未知地址,尤其是与网关不在同一管理范围的地址。

2. 检查网关的 ARP 记录

$gateway = (Get-NetRoute -DestinationPrefix '0.0.0.0/0' |
    Sort-Object RouteMetric |
    Select-Object -First 1 -ExpandProperty NextHop)

"默认网关: $gateway"
arp -a $gateway

把输出里的 MAC 与你的基线比较。单次不一致不等于攻击:网关可能做了主备切换、虚拟化迁移或网络维护。关键是变化频率、发生时间和是否伴随 DHCP/DNS 异常

3. 只读观察 DHCP 和 ARP

如果现场允许抓包,Wireshark 只做观察即可,过滤器可以从下面两个开始:

bootp || arp

你要找的是“同一网段出现多个 DHCP Offer”,以及“同一个网关 IP 在短时间内对应多个 MAC”。不要在生产网络里为了验证猜想主动发送伪造报文。

Linux:同一套证据换一种口音

mkdir -p ./network-evidence
ip addr | tee ./network-evidence/ip-addr.txt
ip route | tee ./network-evidence/ip-route.txt
ip neigh show | tee ./network-evidence/ip-neigh.txt
resolvectl status | tee ./network-evidence/resolved.txt

如果发行版没有 resolvectl,改看:

cat /etc/resolv.conf | tee ./network-evidence/resolv-conf.txt

默认路由可以单独确认:

ip route get 192.0.2.1

输出中的 via 是下一跳,dev 是出口网卡。把它和 ip neigh 中同一地址的 MAC 一起记下来,就有了“路由 + 二层邻居”的最小证据集。

一个安全的基线检查脚本

下面的脚本只读取本机信息,并把结果保存成 JSON,适合每天定时运行。它不会扫描别人,也不会修改网络配置。

保存为 collect_network_baseline.py

from __future__ import annotations

import json
import platform
import socket
import subprocess
from datetime import datetime, timezone
from pathlib import Path


def run(command: list[str]) -> str:
    result = subprocess.run(
        command,
        check=False,
        capture_output=True,
        text=True,
        encoding="utf-8",
        errors="replace",
    )
    return result.stdout.strip() or result.stderr.strip()


def collect() -> dict[str, object]:
    system = platform.system()
    data: dict[str, object] = {
        "captured_at": datetime.now(timezone.utc).isoformat(timespec="seconds"),
        "hostname": socket.gethostname(),
        "platform": platform.platform(),
    }
    if system == "Windows":
        data["ipconfig"] = run(["ipconfig", "/all"])
        data["routes"] = run(["route", "print"])
        data["arp"] = run(["arp", "-a"])
        data["dns"] = run(["powershell", "-NoProfile", "-Command",
                            "Get-DnsClientServerAddress -AddressFamily IPv4"])
    elif system == "Linux":
        data["addresses"] = run(["ip", "addr"])
        data["routes"] = run(["ip", "route"])
        data["neighbors"] = run(["ip", "neigh"])
        data["dns"] = run(["cat", "/etc/resolv.conf"])
    else:
        raise SystemExit(f"暂不支持 {system},请手工记录网络参数")
    return data


output = Path("network-evidence")
output.mkdir(exist_ok=True)
target = output / "baseline.json"
target.write_text(json.dumps(collect(), ensure_ascii=False, indent=2), encoding="utf-8")
print(f"已写入 {target.resolve()}")

运行:

python collect_network_baseline.py

将生成的 baseline.json 纳入受控的运维存储,不要直接提交到公开仓库。里面可能包含主机名、内网地址和 DNS 信息。

发现异常后,按这个顺序恢复

第一步:隔离受影响端口

如果只有一台设备异常,先把它移到隔离 VLAN 或拔掉网线;如果多个端口同时异常,优先在交换机上核对 DHCP Snooping、端口状态和最近的变更记录。隔离的目标是停止继续扩散,不是惩罚某台电脑。

第二步:重新获取合法配置

确认网络侧已经排除异常响应后,再在受影响设备上执行恢复。Windows:

ipconfig /release
ipconfig /renew
ipconfig /flushdns

Linux(NetworkManager):

nmcli device status
nmcli connection show --active
sudo nmcli connection down "有线连接 1"
sudo nmcli connection up "有线连接 1"
resolvectl flush-caches 2>/dev/null || true

有线连接 1 换成 nmcli connection show --active 里实际的连接名。不要在远程 SSH 会话中盲目重启网络服务,否则可能把自己锁在门外。

第三步:重新采集并对比

恢复后再次保存 ipconfig、路由、ARP 和 DNS。以下情况说明还不能结案:

  • DHCP Server 仍然变化。
  • 网关 MAC 在几分钟内反复切换。
  • DNS 解析与可信网络持续不一致。
  • 只有 HTTPS 站点“偶尔”出现证书错误。

交换机侧的四道门

主机自救只能解决一台设备,真正的防线在接入层。不同厂商命名略有差异,但目标是一致的:

  1. DHCP Snooping:只信任上联到合法 DHCP Server 的端口,接入口收到 DHCP Server 报文就丢弃,并记录绑定表。
  2. Dynamic ARP Inspection:用 DHCP Snooping 的绑定关系校验 ARP,避免设备冒充网关。
  3. IP Source Guard:限制端口只能使用绑定表里的 IP/MAC 组合,降低地址伪装空间。
  4. 端口隔离与 802.1X:让终端先通过身份认证,再决定能访问哪个 VLAN,减少“插上网线就默认信任”的情况。

启用前要先做两件事:确认上联端口列表、给静态地址和语音 VLAN 建立明确例外。先在一台测试交换机或低风险 VLAN 观察日志,再逐步扩大范围。配置名可以查对应厂商文档,不要直接把网上别人的整段配置粘进生产设备。

15 分钟排查清单

[ ] 记录时间、受影响 VLAN、设备名和用户现象
[ ] 保存 DHCP、默认网关、DNS、ARP/邻居表
[ ] 与最近一次正常基线比较,而不是只看当前值
[ ] 确认是否存在多个 DHCP Server 或网关 MAC 变化
[ ] 在交换机侧核对端口、绑定表和变更记录
[ ] 隔离异常端口,保留日志和抓包文件
[ ] 网络侧修复后,再释放/续租地址并清理 DNS 缓存
[ ] 复测内网、外网、关键域名和证书链
[ ] 更新基线,并记录长期加固项

三个常见误判

“能上网,就说明没问题”

错误的 DNS 或网关不一定让网络立刻断掉,可能只是把部分流量带到错误路径。可用可信的外部网络交叉解析关键域名,并检查证书是否匹配预期服务。

“ARP 表里有两个 MAC,就是攻击”

高可用网关、负载均衡和虚拟机迁移都会改变 MAC。判断依据应该是基线、时间线、交换机日志和 DHCP 证据的组合。

“清缓存就结束了”

清缓存只改变一台机器的暂态状态,不能阻止异常设备继续发包。没有找到端口和网络侧原因,问题还会回来。

总结:让网络有记忆,也有刹车

局域网不是天然可信区。把 DHCP、ARP、DNS 当成一条证据链来观察,你就能把“网怎么又抽风了”变成可验证的问题:

建立基线 → 只读取证 → 隔离影响 → 合法恢复 → 交换机加固 → 持续复盘

最后提醒一次:本文命令只适用于你拥有或明确获准测试的网络。公开仓库里不要放真实域名、内网地址、设备序列号、抓包文件或任何凭据;排查记录也应先脱敏,再进入工单和知识库。

参考资料


作者:牛马便利店一号店员

文档信息

Search

    Table of Contents