{"record":{"id":"ffb662e3b121ae7c","repo":"netbirdio/netbird","slug":"skip-tls-verify-is-not-supported-for-l4-services","errorCode":null,"errorMessage":"skip_tls_verify is not supported for L4 services","messagePattern":"skip_tls_verify is not supported for L4 services","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"management/internals/modules/reverseproxy/service/service.go","lineNumber":1066,"sourceCode":"\t\t\treturn errors.New(\"target host is required for subnet targets\")\n\t\t}\n\tcase TargetTypeCluster:\n\t\t// target_id carries the cluster address; the proxy resolves\n\t\t// the upstream at request time.\n\tdefault:\n\t\treturn fmt.Errorf(\"invalid target_type %q for L4 service\", target.TargetType)\n\t}\n\tif target.Path != nil && *target.Path != \"\" && *target.Path != \"/\" {\n\t\treturn errors.New(\"path is not supported for L4 services\")\n\t}\n\tif target.Options.SessionIdleTimeout < 0 {\n\t\treturn errors.New(\"session_idle_timeout must be positive for L4 services\")\n\t}\n\tif target.Options.RequestTimeout < 0 {\n\t\treturn errors.New(\"request_timeout must be positive for L4 services\")\n\t}\n\tif target.Options.SkipTLSVerify {\n\t\treturn errors.New(\"skip_tls_verify is not supported for L4 services\")\n\t}\n\tif target.Options.PathRewrite != \"\" {\n\t\treturn errors.New(\"path_rewrite is not supported for L4 services\")\n\t}\n\tif len(target.Options.CustomHeaders) > 0 {\n\t\treturn errors.New(\"custom_headers is not supported for L4 services\")\n\t}\n\treturn nil\n}\n\n// Service mode constants.\nconst (\n\tModeHTTP = \"http\"\n\tModeTCP  = \"tcp\"\n\tModeUDP  = \"udp\"\n\tModeTLS  = \"tls\"\n)\n","sourceCodeStart":1048,"sourceCodeEnd":1084,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/management/internals/modules/reverseproxy/service/service.go#L1048-L1084","documentation":"Returned by validateL4Target when target.options.skip_tls_verify is true. That flag instructs the HTTP proxy's TLS client to not verify the upstream certificate when the proxy itself speaks HTTPS to the backend; in tcp/udp/tls modes the proxy never terminates or originates TLS - it relays encrypted bytes - so there is no handshake it could skip verification on. Self-signed upstream certificates are therefore irrelevant (and safe) for L4 services.","triggerScenarios":"An L4 target whose options block carries skip_tls_verify: true, typically copied from an HTTPS HTTP-mode target that had a self-signed cert; flipping a service from http (https target_protocol) to tls passthrough without clearing the flag.","commonSituations":"'My upstream uses a self-signed cert, better set skip_tls_verify' applied to a passthrough where the client, not the proxy, validates the cert. Template reuse across modes. Tooling that copies the whole options block verbatim.","solutions":["Set skip_tls_verify to false (or omit it) on the L4 target - end-to-end TLS means clients do the verifying.","If the proxy must terminate TLS and skip upstream verification, use mode http with target_protocol https.","Install the CA on the connecting clients instead if the passthrough cert is private."],"exampleFix":"// before\n{ \"mode\": \"tls\", \"targets\": [ { \"target_id\": \"peer-a\", \"port\": 443,\n  \"options\": { \"skip_tls_verify\": true } } ] }\n\n// after\n{ \"mode\": \"tls\", \"targets\": [ { \"target_id\": \"peer-a\", \"port\": 443 } ] }","handlingStrategy":"validation","validationCode":"func checkL4NoSkipTLSVerify(o TargetOptions) error {\n\tif o.SkipTLSVerify {\n\t\treturn errors.New(\"skip_tls_verify is http-only; remove it from L4 targets\")\n\t}\n\treturn nil\n}","typeGuard":"func isL4SkipTLSVerifyClean(o TargetOptions) bool {\n\treturn !o.SkipTLSVerify\n}","tryCatchPattern":"if err := svc.Validate(); err != nil {\n\tif strings.Contains(err.Error(), \"skip_tls_verify is not supported for L4\") {\n\t\treturn respondBadRequest(errors.New(\"passthrough TLS is end-to-end; clients verify the cert\"))\n\t}\n\treturn respondBadRequest(err)\n}","preventionTips":["Understand which side terminates TLS: proxy (http mode) vs client (tls/tcp passthrough).","Only copy skip_tls_verify onto targets whose protocol the proxy itself speaks.","For private CAs on passthrough, distribute the CA to clients instead of touching this flag."],"tags":["netbird","reverse-proxy","validation","l4","tls","options","go"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}