NUD

1) 在Linux内核中, 将能与自已在硬件层直接通信的外部主机的网络接口设备称为"邻居",用neighbour结构描述, 它包含设备的硬件地址信息.系统中所有的IP包都通过路由所绑定的邻居发送到接口设备上.邻居由邻居表(arp_tbl)来索引, 用邻居的IP地址可查询邻居表中某个设备的邻居.

2) 当邻居接收到要发送的IP包时, 如果邻居的硬件地址还未解析,则将发送包暂时缓冲在arp_queue队列中,然后发送地址解析请求, 这时的状态为未完成状态(NUD_INCOMPLETE).如果1秒内没收到外部设备应答, 邻居将重发arp请求, 如果重发达到3次, 则解析失败, 邻居为失败状态(NUD_FAILED).当收到正确应答, 邻居进入连接状态(NUD_REACHABLE),这时arp_queue中发送包将被创建帧头后发送到设备上.

3) 邻居的IP地址与硬件地址的关系并不是固定的, 系统在接收来自邻居的IP包时,会及时地证实(confirm)邻居的IP地址与硬件地址的映射关系. 同时,邻居表每60秒周期性地扫描邻居(neigh_periodic_timer),
一方面从表中清除那些解析失败和长时间(60秒)未被使用的邻居,另一方面识别那些证实时间已超时的邻居, 将它们从连接状态变为过期状态(NUD_STALE). 当邻居在过期状态发送IP包时,就进入延迟状态(NUD_DELAY), 如果在延迟状态5秒后邻居的硬件地址还是未被证实, 邻居则发送arp请求,这时进入探测状态(NUD_PROBE). 在探测状态, IP包并不进行缓冲, 仍旧使用过期的邻居地址发送,如果探测失败,邻居进入失败状态.

4) 为了缩短IP包到设备的传输路径, 在邻居结构上还引入了帧头缓冲结构(hh_cache).如果邻居建立了帧头缓冲, IP包将通过帧头缓冲的输出发送出去. 当邻居处于连接状态时, 帧头缓冲输出直接指向dev_queue_xmit(), 当处于过期状态时, 帧头缓冲输出切换为邻居的输出口, 对以太网设备来说,邻居的输出口指向neigh_resolve_output(),neigh_connect()和neigh_suspect()两个函数用来进行这种切换.

5) 当系统对外部设备arp的请求应答时, 系统将在arp_tbl中创建该外部设备的邻居,刷新为过期状态.当收到对其它设备的地址解析请求时, 系统将源设备的邻居刷新为过期状态. 当收到单发给自已,但目的IP地址不是自已主机地址的arp请求时, 如果设备允许转发并且该IP在代理表有定义,则将它们缓冲到proxy_queue队列, 等待一段随机的时间作出应答, 防止目标设备拥塞,向对方提供的是自已的设备地址.
在 IPv6 网络中,**NUD(Neighbor Unreachability Detection,邻居不可达检测)** 和 **DAD(Duplicate Address Detection,地址重复检测)** 是 ND(Neighbor Discovery)协议的两个核心机制。它们用于确保 IPv6 地址的唯一性以及链路层可达性的正确维护。 --- ## 一、NUD(Neighbor Unreachability Detection) ### ✅ 功能: - 检测本地链路上的邻居节点是否仍然可达。 - 避免因为邻居节点失效而导致的数据包丢失。 ### 📌 工作原理: 1. 当主机发送数据给邻居时,它会检查邻居缓存的状态: - 如果状态是 `REACHABLE`,则直接发送; - 如果状态是 `STALE`,则发送 NS(Neighbor Solicitation)报文验证可达性; 2. 收到 NA(Neighbor Advertisement)响应后更新状态为 `REACHABLE`; 3. 若多次探测失败,则标记为 `UNREACHABLE`。 ### 🧩 报文类型: - 使用 `NS (Neighbor Solicitation)` 和 `NA (Neighbor Advertisement)` 来完成探测。 --- ## 二、DAD(Duplicate Address Detection) ### ✅ 功能: - 在接口启用 IPv6 地址之前,确保该地址在网络中没有被其他设备使用。 ### 📌 工作原理: 1. 主机发送一个 **Solicited-node 多播 NS 报文**,目标地址为自己要使用的 IPv6 地址; 2. 如果收到任何 NA 响应或其它 NS 请求,说明地址冲突; 3. 如果未收到响应,表示地址可用。 ### 🧩 报文类型: - 使用 `NS (Neighbor Solicitation)` 完成地址冲突检测。 --- ## 三、代码演示:构造 DAD NS 报文(Scapy 示例) 以下是一个使用 Scapy 构造 DAD NS 报文的示例,模拟主机进行地址重复检测的过程: ```python from scapy.all import Ether, IPv6, ICMPv6ND_NS from scapy.sendrecv import sendp def send_dad_ns(interface, src_mac, target_ip): # 构造以太网帧头,目的 MAC 为 solicited-node 多播地址 dst_mac = "33:33:ff:%02x:%02x:%02x" % ( int(target_ip.split(":")[-1][0:2], 16), int(target_ip.split(":")[-1][2:4], 16), int(target_ip.split(":")[-1][4:6], 16) ) ether = Ether(src=src_mac, dst=dst_mac) # IPv6 头部,源地址为 :: (未指定) ipv6 = IPv6(src="::", dst=target_ip) # Neighbor Solicitation 报文 ns = ICMPv6ND_NS(target=target_ip) # 组装完整报文 pkt = ether / ipv6 / ns # 发送报文 sendp(pkt, iface=interface, verbose=False) print(f"[+] Sent DAD NS for {target_ip}") if __name__ == "__main__": interface = "eth0" src_mac = "00:11:22:33:44:55" target_ip = "2001:db8::1" send_dad_ns(interface, src_mac, target_ip) ``` > ⚠️ 注意事项: > - 需要安装 `scapy`:`pip install scapy` > - 需要 root 权限运行(如使用 `sudo`) --- ## 四、代码解释 - `Ether(...)`:构造以太网帧,目的 MAC 是 Solicited-node 多播地址(基于目标 IPv6 地址生成)。 - `IPv6(...)`:源地址为 `::`,表示尚未拥有有效地址。 - `ICMPv6ND_NS(...)`:构造 Neighbor Solicitation 报文,目标地址为待检测的 IPv6 地址。 - `sendp(...)`:通过指定网络接口发送原始以太网帧。 --- ## 五、总结对比 | 功能 | NUD | DAD | |------|-----|-----| | 目的 | 检测邻居是否可达 | 检测地址是否重复 | | 触发时机 | 数据发送前检测邻居状态 | 接口配置 IPv6 地址前 | | 使用报文 | NS + NA | NS | | 是否进入交换机 CPU | ✅ 是(用于维护邻居表) | ✅ 是(用于检测地址冲突) | | 是否需要上送 CPU | ✅ 是 | ✅ 是 | --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值