slackhq/nebula · error

ErrUnknownNetworkType

ErrUnknownNetworkType

Error message

unknown network type

What it means

ErrUnknownNetworkType in firewall.go is returned by Firewall.Drop when the packet's network type (the switch over conn/network classification) matches none of the handled cases. The code labels it 'should never happen', so it indicates an internal classification bug or an unexpected packet category reaching the firewall rather than a policy decision.

Source

Thrown at firewall.go:418

		if warning := r.sanity(); warning != nil {
			l.Warn("firewall rule sanity check",
				"table", table,
				"rule", i,
				"warning", warning,
			)
		}

		err = fw.AddRule(inbound, proto, startPort, endPort, r.Groups, r.Host, r.Cidr, r.LocalCidr, r.CAName, r.CASha)
		if err != nil {
			return fmt.Errorf("%s rule #%v; `%s`", table, i, err)
		}
	}

	return nil
}

var ErrUnknownNetworkType = errors.New("unknown network type")
var ErrPeerRejected = errors.New("remote address is not within a network that we handle")
var ErrInvalidRemoteIP = errors.New("remote address is not in remote certificate networks")
var ErrInvalidLocalIP = errors.New("local address is not in list of handled local addresses")
var ErrNoMatchingRule = errors.New("no matching rule in firewall table")

// Drop returns an error if the packet should be dropped, explaining why. It
// returns nil if the packet should not be dropped.
func (f *Firewall) Drop(fp firewall.Packet, incoming bool, h *HostInfo, caPool *cert.CAPool, localCache firewall.ConntrackCache) error {
	// Make sure remote address matches nebula certificate, and determine how to treat it
	if h.networks == nil {
		// Simple case: Certificate has one address and no unsafe networks
		if h.vpnAddrs[0] != fp.RemoteAddr {
			f.metrics(incoming).droppedRemoteAddr.Inc(1)
			return ErrInvalidRemoteIP
		}
	} else {
		nwType, ok := h.networks.Lookup(fp.RemoteAddr)
		if !ok {

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Log the offending packet's network type at the Drop site to identify the unhandled classification.
  2. Update the switch in Drop to handle the new network type explicitly.
  3. Fix the upstream classifier so only known network types reach the firewall.
  4. Check for recent custom modifications to firewall or packet-parsing code that introduced the type.

Example fix

// before
default:
    f.metrics(incoming).droppedRemoteAddr.Inc(1)
    return ErrUnknownNetworkType

// after
case cert.Curve_WhateverNewType: // handle the missing case explicitly
    return f.checkRule(...)
default:
    f.metrics(incoming).droppedRemoteAddr.Inc(1)
    return fmt.Errorf("unknown network type %v: %w", networkType, ErrUnknownNetworkType)
Defensive patterns

Strategy: try-catch

Validate before calling

// before feeding packets to the firewall, ensure the classification is known
switch pkt.NetworkType() {
case ipv4Type, ipv6Type:
    // ok
default:
    return fmt.Errorf("unclassifiable packet, refusing to pass to firewall")
}

Type guard

func isKnownNetworkType(t NetworkType) bool {
    return t == IPv4 || t == IPv6
}

Try / catch

if err := f.Drop(pkt, incoming); err != nil {
    if errors.Is(err, ErrUnknownNetworkType) {
        log.Printf("BUG: unhandled network type %v; dropping and reporting", pkt.NetworkType())
        reportBug(pkt)
        return // drop is safe; do not retry
    }
    // other firewall errors (no matching rule, invalid IP) handled separately
}

Prevention

When it happens

Trigger: Drop() called with a packet whose network type falls into the default branch at firewall.go:450 — i.e. a classification outside IPv4/IPv6 (or the handled host/network cases) reaches the switch.

Common situations: Bugs in tunnel/routing code feeding unclassified packets to the firewall; custom patches adding new network types without updating Drop's switch; corrupted packet metadata from unsafe memory handling.

Related errors


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/447419e63d5ad0e6. Report an issue: GitHub.