#1762·nebula

错误: parseV6 读取 ICMPv6 代码字节而不是类型字节,导致 Echo conntrack 失败

作者: herdiyana256创建于 2026年6月14日更新于 2026年7月19日

Reproduction

go
// Run from inside the nebula directory: go run /tmp/poc.go
package main
import (
    "encoding/binary"
    "fmt"
    "GitHub.com/google/gopacket"
    "GitHub.com/google/gopacket/layers"
)
func main() {
    offset := 40
    // Real OS ICMPv6 Echo Request (RFC 4443)
    real := make([]byte, 40+8)
    real[40] = 128  // Type = Echo Request
    real[41] = 0    // Code = 0
    real[44] = 0xCA; real[45] = 0xFE  // Identifier = 0xCAFE
    icmptype := real[offset+1]  // bug: reads Code=0
    fmt.Printf("Real packet → icmptype read=%d, want=128, match=%v\n",
        icmptype, icmptype == uint8(layers.ICMPv6TypeEchoRequest))
    if binary.BigEndian.Uint16(real[44:46]) != 0 && icmptype != 128 {
        fmt.Println(" BUG: Identifier not extracted → RemotePort=0 in conntrack")
    }
    // gopacket test packet (masks the bug)
    ip := layers.IPv6{Version: 6, HopLimit: 64, NextHeader: layers.IPProtocolICMPv6}
    icmp := layers.ICMPv6{TypeCode: layers.ICMPv6TypeEchoRequest}
    echo := layers.ICMPv6Echo{Identifier: 0xCAFE}
    buf := gopacket.NewSerializeBuffer()
    gopacket.SerializeLayers(buf, gopacket.SerializeOptions{}, &ip, &icmp, &echo)
    b := buf.Bytes()
    fmt.Printf("gopacket pkt → byte[40]=%d byte[41]=%d (Type at byte[1]! reversed vs RFC)\n",
        b[40], b[41])
    fmt.Printf("Bug reads byte[41]=%d → matches ICMPv6TypeEchoRequest=%d → test PASSES (false)\n",
        b[41], uint8(layers.ICMPv6TypeEchoRequest))
}

Output:

Real packet → icmptype read=0, want=128, match=false
BUG: Identifier not extracted → RemotePort=0 in conntrack
gopacket pkt → byte[40]=0
…