PowerShell 中可以使用 Get-NetNeighbor 命令来实现类似于 Windows 中 arp -a 的功能,用于显示本地系统的 ARP 缓存表

Get-NetNeighbor 完整解构

基础定位

Get-NetNeighbor 是 Windows PowerShell 内置 NetTCPIP 模块命令,作用:
 
读取系统内核 邻居缓存(Neighbor Cache),同时包含两类条目:
  1. IPv4 ARP 条目(IPv4 地址 ↔ MAC)
  2. IPv6 NDP 邻居条目(IPv6 地址 ↔ MAC)
等价传统命令对照:
  • arp -a ≈ Get-NetNeighbor -AddressFamily IPv4
  • netsh interface ipv6 show neighbors ≈ Get-NetNeighbor -AddressFamily IPv6
重要区分:
 
arp.exe 老旧工具仅兼容 IPv4;Get-NetNeighbor 原生双栈统一接口,同时管理 ARP 缓存与 NDP 邻居缓存。

一、底层执行原理

1. 整体调用栈模型

plaintext
PowerShell Console
    ↓
NetTCPIP.dll (NetTCPIP CIM/WMI提供程序)
    ↓
iphlpapi.dll (IP Helper API)
    ↓
内核系统调用
    ↓
tcpip.sys(内核协议栈,维护ARP缓存 + IPv6邻居缓存)

2. 核心 API

Get-NetNeighbor 底层最终调用:
 
GetIpNetTable2()
 
来自 iphlpapi.dll,是现代 Windows 提供的统一邻居表查询 API,同时输出 IPv4 ARP、IPv6 NDP 邻居记录。
历史旧 API:GetIpNetTable() 仅支持 IPv4(arp.exe 底层使用)。

工作流程原理

  1. PowerShell 加载 NetTCPIP 模块;
  2. 模块发起 CIM 请求,转发至 iphlpapi.dll::GetIpNetTable2();
  3. iphlpapi.dll 通过 IOCTL 系统调用下发请求至 tcpip.sys;
  4. tcpip.sys 遍历内核内存中的两张表:
    • IPv4:ARP Cache Table
    • IPv6:Neighbor Cache Table(NDP)
  5. 内核把条目(IP 地址、MAC、接口索引、状态、寿命)向上返回;
  6. 数据封装为 NetNeighbor 对象(PSObject)输出到 PowerShell 管道。

3. 邻居状态字段来源(由 tcpip.sys 内核标记)

常见 State 值:
  • Connected:有效稳定条目
  • Incomplete:正在解析(ARP Request / NDP NS 已发出,尚未收到应答)
  • Unreachable:邻居探测失败
  • Permanent:静态固化条目(手动添加)
所有状态不是 PowerShell 生成,完全由内核 tcpip.sys 维护。

二、依赖文件清单(分层)

1)用户态程序 / 模块

  1. NetTCPIP.dll
     
    路径:C:\Windows\System32\WindowsPowerShell\v1.0\Modules\NetTCPIP\
     
    承载所有 Get/Set/New/Remove-NetNeighbor、IP 地址、路由相关 Cmdlet。
  2. iphlpapi.dll
     
    核心依赖,提供 GetIpNetTable2 API。
  3. ws2_32.dll Winsock 支撑
  4. cimwin32.dll CIM 基础设施(WMI 现代替代)
  5. powershell.exe/pwsh.exe PowerShell 运行时

2)内核层依赖

  1. tcpip.sys:双栈协议栈,保存 ARP 缓存、IPv6 邻居缓存
  2. ndis.sys:NDIS 网络驱动框架
  3. 网卡厂商 NDIS 小端口驱动

3)无独立系统服务

邻居缓存完全在内核tcpip.sys自主维护;
 
不需要额外后台服务;ARP、NDP 报文收发全部内核完成。
对比:ipconfig /renew 需要 Dhcp 服务;Get-NetNeighbor不需要任何额外服务。

4)持久化边界说明

邻居缓存默认保存在内核内存,重启清空;
  • 动态 ARP/NDP 条目:内存临时,老化自动删除
  • 静态永久条目 (Permanent):写入内核配置,重启失效;
     
    静态邻居条目不会自动写入注册表持久保存,开机需要重新脚本加载。
注册表不存储动态邻居缓存!注册表只存放网卡静态 TCP/IP 参数,和邻居表无关。

三、配套链(上下游组件生态)

1. 同模块配套 Cmdlet(NetTCPIP 套件)

plaintext
Get-NetNeighbor        # 查询邻居表
New-NetNeighbor        # 添加静态ARP/NDP条目
Remove-NetNeighbor     # 删除邻居缓存
Clear-NetNeighborCache # 清空整张邻居表
Get-NetIPAddress
Get-NetRoute
Get-NetAdapter

2. 传统命令行配套(兼容层)

  • arp.exe:仅 IPv4,底层调用老旧 GetIpNetTable ()
  • netsh interface ipv4 show neighbors
  • netsh interface ipv6 show neighbors

3. 协议底层配套

  • IPv4 ARP(RFC826):填充 IPv4 邻居条目
  • IPv6 NDP(RFC4861 NS/NA 报文):填充 IPv6 邻居条目
  • ICMPv6:支撑 IPv6 NDP 邻居探测

4. 网络侧配套链路

交换机 ARP Snooping、DAI、NDP Snooping、RA Guard;
 
排障闭环:
 
Get-NetNeighbor 查看本地缓存 → 抓包验证 ARP/NDP 报文 → 核查交换机二层安全策略

5. 监控 / 安全配套

可定时脚本采集 Get-NetNeighbor 输出,用于:
  • ARP 欺骗检测
  • 非法终端接入审计
  • 邻居可达性异常监控

四、完整逻辑全链路

