错误: parseV6 读取 ICMPv6 代码字节而不是类型字节,导致 Echo conntrack 失败
作者: herdiyana256创建于 2026年6月14日更新于 2026年7月19日
Reproduction
// 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
…内容来源: slackhq/nebula