slackhq/nebula · warning
ErrIPv6PacketTooShort
ErrIPv6PacketTooShort
Error message
ipv6 packet is too short
What it means
ErrIPv6PacketTooShort is returned by newPacket (via parseV6) when an inbound packet cannot be parsed as IPv6 because the buffer is shorter than the fixed IPv6 header (ipv6.HeaderLen, 40 bytes) or because iputil.IPv6FindUpperProtocol cannot walk the extension headers to find an upper-layer protocol. It guards the firewall parser from indexing out of bounds on truncated or malformed packets.
Source
Thrown at outside.go:315
}
hostinfo.logger(f.l).Info("Host roamed to new udp ip/port.",
"udpAddr", curRemote,
"newAddr", via.UdpAddr,
)
hostinfo.lastRoam = time.Now()
hostinfo.lastRoamRemote = curRemote
hostinfo.SetRemote(via.UdpAddr)
}
}
var (
ErrPacketTooShort = errors.New("packet is too short")
ErrUnknownIPVersion = errors.New("packet is an unknown ip version")
ErrIPv4InvalidHeaderLength = errors.New("invalid ipv4 header length")
ErrIPv4PacketTooShort = errors.New("ipv4 packet is too short")
ErrIPv6PacketTooShort = errors.New("ipv6 packet is too short")
)
// newPacket validates and parses the interesting bits for the firewall out of the ip and sub protocol headers
func newPacket(data []byte, incoming bool, fp *firewall.ParsedPacket) error {
// fp is reused across packets; reset the parse byproducts so an early-error return cannot
// leak the previous packet's offsets.
fp.IPHdrLen = 0
fp.FragAny = false
if len(data) < 1 {
return ErrPacketTooShort
}
version := int((data[0] >> 4) & 0x0f)
switch version {
case ipv4.Version:
return parseV4(data, incoming, fp)
case ipv6.Version:
return parseV6(data, incoming, fp)View on GitHub (pinned to dd8f660c0a)
Solutions
- Log the peer and actual len(data) to identify the truncating source (NIC offload, tunnel, or peer).
- Verify MTU settings end-to-end (host NIC, VPN/tunnel overhead, VPN preferred MTU) and reduce MTU if fragmentation/overflow is suspected.
- Disable or update GRO/GSO/LRO offload on the receiving interface if truncation correlates with offloaded traffic.
- Ensure the caller passes the full received buffer to newPacket instead of a truncated slice.
- If malicious input is the cause, treat as expected: the error is a safe rejection and the packet should be dropped.
Example fix
// before: blindly parse whatever was read
n, _ := conn.Read(buf)
err := newPacket(buf[:n], incoming, fp)
// after: pre-validate minimum IPv6 header length
n, _ := conn.Read(buf)
if n >= ipv6.HeaderLen && buf[0]>>4 == 6 {
err = newPacket(buf[:n], incoming, fp)
} else {
// drop / count as malformed
} Defensive patterns
Strategy: validation
Validate before calling
func isParseableIPv6(pkt []byte) bool {
return len(pkt) >= ipv6.HeaderLen && pkt[0]>>4 == 6
}
if !isParseableIPv6(buf[:n]) {
stats.MalformedV6++
return nil // drop before calling newPacket
} Type guard
func ipv6HeaderPresent(b []byte) bool {
if len(b) < ipv6.HeaderLen {
return false
}
return b[0]>>4 == 6
} Try / catch
if err := newPacket(data, incoming, fp); err != nil {
if errors.Is(err, ErrIPv6PacketTooShort) {
log.Debug("dropping short ipv6 packet", "len", len(data), "src", src)
return nil // safe rejection
}
return err
} Prevention
- Validate minimum header length and IP version before handing buffers to the parser.
- Audit MTU and offload (GRO/GSO/LRO) settings on receiving interfaces.
- Never slice packet buffers by assumed header sizes; use the actual read length.
- Count short-packet rejections per peer to detect hostile or buggy senders early.
When it happens
Trigger: parseV6 receives data with len(data) < ipv6.HeaderLen (outside.go:341), or IPv6FindUpperProtocol fails to locate an upper protocol / walk extension headers within the buffer (outside.go:357). Directly triggered by any call path that feeds a truncated, corrupted, or deliberately malformed IPv6 datagram into newPacket.
Common situations: MTU mismatches or offloads (TSO/GSO/LRO) delivering partial frames, buggy NIC or tunnel software truncating packets, hostile peers sending malformed packets to probe the firewall, userspace readers that slice a packet buffer too short before calling the parser.
Related errors
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/4d8235152603f4e9.
Report an issue: GitHub.