链路 1:基础查询 Get-NetNeighbor

plaintext
pwsh.exe/powershell.exe
    ↓
加载 NetTCPIP 模块
    ↓
NetTCPIP.dll 发起调用 iphlpapi.dll!GetIpNetTable2()
    ↓
iphlpapi.dll 发起系统调用,下发控制指令至 tcpip.sys
    ↓
tcpip.sys 读取内核内存:
    IPv4 ARP Cache + IPv6 Neighbor Cache
    ↓
原始条目数据逐层向上返回
    ↓
NetTCPIP.dll 将原始C结构封装为 PowerShell NetNeighbor 对象
    ↓
输出对象流,控制台展示表格/可供管道继续处理

链路 2:过滤示例 Get-NetNeighbor -AddressFamily IPv6

上层增加筛选逻辑:
 
内核一次性返回全部条目 → NetTCPIP 模块在用户态过滤地址簇,仅输出 IPv6 NDP 记录
⚠️ 注意:过滤是在 PowerShell 用户层完成,无法在内核侧只索取单栈数据。

链路 3:添加静态条目 New-NetNeighbor

plaintext
New-NetNeighbor → NetTCPIP.dll → iphlpapi.dll → SetIpNetEntry2()
    ↓
下发命令至tcpip.sys
    ↓
在内核邻居表写入 Permanent 静态映射

链路 4:清除缓存 Clear-NetNeighborCache

调用 FlushIpNetTable2(),通知 tcpip.sys 清空指定接口 / 全系统动态邻居条目。

五、关键认知误区澄清

  1. ❌ Get-NetNeighbor 直接抓取网卡报文解析 ARP/NDP
     
    ✅ 错误。不抓包!只是读取 tcpip.sys已经学习完成的内核缓存。看不到历史上已经老化删除的记录。
  2. ❌ arp -a 和 Get-NetNeighbor IPv4 数据源完全一致
     
    ✅ 数据源同源(tcpip.sys ARP 缓存),但调用 API 不同:
     
    arp.exe 使用老旧 GetIpNetTable;Get-NetNeighbor 使用现代 GetIpNetTable2,信息字段更丰富。
  3. ❌ 静态邻居条目永久保存在注册表
     
    ✅ 错误。仅存内核内存,重启丢失;如需持久,开机脚本执行 New-NetNeighbor。
  4. ❌ 可以通过 Get-NetNeighbor 触发 ARP/NDP 探测
     
    ✅ 错误!查询动作不会主动发送 ARP Request / NDP NS。
     
    想要触发解析:必须主动 ping 目标 IP,由 tcpip.sys 主动发起邻居请求。
  5. ❌ IPv6 条目叫 ARP 缓存
     
    ✅ 规范名称:邻居缓存 Neighbor Cache,由 NDP 协议维护,不属于 ARP。

六、横向对比速记

工具 支持协议 底层 API 归属
arp.exe 仅 IPv4 ARP GetIpNetTable 传统 EXE
Get-NetNeighbor IPv4 ARP + IPv6 NDP GetIpNetTable2 PowerShell NetTCPIP 模块

1、详细介绍内核协议栈(Windows NT 内核协议栈 tcpip.sys)

基础定义

Windows 内核网络协议栈主体文件:tcpip.sys,运行在内核模式(Ring0),是操作系统网络最核心底层组件,承接上层应用、Winsock,向下对接 NDIS 网卡驱动,同时原生支持 IPv4 + IPv6 双栈。

分层架构(自上而下)

  1. Winsock 接口层(用户态)
     
    ws2_32.dll,为应用程序提供 socket API;应用无法直接操作内核栈,必须通过这套接口。
  2. 内核 Socket 层(AFD.SYS)
     
    内核套接字驱动,转发用户态 socket 请求至 tcpip.sys。
  3. tcpip.sys 协议处理层【核心】
     
    承载完整协议处理:
  • 网络层:IPv4、IPv6、ICMPv4、ICMPv6
  • 地址解析:ARP 缓存管理、NDP 邻居缓存管理
  • 传输层:TCP、UDP
  • 路由表维护、分片重组、QoS、数据包过滤
  1. NDIS 接口层(ndis.sys)
     
    统一网络驱动框架,隔离协议栈与各类网卡驱动;提供数据包收发、网卡枚举、二层帧封装。
  2. 网卡小端口驱动
     
    厂商硬件驱动,负责和物理网卡交互,收发以太网帧。

tcpip.sys 关键内置数据表(和你前面学习内容强关联)

  1. IPv4 ARP Cache(ARP 缓存表)
  2. IPv6 Neighbor Cache(NDP 邻居缓存)
  3. IP 路由表
  4. TCP 连接控制块 TCB、UDP 端口表

核心特性

  • ARP/NDP 报文在内核自主生成、收发,不需要用户态服务;
  • Get-NetNeighbor、arp -a 本质都是读取该驱动内存中的缓存;
  • 所有网卡 IP、网关、MTU、地址生命周期全部由协议栈维护;
  • 隔离边界:用户态程序不能直接修改内核内存缓存,只能通过 Win32 API 间接读写。

配套依赖

内核:afd.sys、ndis.sys、netbt.sys;
 
用户态访问入口:iphlpapi.dll(IP Helper API)。

2、如何使用 Get-NetNeighbor 命令

前置要求:Windows 8 / Server2012 及以上原生内置,归属 NetTCPIP 模块,打开 PowerShell 执行。

基础语法

powershell
 
 
 
# 查看全部邻居缓存(IPv4 ARP + IPv6 NDP)
Get-NetNeighbor

# 仅查看IPv4 ARP缓存(等价 arp -a)
Get-NetNeighbor -AddressFamily IPv4

