{"record":{"id":"ec498785873f1fe5","repo":"slackhq/nebula","slug":"errunknownipversion","errorCode":"ErrUnknownIPVersion","errorMessage":"packet is an unknown ip version","messagePattern":"packet is an unknown ip version","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"outside.go","lineNumber":312,"sourceCode":"\t\t\t\t)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\thostinfo.logger(f.l).Info(\"Host roamed to new udp ip/port.\",\n\t\t\t\"udpAddr\", curRemote,\n\t\t\t\"newAddr\", via.UdpAddr,\n\t\t)\n\t\thostinfo.lastRoam = time.Now()\n\t\thostinfo.lastRoamRemote = curRemote\n\t\thostinfo.SetRemote(via.UdpAddr)\n\t}\n\n}\n\nvar (\n\tErrPacketTooShort          = errors.New(\"packet is too short\")\n\tErrUnknownIPVersion        = errors.New(\"packet is an unknown ip version\")\n\tErrIPv4InvalidHeaderLength = errors.New(\"invalid ipv4 header length\")\n\tErrIPv4PacketTooShort      = errors.New(\"ipv4 packet is too short\")\n\tErrIPv6PacketTooShort      = errors.New(\"ipv6 packet is too short\")\n)\n\n// newPacket validates and parses the interesting bits for the firewall out of the ip and sub protocol headers\nfunc newPacket(data []byte, incoming bool, fp *firewall.ParsedPacket) error {\n\t// fp is reused across packets; reset the parse byproducts so an early-error return cannot\n\t// leak the previous packet's offsets.\n\tfp.IPHdrLen = 0\n\tfp.FragAny = false\n\tif len(data) < 1 {\n\t\treturn ErrPacketTooShort\n\t}\n\n\tversion := int((data[0] >> 4) & 0x0f)\n\tswitch version {\n\tcase ipv4.Version:","sourceCodeStart":294,"sourceCodeEnd":330,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/outside.go#L294-L330","documentation":"newPacket inspects the IP version nibble of each received packet so the firewall can parse IPv4 or IPv6 headers. Any version other than 4 or 6 is rejected with ErrUnknownIPVersion because nebula cannot compute firewall rules for unknown protocols.","triggerScenarios":"newPacket is called with data whose first nibble is neither 0x4 nor 0x6 (outside.go:335 return path); Test_newPacket feeds a zero-filled packet to trigger it.","commonSituations":"Non-IP traffic or corrupted packets reaching the tunnel interface, misconfigured overlay networks injecting raw frames, bit-flips or truncation corrupting the IP header.","solutions":["Verify only IPv4/IPv6 traffic is routed into the nebula interface.","Check overlay/underlay routing for misrouted non-IP frames.","Capture the packet and inspect the first byte's version nibble."],"exampleFix":"// before: raw frame sent into tunnel\niface.Write(ethernetFrame)\n// after\nif ipPacket := extractIP(frame); ipPacket != nil { iface.Write(ipPacket) }","handlingStrategy":"validation","validationCode":"if len(data) > 0 && data[0]>>4 != 4 && data[0]>>4 != 6 {\n    return errors.New(\"not an IPv4/IPv6 packet\")\n}","typeGuard":null,"tryCatchPattern":"if errors.Is(err, outside.ErrUnknownIPVersion) {\n    // drop packet and log the raw first byte for diagnosis\n}","preventionTips":["Ensure only IP traffic is routed into the tunnel interface.","Validate overlay routing rules to keep raw frames out.","Alert on unknown-version spikes as a corruption signal."],"tags":["packet-parsing","ip-version","network"],"backgroundTag":"unknown-ip-version","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}