You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP实现ICMPv6 Solicitation Request无Neighbor Advertisement回复问题

ICMPv6邻居请求无回复问题排查与修复

以下是用于发送ICMPv6邻居请求(Neighbor Solicitation)的PHP脚本:

$socket = socket_create(AF_INET6, SOCK_RAW, 58);
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec' => 1, 'usec' => 0));
$type = chr(135);
$code = chr(0);
$check = chr(0);
$check .= chr(0);

$reserverd = chr(0) . chr(0) . chr(0) . chr(0);
$distMul = "ff02::1:ff26:13dc"; // 请求节点多播地址
$target = "fe80::3b40:f032:5726:13dc";
$id = inet_pton($target);
socket_set_option($socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 255);
$package = $type . $code . $check . $reserverd . $id;
socket_connect($socket, $distMul, 0);
socket_send($socket, $package, strlen($package), 0);
$str = socket_read($socket, 2048);
socket_close($socket);

Wireshark抓包结果:
Wireshark抓包截图

问题:该请求始终无法收到Type 136的邻居通告(Neighbor Advertisement)回复。

核心问题与修复方案

  • 必须计算ICMPv6校验和:当前直接将校验和设为全0,ICMPv6要求校验和必须基于伪头部(IPv6头部部分字段)+ ICMPv6报文计算,接收方会直接丢弃校验和无效的包。需实现符合RFC 2460标准的校验和计算逻辑。
  • 添加源链路层地址选项:邻居请求报文必须携带源链路层地址选项(Type 1),格式为Type(1字节) + Length(1字节,单位为8字节块) + 6字节MAC地址,否则目标节点无法确定回复的链路层地址,不会发送NA包。
  • 修正多播跳数:本地链路的多播跳数应设为1而非255,邻居请求是本地链路范围内的操作,跳数设为1符合协议规范,避免跨网段传输的不必要问题。
  • 确认运行权限:RAW socket需要root/管理员权限才能创建,确保脚本以足够权限运行,否则会存在发送/接收限制。

修正后的关键代码示例

  1. ICMPv6校验和计算函数:
function calculate_icmpv6_checksum($pseudo_header, $icmp_packet) {
    $data = $pseudo_header . $icmp_packet;
    $len = strlen($data);
    $sum = 0;
    for ($i = 0; $i < $len; $i += 2) {
        $sum += ord($data[$i]) << 8;
        if ($i+1 < $len) {
            $sum += ord($data[$i+1]);
        }
    }
    $sum = ($sum >> 16) + ($sum & 0xffff);
    $sum += ($sum >> 16);
    return pack('n', ~$sum & 0xffff);
}
  1. 添加源链路层地址选项:
// 替换为你的网卡MAC地址,格式如"00:11:22:33:44:55"
$mac = "00:11:22:33:44:55";
$mac_bytes = pack('H*', str_replace(':', '', $mac));
// 构造源链路层地址选项
$source_link_option = chr(1) . chr(1) . $mac_bytes;
// 拼接完整ICMP报文
$package = $type . $code . $check . $reserverd . $id . $source_link_option;
  1. 修正多播跳数设置:
socket_set_option($socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 1);

内容的提问来源于stack exchange,提问作者anru

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 17:33:21