# 仅查看IPv6 NDP邻居缓存
Get-NetNeighbor -AddressFamily IPv6
 

高频实用示例

powershell
 
 
 
# 指定网卡索引查看(先 Get-NetAdapter 确认接口索引号)
Get-NetNeighbor -InterfaceIndex 3

# 筛选状态为 Incomplete(解析失败/未收到应答)的条目
Get-NetNeighbor | Where-Object {$_.State -eq "Incomplete"}

# 格式化输出IP、MAC、状态
Get-NetNeighbor -AddressFamily IPv4 | Select IPAddress,LinkLayerAddress,State

# 添加静态ARP绑定(永久条目,重启失效)
New-NetNeighbor -InterfaceIndex 3 -IPAddress "192.168.1.1" -LinkLayerAddress "AA-BB-CC-DD-EE-FF" -State Permanent

# 删除一条邻居缓存
Remove-NetNeighbor -IPAddress 192.168.1.1 -InterfaceIndex 3

# 清空所有动态邻居缓存
Clear-NetNeighborCache
 

字段释义(State 状态)

  • Connected:正常可用动态条目
  • Incomplete:正在解析,已发 ARP/NS,无回复
  • Unreachable:邻居探测判定不可达
  • Permanent:静态永久绑定条目

重要注意点

  1. 查询不会主动触发 ARP/NDP 探测;想要触发解析,需要 ping 对应 IP;
  2. 静态条目仅保存在内核内存,系统重启丢失;
  3. 普通用户可查询;增删静态条目需要管理员权限。

3、PowerShell 和 CMD 命令核心区别

1)底层架构本质区别

CMD

  • 宿主程序:cmd.exe,传统命令解释器
  • 处理对象:纯文本字符串
  • 内置命令有限,大量功能依赖独立 exe 程序(arp.exe、ipconfig.exe、route.exe)
  • 管道传递:文本流,工具之间只能通过字符串交互,需要复杂文本截取

PowerShell

  • 宿主:powershell.exe / pwsh.exe
  • 处理对象:.NET 对象(核心差异)
  • 拥有原生模块系统(NetTCPIP、ActiveDirectory 等),大量 Cmdlet 内置,不再依赖独立 exe
  • 管道传递完整对象,可以直接读取属性,不用文本切割

2)网络相关直观对比(贴合你学习链路)

表格
 
 
 
场景 CMD PowerShell
查看 ARP 缓存 arp -a(独立 exe,仅 IPv4) Get-NetNeighbor(原生双栈,输出对象)
查看网卡 IP ipconfig /all(文本输出) Get-NetIPAddress(结构化对象)
路由管理 route.exe Get-NetRoute / New-NetRoute
过滤数据 findstr 文本匹配 Where-Object 对象属性筛选

3)关键能力差异

  1. 数据交互
     
    CMD:所有输出是字符串,提取 MAC、IP 需要 for 循环、findstr 截取,极易出错;
     
    PowerShell:直接访问 $obj.IPAddress、$obj.LinkLayerAddress 属性。
  2. 扩展性
     
    CMD 扩展能力弱,依靠外部 exe;
     
    PowerShell 支持模块、函数、面向对象、远程管理 (WinRM)。
  3. 系统 API 调用方式
     
    CMD 调用独立 exe 程序(ipconfig.exe、arp.exe),exe 再调用 DLL;
     
    PowerShell Cmdlet 一般直接封装 API,减少中间 exe 层级。
  4. 兼容性
     
    CMD 兼容老旧 Windows 批处理脚本;
     
    PowerShell 向后兼容,可以调用所有传统 exe 命令。

4)一句话总结

CMD = 文本驱动的老式命令终端;
 
PowerShell = 基于.NET 对象、面向 Windows 系统管理的现代化脚本环境。

实例直观对比

CMD 查看 ARP 并筛选网关:只能字符串查找
cmd
 
 
 
arp -a | findstr 192.168.1.1
 
PowerShell 方式(直接按属性筛选,不受文本格式影响)
powershell
 
 
 
Get-NetNeighbor -AddressFamily IPv4 | Where-Object IPAddress -eq "192.168.1.1"

Get-NetNeighbor 故障排查标准操作流程

适用场景:IPv4 ARP 欺骗、IPv6 NDP 异常、邻居条目 Incomplete(解析未完成)
 
环境前提:Windows PowerShell(管理员模式最佳),掌握 Get-NetNeighbor、基础抓包、二层交换机知识

前置术语回顾

  1. Incomplete:主机发出 ARP Request / NDP NS 请求,未收到任何应答
  2. Neighbor Cache:内核tcpip.sys维护,同时承载 IPv4 ARP 表、IPv6 NDP 邻居表
  3. 关键命令速查
powershell
 
 
 
# 查看全部邻居表
Get-NetNeighbor
# 单独IPv4 ARP
Get-NetNeighbor -AddressFamily IPv4
# 单独IPv6 NDP
Get-NetNeighbor -AddressFamily IPv6
# 筛选异常条目
Get-NetNeighbor | Where-Object {$_.State -eq 'Incomplete'}
 

一、标准化排查总流程(通用链路)

Step1 采集基线信息,确认故障现象

  1. 打开 PowerShell,导出邻居缓存快照留存证据
powershell
 
 
 
Get-NetNeighbor | Export-Csv -Path C:\neighbor_before.csv -Encoding UTF8
 
  1. 定位异常接口:
powershell
 
 
 
# 查看网卡索引号
Get-NetAdapter
# 只观察故障网卡邻居表(替换接口索引)
Get-NetNeighbor -InterfaceIndex 3
 
  1. 确认故障分类
  • 现象 A:目标 IP 条目持续 Incomplete → 地址解析不通
  • 现象 B:同一 IP 频繁切换 MAC / 网关 MAC 异常 → ARP 欺骗 / NDP 欺骗
  • 现象 C:IPv6 邻居反复消失、可达性震荡 → NDP 邻居可达性故障
