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

  1. Log the peer and actual len(data) to identify the truncating source (NIC offload, tunnel, or peer).
  2. Verify MTU settings end-to-end (host NIC, VPN/tunnel overhead, VPN preferred MTU) and reduce MTU if fragmentation/overflow is suspected.
  3. Disable or update GRO/GSO/LRO offload on the receiving interface if truncation correlates with offloaded traffic.
  4. Ensure the caller passes the full received buffer to newPacket instead of a truncated slice.
  5. 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

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.