{"record":{"id":"8e48bba693fb248f","repo":"slackhq/nebula","slug":"invalid-vpn-addr-for-v1-handlehostquery","errorCode":null,"errorMessage":"invalid vpn addr for v1 handleHostQuery","messagePattern":"invalid vpn addr for v1 handleHostQuery","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lighthouse.go","lineNumber":1222,"sourceCode":"\t\t} else {\n\t\t\tcrt := targetHI.GetCert().Certificate\n\t\t\tuseVersion = crt.Version()\n\t\t\t// we can only retarget if we have a hostinfo\n\t\t\tnewDest, ok := findNetworkUnion(crt.Networks(), fromVpnAddrs)\n\t\t\tif ok {\n\t\t\t\twhereToPunch = newDest\n\t\t\t} else {\n\t\t\t\tif lhh.l.Enabled(context.Background(), slog.LevelDebug) {\n\t\t\t\t\tlhh.l.Debug(\"unable to punch to host, no addresses in common\",\n\t\t\t\t\t\t\"to\", crt.Networks(),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif useVersion == cert.Version1 {\n\t\t\tif !whereToPunch.Is4() {\n\t\t\t\treturn 0, fmt.Errorf(\"invalid vpn addr for v1 handleHostQuery\")\n\t\t\t}\n\t\t\tb := whereToPunch.As4()\n\t\t\tn.Details.OldVpnAddr = binary.BigEndian.Uint32(b[:])\n\t\t} else if useVersion == cert.Version2 {\n\t\t\tn.Details.VpnAddr = netAddrToProtoAddr(whereToPunch)\n\t\t} else {\n\t\t\treturn 0, errors.New(\"unsupported version\")\n\t\t}\n\t\tlhh.coalesceAnswers(useVersion, c, n)\n\n\t\treturn n.MarshalTo(lhh.pb)\n\t})\n\n\tif !found {\n\t\treturn\n\t}\n\n\tif err != nil {","sourceCodeStart":1204,"sourceCodeEnd":1240,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/lighthouse.go#L1204-L1240","documentation":"In handleHostQuery, when the selected certificate encoding version is cert.Version1, the queried VPN address must be an IPv4 address (Is4), because the v1 wire format stores only a 32-bit OldVpnAddr. An IPv6 or non-v4 address cannot be encoded for v1 recipients.","triggerScenarios":"A host query answer targets a dual-stack/v6 VPN address while the requesting peer (or reply encoding) uses cert.Version1, so whereToPunch.Is4() fails.","commonSituations":"IPv6-enabled VPN network (v2 certs) with legacy v1-cert lighthouses/peers; lighthouse replying to an old node about a v6 address; mixed cert-version upgrade.","solutions":["Upgrade all nodes/certs to Version2 so v6 VPN addresses can be encoded","Restrict VPN addresses to IPv4 while v1 peers remain in the network","Filter the host query response to only v4 targets when answering v1 peers"],"exampleFix":"// before\nif useVersion == cert.Version1 {\n    if !whereToPunch.Is4() {\n        return 0, fmt.Errorf(\"invalid vpn addr for v1 handleHostQuery\")\n    }\n// after: prefer v2 when the target is not v4\nif !whereToPunch.Is4() && canUseV2 {\n    useVersion = cert.Version2\n}","handlingStrategy":"type-guard","validationCode":"if useVersion == cert.Version1 && !whereToPunch.Is4() {\n    // skip or convert target before responding\n}","typeGuard":"func v1SafeAddr(a netip.Addr) bool { return a.Is4() }","tryCatchPattern":null,"preventionTips":["Upgrade the whole network to cert v2 before enabling IPv6 VPN addresses","Don't assign v6 VPN addresses to peers reachable only via v1 certs","Test lighthouse queries with mixed v1/v2 certs in staging"],"tags":["lighthouse","ipv6","cert-version"],"backgroundTag":"ipv6-not-supported-in-v1","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"}