重要提醒:Get-NetNeighbor 仅读取内核缓存,不会主动触发解析
 
想要触发 ARP/NDP 请求:ping 目标IP

Step2 基础连通性分层定位(由上层到下层)

  1. Ping 目标 IP
powershell
 
 
 
ping 192.168.1.1
ping 2001::xxx
 
  1. 持续监控邻居状态(实时观察变化)
powershell
 
 
 
while($true){Get-NetNeighbor -InterfaceIndex 3;Start-Sleep 1}
 
  1. 判断边界
  • 若 ping 不通 + 条目 Incomplete:二层解析环节故障
  • 若 ping 通但邻居表异常:存在缓存异常、静态条目冲突

Step3 区分单栈故障:IPv4 ARP / IPv6 NDP

powershell
 
 
 
# 分离查看
Get-NetNeighbor -AddressFamily IPv4
Get-NetNeighbor -AddressFamily IPv6
 
  • 仅 IPv4 异常:聚焦 ARP、交换机 DAI、ARP Snooping
  • 仅 IPv6 异常:聚焦 NDP、RA Guard、组播转发、DAD 冲突

Step4 清理缓存复现故障(排除陈旧缓存干扰)

powershell
 
 
 
# 清空动态邻居缓存
Clear-NetNeighborCache
# 重新触发解析
ping 目标IP
# 再次观测状态
Get-NetNeighbor
 
⚠️ Permanent 静态条目不会被清除。

Step5 结合抓包确认报文收发(关键分界点)

使用 Wireshark 抓网卡流量:
  1. Incomplete 场景重点观察:
    • 是否发出 ARP Request / ICMPv6 NS
    • 是否收到对端 ARP Reply / NA
  2. 报文判定结论:
    表格
     
     
     
    抓包现象 根因方向
    请求报文发出,无应答 对端离线、交换机阻断广播 / 组播、VLAN 隔离、防火墙拦截
    请求未发出 本机协议栈 tcpip.sys 异常、路由判定目标不在同一链路
    收到应答,但内核不写入缓存 安全软件拦截、MAC 冲突、重复地址 DAD 冲突

Step6 网络设备侧协同核查

  1. IPv4 环境:交换机 MAC 地址表、ARP-Snooping、DAI 动态 ARP 检测
  2. IPv6 环境:NDP Snooping、RA Guard、MLD 组播转发策略
  3. 确认:同一广播域,路由器不转发 ARP/NDP 报文

Step7 临时验证手段

  1. 手动添加静态邻居条目测试连通性
powershell
 
 
 
# IPv4静态ARP
New-NetNeighbor -InterfaceIndex 3 -IPAddress "192.168.1.1" -LinkLayerAddress "xx-xx-xx-xx-xx-xx" -State Permanent
# IPv6静态NDP
New-NetNeighbor -InterfaceIndex 3 -IPAddress "2001::1" -LinkLayerAddress "xx-xx-xx-xx-xx-xx" -State Permanent
 
✅ 静态添加后通信恢复 → 证明地址解析流程故障;
 
❌ 静态添加依旧不通 → 问题不在 ARP/NDP,向上排查路由、防火墙。

Step8 故障闭环与证据留存

powershell
 
 
 
# 故障恢复后再次导出快照对比
Get-NetNeighbor | Export-Csv -Path C:\neighbor_after.csv -Encoding UTF8
 

二、场景专项排查链路

场景 1:邻居条目持续 Incomplete 专项排查

可能根因清单

  1. 目标设备关机、离线、防火墙禁止应答 ARP/NS
  2. 两端不在同一个 VLAN / 广播域
  3. 交换机关闭广播转发、端口隔离
  4. IPv6 场景:请求节点组播被交换机拦截(MLD 问题)
  5. 本机网卡驱动异常、tcpip.sys 协议栈损坏
  6. 目标存在 IP 冲突(IPv6 DAD 冲突尤为常见)

定向排查顺序

  1. ping 触发解析 → Get-NetNeighbor确认进入 Incomplete
  2. 抓包:确认本机是否发出请求报文
  3. 在同网段另一台设备测试能否解析目标 IP
    • 其他主机正常:本机网卡 / 协议栈问题
    • 所有主机都无法解析:二层网络、目标设备问题
  4. IPv6 额外检查:是否启用 IPv6、组播是否正常、DAD 地址冲突

场景 2:ARP 欺骗(IPv4)排查链路

现象特征:
 
网关 IP 对应的 MAC 地址频繁变更;多个 IP 映射到同一个陌生 MAC。

操作步骤

  1. 持续监控邻居表,记录异常 MAC
powershell
 
 
 
while($true){Get-NetNeighbor -AddressFamily IPv4 | Where IPAddress -eq "192.168.1.1";sleep 1}
 
  1. 区分两种情况
  • 异常 MAC 为本机:本机中毒发起 ARP 欺骗
  • 异常 MAC 为未知终端:内网主机恶意发送免费 ARP
  1. 临时处置:添加网关静态 ARP 绑定
powershell
 
 
 
New-NetNeighbor -InterfaceIndex X -IPAddress 网关IP -LinkLayerAddress 真实网关MAC -State Permanent
 
  1. 交换机溯源:通过异常 MAC 查看对应接入端口,定位攻击主机
  2. 长期防护:交换机开启 ARP Snooping + DAI

场景 3:IPv6 NDP 异常(NDP 欺骗、邻居震荡)

IPv6 无广播,依靠 NS/NA、RA 报文,攻击类型:RA 欺骗、NA 欺骗
 
现象:
 
