{"record":{"id":"9f1391dadd303b32","repo":"slackhq/nebula","slug":"unknown-protocol-v","errorCode":null,"errorMessage":"unknown protocol %v","messagePattern":"unknown protocol (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"firewall.go","lineNumber":281,"sourceCode":"\t}\n\n\tswitch proto {\n\tcase iputil.IPProtocolTCP:\n\t\tfp = ft.TCP\n\tcase iputil.IPProtocolUDP:\n\t\tfp = ft.UDP\n\tcase iputil.IPProtocolICMP, iputil.IPProtocolICMPv6:\n\t\t//ICMP traffic doesn't have ports, so we always coerce to \"any\", even if a value is provided\n\t\tif startPort != firewall.PortAny {\n\t\t\tf.l.Warn(\"ignoring port specification for ICMP firewall rule\", \"startPort\", startPort)\n\t\t}\n\t\tstartPort = firewall.PortAny\n\t\tendPort = firewall.PortAny\n\t\tfp = ft.ICMP\n\tcase firewall.ProtoAny:\n\t\tfp = ft.AnyProto\n\tdefault:\n\t\treturn fmt.Errorf(\"unknown protocol %v\", proto)\n\t}\n\n\t// We need this rule string because we generate a hash. Removing this will break firewall reload.\n\truleString := fmt.Sprintf(\n\t\t\"incoming: %v, proto: %v, startPort: %v, endPort: %v, groups: %v, host: %v, ip: %v, localIp: %v, caName: %v, caSha: %s\",\n\t\tincoming, proto, startPort, endPort, groups, host, cidr, localCidr, caName, caSha,\n\t)\n\tf.rules += ruleString + \"\\n\"\n\n\tdirection := \"incoming\"\n\tif !incoming {\n\t\tdirection = \"outgoing\"\n\t}\n\tf.l.Info(\"Firewall rule added\",\n\t\t\"firewallRule\", m{\"direction\": direction, \"proto\": proto, \"startPort\": startPort, \"endPort\": endPort, \"groups\": groups, \"host\": host, \"cidr\": cidr, \"localCidr\": localCidr, \"caName\": caName, \"caSha\": caSha},\n\t)\n\n\treturn fp.addRule(f, startPort, endPort, groups, host, cidr, localCidr, caName, caSha)","sourceCodeStart":263,"sourceCodeEnd":299,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/firewall.go#L263-L299","documentation":"AddRule on the firewall validates the protocol of a new rule. Only tcp, udp, icmp, and any are supported; anything else falls through to the default case and returns this error. The rule is not installed when this occurs.","triggerScenarios":"Calling firewall.AddRule with a FirewallProtocol value other than ProtoTCP, ProtoUDP, ProtoICMP, or ProtoAny (e.g. an unvalidated value read from config or a zero-value custom constant).","commonSituations":"Typo in a firewall rule's \"proto\" field in the Nebula config YAML (e.g. \"http\" instead of \"tcp\"), programmatic rule construction with a wrong constant, or parsing raw user input into a proto value without validation.","solutions":["Use one of the supported protocols: tcp, udp, icmp, or any.","If you need a rule that matches all traffic, use ProtoAny instead of an invented value.","Normalize/validate the proto string from config before constructing the rule (config parsing normally lowercases it via convertRule)."],"exampleFix":"// before\nfw.AddRule(true, firewall.Proto(\"http\"), 0, 443, []string{\"app\"}, \"\", nil, nil, nil, \"\", \"\")\n// after\nfw.AddRule(true, firewall.ProtoTCP, 0, 443, []string{\"app\"}, \"\", nil, nil, nil, \"\", \"\")","handlingStrategy":"validation","validationCode":"var validProtos = map[firewall.Protocol]bool{\n    firewall.ProtoTCP: true, firewall.ProtoUDP: true,\n    firewall.ProtoICMP: true, firewall.ProtoAny: true,\n}\nif !validProtos[proto] {\n    return fmt.Errorf(\"unsupported proto %q; use tcp, udp, icmp, or any\", proto)\n}\nerr := fw.AddRule(true, proto, 0, 443, groups, \"\", nil, nil, nil, \"\", \"\")","typeGuard":"func isSupportedProto(p firewall.Protocol) bool {\n    switch p {\n    case firewall.ProtoTCP, firewall.ProtoUDP, firewall.ProtoICMP, firewall.ProtoAny:\n        return true\n    }\n    return false\n}","tryCatchPattern":"if err := fw.AddRule(true, proto, start, end, groups, \"\", nil, nil, nil, \"\", \"\"); err != nil {\n    if strings.Contains(err.Error(), \"unknown protocol\") {\n        log.Fatalf(\"proto %v not supported; use tcp/udp/icmp/any\", proto)\n    }\n    return err\n}","preventionTips":["Only use the library's exported proto constants, never raw strings cast to Protocol.","Normalize config proto values to lowercase before mapping them to constants.","Add a config lint step that checks proto values against the supported set."],"tags":["firewall","configuration","validation"],"backgroundTag":"invalid-protocol-value","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"}