默认网关随机变化、邻居条目频繁 Unreachable、无法获取 IPv6 地址

排查链路

  1. Get-NetNeighbor -AddressFamily IPv6 观察网关邻居条目
  2. 抓包重点查看 ICMPv6 RA、NA 报文
  3. 判定:是否存在非法设备发送伪造 RA/NA
  4. 临时防护:交换机开启 RA Guard、NDP Snooping
  5. 检查 DAD 重复地址检测告警(地址冲突会导致邻居不稳定)

三、常见坑与避坑清单

  1. ❌ 不要只依靠arp -a排查 IPv6,必须使用Get-NetNeighbor
  2. ❌ Incomplete ≠ 一定被攻击,优先确认目标设备是否在线
  3. ❌ 清理缓存后不重新 ping,不会产生新的邻居条目
  4. ❌ 静态邻居条目重启失效,不能作为永久解决方案
  5. ❌ ARP/NDP 为链路本地协议,跨三层设备无法解析
  6. ❌ 防火墙拦截 ICMPv6 会直接导致 NDP 整体失效

四、故障排查速查脚本(可直接复制使用)

powershell
 
 
 
#1.导出邻居缓存
Get-NetNeighbor | Export-Csv C:\neighbor_log.csv -Encoding UTF8
#2.筛选所有异常状态条目
Get-NetNeighbor | Where-Object {$_.State -in 'Incomplete','Unreachable'}
#3.持续监控
while($true)
{
    Clear-Host
    Get-NetNeighbor -InterfaceIndex 3
    Start-Sleep 1
}

整套 Windows NT 内核网络分层完整讲解

自上而下层级关系总览
 
用户态应用 → ws2_32.dll (Winsock) → afd.sys → tcpip.sys → ndis.sys → 网卡小端口驱动 → 硬件网卡

1、详细介绍内核协议栈(Windows NT 内核协议栈 tcpip.sys)

基础定位

tcpip.sys 运行于内核模式 Ring0,是 Windows TCP/IP 协议栈核心驱动,原生实现IPv4/IPv6 双栈,位于传输层、网络层处理核心。

核心职责

  1. 网络层处理
     
    IPv4、IPv6 报文收发、分片 / 重组;ICMPv4、ICMPv6;
     
    维护 ARP 缓存表(IPv4)、Neighbor 邻居缓存(IPv6 NDP);路由表计算与查找。
  2. 传输层处理
     
    TCP(连接管理、重传、拥塞控制、TCB 传输控制块)、UDP;端口绑定、流量控制。
  3. 地址解析逻辑
     
    收到上层发包请求时,查询邻居缓存;无有效条目自动发起 ARP Request / NDP NS 请求;接收应答更新缓存。
Get-NetNeighbor、arp -a 最终都是通过 API 读取tcpip.sys内核内存中的邻居缓存。
  1. 内置过滤与策略
     
    内置 TCP/IP 筛选、IPsec、QoS 流量调度、路径 MTU 发现 PMTUd。

上下游对接

  • 上层:接收 afd.sys 下发的 Socket 数据
  • 下层:将封装好的 IP 报文交付 ndis.sys 转发给网卡驱动

关键内置数据表

  • IPv4 ARP Cache
  • IPv6 Neighbor Cache(NDP)
  • IP 路由表
  • TCP TCB 连接块、UDP 端口控制表

典型关联故障

邻居条目持续Incomplete、路由失效、TCP 重传、IPv6 NDP 异常、ARP 解析异常,根源大多在tcpip.sys处理逻辑。

2、介绍 AFD.SYS 的工作原理

AFD = Ancillary Function Driver(辅助功能驱动)

定位

内核态驱动,位于 Winsock 与 tcpip.sys 中间层,内核 Socket 抽象层。
 
链路:用户态 ws2_32.dll ↔ afd.sys ↔ tcpip.sys

核心工作原理

  1. 用户态应用调用ws2_32.dll的 socket API(socket/connect/send/recv);
  2. ws2_32.dll通过系统调用,把请求转发至内核afd.sys;
  3. AFD 负责管理 Socket 对象、缓冲区、I/O 模型:
    • 维护每个 socket 的收发缓冲区;
    • 实现重叠 IO、IOCP 完成端口、异步 Socket(Windows 高性能网络基石);
    • 处理阻塞 / 非阻塞等待、事件通知;
  4. AFD 剥离上层 Socket 语义,把原始数据交给tcpip.sys完成 TCP/UDP/IP 封装;
  5. 下行报文反向流程:tcpip.sys 向上投递数据 → AFD 放入 Socket 缓冲区 → 通知用户态应用读取。

关键特点

  1. afd.sys 不实现任何 TCP/IP 协议,只做 Socket 会话管理;协议处理全权交给tcpip.sys。
  2. 所有 Windows 网络程序(浏览器、ping、服务器软件)的 Socket 通信必须经过 AFD。
  3. 常见现象:大量连接堆积、端口耗尽、IOCP 卡顿,很多和 AFD 缓冲区、连接资源调度相关。

简易数据流

plaintext
 
 
 
应用程序 → ws2_32.dll → 系统调用 → afd.sys(套接字管理、缓冲区) → tcpip.sys(协议封装) → ndis.sys
 

3、详细介绍 NDIS 接口层(ndis.sys)

NDIS:Network Driver Interface Specification,网络驱动接口规范,实现文件 ndis.sys。

定位

位于tcpip.sys下方、硬件网卡驱动上方,统一抽象层,解耦协议栈与网卡硬件驱动。
作用:让tcpip.sys不需要认识不同厂商千差万别的网卡驱动;网卡驱动也不用适配协议栈。

NDIS 分层模型(自上而下)

  1. 协议驱动:tcpip.sys 属于 NDIS 协议驱动,负责生成 IP 报文;
  2. NDIS 中间驱动(可选):防火墙、VPN、流量采集驱动(Wireshark NDIS 捕获驱动);
  3. 小端口驱动(Miniport Driver):网卡厂商硬件驱动,直接操控网卡。
     
    ndis.sys作为调度中枢,提供标准接口,转发报文。

核心工作原理

下行(主机发包)

tcpip.sys组装好 IP 报文 → 调用 NDIS 标准接口 → ndis.sys转发给网卡小端口驱动 → 网卡转换成以太网帧发送。

上行(接收报文)

网卡收到二层帧 → 小端口驱动上交 ndis.sys → ndis 分发至对应协议驱动tcpip.sys;
 
tcpip.sys识别以太网类型(0x0800 IPv4 / 0x86DD IPv6 / 0x0806 ARP)再进一步处理。

核心能力

  1. 硬件抽象:统一发包、收包、网卡参数配置接口;
  2. 支持报文过滤、多队列 RSS 接收、电源管理;
  3. 提供数据包捕获能力(抓包软件依赖 NDIS);
  4. 维护网卡状态、MAC 地址、MTU、VLAN 配置。

和 ARP/NDP 强相关关键点

ARP、NDP 报文本质是二层以太网帧,帧封装、硬件收发全部依托 NDIS;
 
如果 NDIS 层故障,会出现:协议栈正常,但网卡收不到 / 发不出二层帧,直接造成邻居缓存持续Incomplete。

层级完整汇总(串联全部三者)

plaintext
 
 
 
【用户态】
应用程序
    ↓
ws2_32.dll (Winsock 用户态Socket API)
———————————— 用户态/内核态边界 ———————————
【内核态】
afd.sys    内核Socket管理层(会话、缓冲区、IOCP)
    ↓
tcpip.sys  TCP/IP协议栈(IPv4/IPv6、ARP、NDP、TCP、UDP、路由、邻居缓存)
    ↓
ndis.sys   NDIS驱动抽象接口层
    ↓
网卡小端口驱动
    ↓
物理网卡硬件
 

高频易混淆区分总结

  1. afd.sys:只管 Socket 会话、缓冲区,不处理 IP/TCP 协议
  2. tcpip.sys:真正的 TCP/IP 协议实现,维护 ARP、NDP 邻居缓存
  3. ndis.sys:网卡硬件抽象层,负责二层帧收发,隔离协议栈与硬件

1、如何使用 PowerShell 导出邻居缓存快照

适用:Get-NetNeighbor,用于故障前后留存证据、离线对比分析,管理员权限最佳。

基础导出命令

powershell
 
 
 
# 完整导出全部邻居缓存(IPv4 ARP + IPv6 NDP)为CSV,方便Excel打开
Get-NetNeighbor | Export-Csv -Path "C:\neighbor_snapshot.csv" -Encoding UTF8 -NoTypeInformation
 
参数说明:
  • -Encoding UTF8:防止中文乱码
  • -NoTypeInformation:去除 CSV 首行多余.NET 类型字段

场景化导出脚本

powershell
 
 
 
# 仅导出IPv4 ARP缓存
Get-NetNeighbor -AddressFamily IPv4 | Export-Csv "C:\arp_snapshot.csv" -Encoding UTF8 -NoTypeInformation

# 仅导出IPv6 NDP邻居缓存
Get-NetNeighbor -AddressFamily IPv6 | Export-Csv "C:\ndp_snapshot.csv" -Encoding UTF8 -NoTypeInformation

# 只导出故障网卡(替换InterfaceIndex)
Get-NetNeighbor -InterfaceIndex 3 | Export-Csv "C:\if3_neighbor.csv" -Encoding UTF8 -NoTypeInformation

# 只导出异常状态条目(Incomplete、Unreachable)
Get-NetNeighbor | Where-Object {$_.State -in "Incomplete","Unreachable"} | Export-Csv "C:\error_neighbor.csv" -Encoding UTF8 -NoTypeInformation
 

进阶:带时间戳自动快照(便于持续监控)

powershell
 
 
 
$time=Get-Date -Format "yyyyMMdd_HHmmss"
Get-NetNeighbor | Export-Csv "C:\neighbor_$time.csv" -Encoding UTF8 -NoTypeInformation
 

关键注意事项

  1. 快照仅捕获当前内核缓存,不会主动触发 ARP/NDP 解析;排查前先ping 目标IP再导出。
  2. Permanent静态条目与动态条目会一并导出。
  3. CSV 可离线对比故障前后 MAC 变化,用于定位 ARP/NDP 欺骗。

2、如何使用基础抓包工具分析邻居缓存相关故障

工具以 Wireshark 为例,核心目标:验证 ARP/NDP 报文收发,解释邻居缓存出现Incomplete、MAC 异常的根本原因。

步骤 1:配置抓包过滤器

plaintext
 
 
 
# IPv4 ARP报文过滤
arp

# IPv6 NDP报文过滤(NS/NA/RS/RA)
icmpv6.type == 135 or icmpv6.type == 136

# 同时抓取ARP+NDP
arp or icmpv6.type == 135 or icmpv6.type == 136
 

步骤 2:标准分析流程

  1. 启动抓包 → 清空邻居缓存 Clear-NetNeighborCache
  2. ping 目标IP 主动触发地址解析
  3. 对照 Get-NetNeighbor 状态,结合抓包 4 种判定:
    表格
     
     
     
    抓包现象 结论 邻居缓存表现
    发出 ARP Request / NS,无任何应答 二层转发阻断、目标设备离线、防火墙屏蔽 条目变为Incomplete
    发出请求,收到合法 Reply/NA 解析成功,内核写入缓存 状态变为Connected
    收到多条 Reply/NA,MAC 来回切换 存在 ARP 欺骗 / NDP 欺骗 同一 IP 不断绑定不同 MAC
    未发出 ARP/NS 请求 协议栈判定目标不在同一网段,直接路由,不会产生邻居条目 无对应 IP 条目

实操要点

  1. 抓包网卡必须选择业务网卡;
  2. IPv6 场景重点关注请求节点组播能否正常转发;
  3. 抓包文件(pcapng)可和邻居缓存 CSV 配套留存作为故障证据;
  4. 区分:抓包看线路报文,Get-NetNeighbor 看系统内核最终缓存,两者不一致通常是本机防火墙、安全软件拦截应答报文。

3、如何使用二层交换机排查邻居条目 Incomplete 状态

现象:Windows 主机持续出现Incomplete,代表 ARP Request/NDP NS 发出后收不到应答,需要在交换机侧定位二层链路问题。

Step1 基础信息采集

  1. 在 Windows 主机获取:本机网卡接口索引、本机 IP、目标 IP、目标预期 MAC;
  2. 交换机查询主机接入端口:
plaintext
 
 
 
# 华为/H3C
display mac-address 主机MAC

# 思科
show mac-address-table address <mac>
 

Step2 核心排查步骤

  1. 检查 VLAN 一致性
     
    确认本机端口与目标端口在同一个 VLAN;跨 VLAN 无法直接 ARP/NDP 解析,必然 Incomplete。
  2. 验证广播 / 组播转发能力
  • IPv4:ARP 依靠广播;检查端口是否配置port-isolate端口隔离、ACL 阻断广播报文。
  • IPv6:NDP 依靠组播;确认交换机开启 MLD Snooping,没有过滤请求节点组播。
  1. 端口状态与链路质量
     
    检查端口是否 err-disabled、速率双工不匹配、存在大量 CRC 错误、风暴抑制拦截广播。
plaintext
 
 
 
# 查看端口统计
display interface GigabitEthernet 0/0/1
 
  1. 安全策略核查(最常见诱因)
  • 交换机开启 DAI(动态 ARP 检测),非法 ARP 报文被丢弃;
  • 开启 NDP Snooping、RA Guard,拦截非法 NA 报文;
  • ACL 过滤 ARP、ICMPv6 报文。
  1. 跨设备转发验证
     
    在交换机镜像端口抓包:
  • 能否看到主机发出的 ARP/NS;
  • 目标设备回复的 ARP Reply/NA 能否回传到主机端口。

Step3 分层判定结论

  1. 主机发请求,交换机收到请求,但目标无回复 → 目标终端故障、防火墙拦截;
  2. 主机发请求,目标正常回复,交换机不转发回源端口 → 交换机策略、VLAN、组播问题;
  3. 同一网段其他主机解析正常,仅这台 Windows 异常 → 主机网卡驱动、tcpip.sys、本机防火墙问题。

快速临时验证手段

把故障主机和对端设备直连同一交换机端口,移除中间策略测试,排除链路中间设备拦截。

Get-NetNeighbor 是 PowerShell 中的一个命令,用于检索和显示网络邻居信息,包括 ARP (地址解析协议) 缓存表中的条目。ARP 缓存表存储了 IP 地址与 MAC 地址之间的映射关系,它是网络通信中实现 IP 地址到硬件地址(如 MAC 地址)转换的重要组成部分。

使用 Get-NetNeighbor 命令可以列出本地系统的 ARP 缓存表,其中包含了与本地系统通信过的远程主机的 IP 地址、MAC 地址以及其他相关信息。

这个命令的输出通常包括以下列信息:

  • ifIndex:接口索引,标识与网络接口相关联的唯一编号。

    Get-NetNeighbor 命令用于检索与网络相关的邻居信息,如 IP 地址、MAC 地址等。在你的命令中,似乎你尝试使用 ifIndex 参数来过滤结果,但是该命令并不支持直接使用接口索引来查询邻居信息。

    要根据接口索引查询邻居信息,你可以尝试使用以下命令:

    powershellCopy Code
    Get-NetNeighbor | Where-Object { $_.InterfaceIndex -eq <接口索引> }

    这将返回与指定接口索引相关联的邻居信息。请将 <接口索引> 替换为你要查询的实际接口索引值。

  • IPAddress:远程主机的 IP 地址。
  • LinkLayerAddress:远程主机的 MAC 地址。
  • State:邻居状态,如 Reachable(可达)、Stale(陈旧)等。

使用 Get-NetNeighbor 命令可以帮助诊断网络连接问题,了解本地系统与其他主机之间的通信状态,以及检查 ARP 缓存表中的条目是否正确。

Get-NetNeighbor 命令可以使用多种参数来过滤和定制输出。以下是一些常用的参数:

  1. -AddressFamily:指定地址族,可以是 IPv4 或 IPv6。默认为 IPv4。

  2. -InterfaceIndex:指定网络接口的索引,只显示指定接口的 ARP 缓存。

  3. -IPAddress:指定要检索 ARP 缓存的特定 IP 地址。

    Get-NetNeighbor -IPAddress 192.168.1.1

    ifIndex IPAddress                                          LinkLayerAddress      State       PolicyStore
    ------- ---------                                          ----------------      -----       -----------

  4. -State:指定要检索的邻居状态,例如 Reachable、Stale、Incomplete 等。

    Get-NetNeighbor 命令的 -State 参数支持的值是预定义的邻居状态。这些预定义的邻居状态包括:

    • Reachable:表示邻居是可达的,可以与之通信。
    • Stale:表示邻居条目存在,但已过期,不建议使用。
    • Delay:表示邻居正在等待确认。
    • Probe:表示正在向邻居发送探测以确认其状态。
    • Invalid:表示邻居条目无效。
    • Unreachable:表示无法与邻居通信。
    • Incomplete:表示邻居条目不完整或未知。

    因此,当使用 -State 参数时,你需要指定这些预定义状态值中的一个作为参数。例如:

    Copy Code
    Get-NetNeighbor -State Reachable

    这将列出所有状态为 "Reachable" 的邻居信息。

    Get-NetNeighbor -State Reachable

    ifIndex IPAddress                                          LinkLayerAddress      State       PolicyStore
    ------- ---------                                          ----------------      -----       -----------

    Get-NetNeighbor -State stale

    ifIndex IPAddress                                          LinkLayerAddress      State       PolicyStore
    ------- ---------                                          ----------------      -----       -----------

     
  5. -Protocol:指定要检索的邻居协议类型,例如 ICMP、UDP、TCP 等。

     

  6. -LinkLayerAddress:指定要检索的邻居链路层地址(MAC 地址)。

  7. -PolicyStore:指定要使用的 IP 策略存储。

  8. -AddressFamily:指定要检索的地址族类型,如 IPv4 或 IPv6。

你可以根据需要使用这些参数来过滤和定制 Get-NetNeighbor 命令的输出。例如,如果你只想查看特定网络接口的 ARP 缓存,可以使用 -InterfaceIndex 参数

Get-NetNeighbor 命令的全部参数包括:

  1. -AddressFamily:指定要检索的地址族类型,可以是 IPv4 或 IPv6。

    提供 -AddressFamily 参数来获取邻居信息:

    Copy Code
    Get-NetNeighbor -AddressFamily IPv4

    Get-NetNeighbor -AddressFamily IPv4

    ifIndex IPAddress                                          LinkLayerAddress      State       PolicyStore
    ------- ---------                                          ----------------      -----       -----------

    或者:

    Copy Code
    Get-NetNeighbor -AddressFamily IPv6

     Get-NetNeighbor -AddressFamily IPv6

    ifIndex IPAddress                                          LinkLayerAddress      State       PolicyStore
    ------- ---------                                          ----------------      -----       -----------

    这将使命令只返回与指定地址族类型相关的邻居信息。

  2. -InterfaceIndex:指定要检索的网络接口的索引号码。

  3. -IPAddress:指定要检索的特定 IP 地址。

  4. -State:指定要检索的邻居状态,例如 Reachable、Stale、Incomplete 等。

  5. -LinkLayerAddress:指定要检索的邻居的链路层地址(MAC 地址)。

    查询具有特定链路层地址的邻居信息,你应该先获取目标设备的链路层地址(MAC 地址),然后使用 -LinkLayerAddress 参数来指定该地址进行查询。例如:

    powershellCopy Code
    Get-NetNeighbor -LinkLayerAddress "目标设备的MAC地址"

    这样就可以查询到具有指定链路层地址的邻居信息。

    Get-NetNeighbor -LinkLayerAddress "目标设备的MAC地址"

    ifIndex IPAddress                                          LinkLayerAddress      State       PolicyStore
    ------- ---------                                          ----------------      -----       -----------

  6. -PolicyStore:指定要使用的 IP 策略存储。

  7. -CimSession:指定用于操作的 CIM 会话。

    该参数允许你指定一个或多个 CIM 会话,以执行命令的远程操作。

    你可以通过以下方式提供 -CimSession 参数来获取邻居信息:

    Copy Code
    Get-NetNeighbor -CimSession $yourCimSession

    其中 $yourCimSession 是你已经建立的一个 CIM 会话对象。

  8. -ThrottleLimit:指定并发操作的限制。

    过以下方式提供 -ThrottleLimit 参数来获取邻居信息:

    Copy Code
    Get-NetNeighbor -ThrottleLimit 100

    这将使命令一次性处理最多 100 个邻居信息。你可以根据需要调整这个数字。

    Get-NetNeighbor -ThrottleLimit 100

    ifIndex IPAddress                                          LinkLayerAddress      State       PolicyStore
    ------- ---------                                          ----------------      -----       -----------

这些参数允许用户根据需要过滤和定制 Get-NetNeighbor 命令的输出。例如,你可以使用 -InterfaceIndex 参数指定要检索的网络接口,或使用 -State 参数指定要检索的邻居状态。

 

PowerShell 中可以使用 Get-NetNeighbor 命令来实现类似于 Windows 中 arp -a 的功能,用于显示本地系统的 ARP 缓存表。以下是如何在 PowerShell 中执行类似 arp -a 的操作:

powershellCopy Code
Get-NetNeighbor

这个命令会列出本地系统的 ARP 缓存表,显示每个 IP 地址对应的 MAC 地址以及其他相关信息,类似于 Windows 中 arp -a 命令的输出。

Get-NetNeighbor

索引号(ifIndex)、IP 地址(IPAddress)、链路层地址(LinkLayerAddress)、状态(State)和策略存储(PolicyStore)

ifIndex IPAddress                                          LinkLayerAddress      State       PolicyStore
------- ---------                                          ----------------      -----       -----------

Get-NetNeighbor 返回本地系统的邻居关系表,该表列出了系统中已知的网络邻居的信息,包括其接口索引号(ifIndex)、IP 地址(IPAddress)、链路层地址(LinkLayerAddress)、状态(State)和策略存储(PolicyStore)。

如果你想过滤特定接口的 ARP 缓存表,你可以使用 InterfaceIndex 参数,例如:

powershellCopy Code
Get-NetNeighbor -InterfaceIndex <InterfaceIndex>

其中 <InterfaceIndex> 是你想要过滤的网络接口的索引号。你可以使用 Get-NetAdapter 命令来查看所有网络接口及其对应的索引号。


 

posted @ 2024-04-02 15:14  suv789  阅读(484)  评论(0)    收藏  举报